root / cmd.c @ 2d72c572
History | View | Annotate | Download (10.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 | e3aff4f6 | aliguori | * along with this program; if not, write the Free Software Foundation,
|
16 | e3aff4f6 | aliguori | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
17 | e3aff4f6 | aliguori | */
|
18 | e3aff4f6 | aliguori | |
19 | e3aff4f6 | aliguori | #include <stdio.h> |
20 | e3aff4f6 | aliguori | #include <stdlib.h> |
21 | e3aff4f6 | aliguori | #include <string.h> |
22 | e3aff4f6 | aliguori | #include <ctype.h> |
23 | e3aff4f6 | aliguori | #include <errno.h> |
24 | e3aff4f6 | aliguori | |
25 | e3aff4f6 | aliguori | #include "cmd.h" |
26 | e3aff4f6 | aliguori | |
27 | e3aff4f6 | aliguori | #define _(x) x /* not gettext support yet */ |
28 | e3aff4f6 | aliguori | |
29 | e3aff4f6 | aliguori | extern int optind; |
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 | e3aff4f6 | aliguori | void
|
154 | e3aff4f6 | aliguori | command_loop(void)
|
155 | e3aff4f6 | aliguori | { |
156 | e3aff4f6 | aliguori | int c, i, j = 0, done = 0; |
157 | e3aff4f6 | aliguori | char *input;
|
158 | e3aff4f6 | aliguori | char **v;
|
159 | e3aff4f6 | aliguori | const cmdinfo_t *ct;
|
160 | e3aff4f6 | aliguori | |
161 | e3aff4f6 | aliguori | for (i = 0; !done && i < ncmdline; i++) { |
162 | e3aff4f6 | aliguori | input = strdup(cmdline[i]); |
163 | e3aff4f6 | aliguori | if (!input) {
|
164 | e3aff4f6 | aliguori | fprintf(stderr, |
165 | e3aff4f6 | aliguori | _("cannot strdup command '%s': %s\n"),
|
166 | e3aff4f6 | aliguori | cmdline[i], strerror(errno)); |
167 | e3aff4f6 | aliguori | exit(1);
|
168 | e3aff4f6 | aliguori | } |
169 | e3aff4f6 | aliguori | v = breakline(input, &c); |
170 | e3aff4f6 | aliguori | if (c) {
|
171 | e3aff4f6 | aliguori | ct = find_command(v[0]);
|
172 | e3aff4f6 | aliguori | if (ct) {
|
173 | e3aff4f6 | aliguori | if (ct->flags & CMD_FLAG_GLOBAL)
|
174 | e3aff4f6 | aliguori | done = command(ct, c, v); |
175 | e3aff4f6 | aliguori | else {
|
176 | e3aff4f6 | aliguori | j = 0;
|
177 | e3aff4f6 | aliguori | while (!done && (j = args_command(j)))
|
178 | e3aff4f6 | aliguori | done = command(ct, c, v); |
179 | e3aff4f6 | aliguori | } |
180 | e3aff4f6 | aliguori | } else
|
181 | e3aff4f6 | aliguori | fprintf(stderr, _("command \"%s\" not found\n"),
|
182 | e3aff4f6 | aliguori | v[0]);
|
183 | e3aff4f6 | aliguori | } |
184 | e3aff4f6 | aliguori | doneline(input, v); |
185 | e3aff4f6 | aliguori | } |
186 | e3aff4f6 | aliguori | if (cmdline) {
|
187 | e3aff4f6 | aliguori | free(cmdline); |
188 | e3aff4f6 | aliguori | return;
|
189 | e3aff4f6 | aliguori | } |
190 | e3aff4f6 | aliguori | while (!done) {
|
191 | e3aff4f6 | aliguori | if ((input = fetchline()) == NULL) |
192 | e3aff4f6 | aliguori | break;
|
193 | e3aff4f6 | aliguori | v = breakline(input, &c); |
194 | e3aff4f6 | aliguori | if (c) {
|
195 | e3aff4f6 | aliguori | ct = find_command(v[0]);
|
196 | e3aff4f6 | aliguori | if (ct)
|
197 | e3aff4f6 | aliguori | done = command(ct, c, v); |
198 | e3aff4f6 | aliguori | else
|
199 | e3aff4f6 | aliguori | fprintf(stderr, _("command \"%s\" not found\n"),
|
200 | e3aff4f6 | aliguori | v[0]);
|
201 | e3aff4f6 | aliguori | } |
202 | e3aff4f6 | aliguori | doneline(input, v); |
203 | e3aff4f6 | aliguori | } |
204 | e3aff4f6 | aliguori | } |
205 | e3aff4f6 | aliguori | |
206 | e3aff4f6 | aliguori | /* from libxcmd/input.c */
|
207 | e3aff4f6 | aliguori | |
208 | e3aff4f6 | aliguori | #if defined(ENABLE_READLINE)
|
209 | e3aff4f6 | aliguori | # include <readline/history.h> |
210 | e3aff4f6 | aliguori | # include <readline/readline.h> |
211 | e3aff4f6 | aliguori | #elif defined(ENABLE_EDITLINE)
|
212 | e3aff4f6 | aliguori | # include <histedit.h> |
213 | e3aff4f6 | aliguori | #endif
|
214 | e3aff4f6 | aliguori | |
215 | e3aff4f6 | aliguori | static char * |
216 | e3aff4f6 | aliguori | get_prompt(void)
|
217 | e3aff4f6 | aliguori | { |
218 | e3aff4f6 | aliguori | static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; |
219 | e3aff4f6 | aliguori | |
220 | e3aff4f6 | aliguori | if (!prompt[0]) |
221 | e3aff4f6 | aliguori | snprintf(prompt, sizeof(prompt), "%s> ", progname); |
222 | e3aff4f6 | aliguori | return prompt;
|
223 | e3aff4f6 | aliguori | } |
224 | e3aff4f6 | aliguori | |
225 | e3aff4f6 | aliguori | #if defined(ENABLE_READLINE)
|
226 | e3aff4f6 | aliguori | char *
|
227 | e3aff4f6 | aliguori | fetchline(void)
|
228 | e3aff4f6 | aliguori | { |
229 | e3aff4f6 | aliguori | char *line;
|
230 | e3aff4f6 | aliguori | |
231 | e3aff4f6 | aliguori | line = readline(get_prompt()); |
232 | e3aff4f6 | aliguori | if (line && *line)
|
233 | e3aff4f6 | aliguori | add_history(line); |
234 | e3aff4f6 | aliguori | return line;
|
235 | e3aff4f6 | aliguori | } |
236 | e3aff4f6 | aliguori | #elif defined(ENABLE_EDITLINE)
|
237 | e3aff4f6 | aliguori | static char *el_get_prompt(EditLine *e) { return get_prompt(); } |
238 | e3aff4f6 | aliguori | char *
|
239 | e3aff4f6 | aliguori | fetchline(void)
|
240 | e3aff4f6 | aliguori | { |
241 | e3aff4f6 | aliguori | static EditLine *el;
|
242 | e3aff4f6 | aliguori | static History *hist;
|
243 | e3aff4f6 | aliguori | HistEvent hevent; |
244 | e3aff4f6 | aliguori | char *line;
|
245 | e3aff4f6 | aliguori | int count;
|
246 | e3aff4f6 | aliguori | |
247 | e3aff4f6 | aliguori | if (!el) {
|
248 | e3aff4f6 | aliguori | hist = history_init(); |
249 | e3aff4f6 | aliguori | history(hist, &hevent, H_SETSIZE, 100);
|
250 | e3aff4f6 | aliguori | el = el_init(progname, stdin, stdout, stderr); |
251 | e3aff4f6 | aliguori | el_source(el, NULL);
|
252 | e3aff4f6 | aliguori | el_set(el, EL_SIGNAL, 1);
|
253 | e3aff4f6 | aliguori | el_set(el, EL_PROMPT, el_get_prompt); |
254 | e3aff4f6 | aliguori | el_set(el, EL_HIST, history, (const char *)hist); |
255 | e3aff4f6 | aliguori | } |
256 | e3aff4f6 | aliguori | line = strdup(el_gets(el, &count)); |
257 | e3aff4f6 | aliguori | if (line) {
|
258 | e3aff4f6 | aliguori | if (count > 0) |
259 | e3aff4f6 | aliguori | line[count-1] = '\0'; |
260 | e3aff4f6 | aliguori | if (*line)
|
261 | e3aff4f6 | aliguori | history(hist, &hevent, H_ENTER, line); |
262 | e3aff4f6 | aliguori | } |
263 | e3aff4f6 | aliguori | return line;
|
264 | e3aff4f6 | aliguori | } |
265 | e3aff4f6 | aliguori | #else
|
266 | e3aff4f6 | aliguori | # define MAXREADLINESZ 1024 |
267 | e3aff4f6 | aliguori | char *
|
268 | e3aff4f6 | aliguori | fetchline(void)
|
269 | e3aff4f6 | aliguori | { |
270 | e3aff4f6 | aliguori | char *p, *line = malloc(MAXREADLINESZ);
|
271 | e3aff4f6 | aliguori | |
272 | e3aff4f6 | aliguori | if (!line)
|
273 | e3aff4f6 | aliguori | return NULL; |
274 | e3aff4f6 | aliguori | printf("%s", get_prompt());
|
275 | e3aff4f6 | aliguori | fflush(stdout); |
276 | e3aff4f6 | aliguori | if (!fgets(line, MAXREADLINESZ, stdin)) {
|
277 | e3aff4f6 | aliguori | free(line); |
278 | e3aff4f6 | aliguori | return NULL; |
279 | e3aff4f6 | aliguori | } |
280 | e3aff4f6 | aliguori | p = line + strlen(line); |
281 | e3aff4f6 | aliguori | if (p != line && p[-1] == '\n') |
282 | e3aff4f6 | aliguori | p[-1] = '\0'; |
283 | e3aff4f6 | aliguori | return line;
|
284 | e3aff4f6 | aliguori | } |
285 | e3aff4f6 | aliguori | #endif
|
286 | e3aff4f6 | aliguori | |
287 | e3aff4f6 | aliguori | char **
|
288 | e3aff4f6 | aliguori | breakline( |
289 | e3aff4f6 | aliguori | char *input,
|
290 | e3aff4f6 | aliguori | int *count)
|
291 | e3aff4f6 | aliguori | { |
292 | e3aff4f6 | aliguori | int c = 0; |
293 | e3aff4f6 | aliguori | char *p;
|
294 | e3aff4f6 | aliguori | char **rval = calloc(sizeof(char *), 1); |
295 | e3aff4f6 | aliguori | |
296 | e3aff4f6 | aliguori | while (rval && (p = strsep(&input, " ")) != NULL) { |
297 | e3aff4f6 | aliguori | if (!*p)
|
298 | e3aff4f6 | aliguori | continue;
|
299 | e3aff4f6 | aliguori | c++; |
300 | e3aff4f6 | aliguori | rval = realloc(rval, sizeof(*rval) * (c + 1)); |
301 | e3aff4f6 | aliguori | if (!rval) {
|
302 | e3aff4f6 | aliguori | c = 0;
|
303 | e3aff4f6 | aliguori | break;
|
304 | e3aff4f6 | aliguori | } |
305 | e3aff4f6 | aliguori | rval[c - 1] = p;
|
306 | e3aff4f6 | aliguori | rval[c] = NULL;
|
307 | e3aff4f6 | aliguori | } |
308 | e3aff4f6 | aliguori | *count = c; |
309 | e3aff4f6 | aliguori | return rval;
|
310 | e3aff4f6 | aliguori | } |
311 | e3aff4f6 | aliguori | |
312 | e3aff4f6 | aliguori | void
|
313 | e3aff4f6 | aliguori | doneline( |
314 | e3aff4f6 | aliguori | char *input,
|
315 | e3aff4f6 | aliguori | char **vec)
|
316 | e3aff4f6 | aliguori | { |
317 | e3aff4f6 | aliguori | free(input); |
318 | e3aff4f6 | aliguori | free(vec); |
319 | e3aff4f6 | aliguori | } |
320 | e3aff4f6 | aliguori | |
321 | e3aff4f6 | aliguori | #define EXABYTES(x) ((long long)(x) << 60) |
322 | e3aff4f6 | aliguori | #define PETABYTES(x) ((long long)(x) << 50) |
323 | e3aff4f6 | aliguori | #define TERABYTES(x) ((long long)(x) << 40) |
324 | e3aff4f6 | aliguori | #define GIGABYTES(x) ((long long)(x) << 30) |
325 | e3aff4f6 | aliguori | #define MEGABYTES(x) ((long long)(x) << 20) |
326 | e3aff4f6 | aliguori | #define KILOBYTES(x) ((long long)(x) << 10) |
327 | e3aff4f6 | aliguori | |
328 | e3aff4f6 | aliguori | long long |
329 | e3aff4f6 | aliguori | cvtnum( |
330 | e3aff4f6 | aliguori | char *s)
|
331 | e3aff4f6 | aliguori | { |
332 | e3aff4f6 | aliguori | long long i; |
333 | e3aff4f6 | aliguori | char *sp;
|
334 | e3aff4f6 | aliguori | int c;
|
335 | e3aff4f6 | aliguori | |
336 | e3aff4f6 | aliguori | i = strtoll(s, &sp, 0);
|
337 | e3aff4f6 | aliguori | if (i == 0 && sp == s) |
338 | e3aff4f6 | aliguori | return -1LL; |
339 | e3aff4f6 | aliguori | if (*sp == '\0') |
340 | e3aff4f6 | aliguori | return i;
|
341 | e3aff4f6 | aliguori | |
342 | e3aff4f6 | aliguori | if (sp[1] != '\0') |
343 | e3aff4f6 | aliguori | return -1LL; |
344 | e3aff4f6 | aliguori | |
345 | e3aff4f6 | aliguori | c = tolower(*sp); |
346 | e3aff4f6 | aliguori | switch (c) {
|
347 | e3aff4f6 | aliguori | default:
|
348 | e3aff4f6 | aliguori | return i;
|
349 | e3aff4f6 | aliguori | case 'k': |
350 | e3aff4f6 | aliguori | return KILOBYTES(i);
|
351 | e3aff4f6 | aliguori | case 'm': |
352 | e3aff4f6 | aliguori | return MEGABYTES(i);
|
353 | e3aff4f6 | aliguori | case 'g': |
354 | e3aff4f6 | aliguori | return GIGABYTES(i);
|
355 | e3aff4f6 | aliguori | case 't': |
356 | e3aff4f6 | aliguori | return TERABYTES(i);
|
357 | e3aff4f6 | aliguori | case 'p': |
358 | e3aff4f6 | aliguori | return PETABYTES(i);
|
359 | e3aff4f6 | aliguori | case 'e': |
360 | e3aff4f6 | aliguori | return EXABYTES(i);
|
361 | e3aff4f6 | aliguori | } |
362 | e3aff4f6 | aliguori | return -1LL; |
363 | e3aff4f6 | aliguori | } |
364 | e3aff4f6 | aliguori | |
365 | e3aff4f6 | aliguori | #define TO_EXABYTES(x) ((x) / EXABYTES(1)) |
366 | e3aff4f6 | aliguori | #define TO_PETABYTES(x) ((x) / PETABYTES(1)) |
367 | e3aff4f6 | aliguori | #define TO_TERABYTES(x) ((x) / TERABYTES(1)) |
368 | e3aff4f6 | aliguori | #define TO_GIGABYTES(x) ((x) / GIGABYTES(1)) |
369 | e3aff4f6 | aliguori | #define TO_MEGABYTES(x) ((x) / MEGABYTES(1)) |
370 | e3aff4f6 | aliguori | #define TO_KILOBYTES(x) ((x) / KILOBYTES(1)) |
371 | e3aff4f6 | aliguori | |
372 | e3aff4f6 | aliguori | void
|
373 | e3aff4f6 | aliguori | cvtstr( |
374 | e3aff4f6 | aliguori | double value,
|
375 | e3aff4f6 | aliguori | char *str,
|
376 | e3aff4f6 | aliguori | size_t size) |
377 | e3aff4f6 | aliguori | { |
378 | e3aff4f6 | aliguori | const char *fmt; |
379 | e3aff4f6 | aliguori | int precise;
|
380 | e3aff4f6 | aliguori | |
381 | e3aff4f6 | aliguori | precise = ((double)value * 1000 == (double)(int)value * 1000); |
382 | e3aff4f6 | aliguori | |
383 | e3aff4f6 | aliguori | if (value >= EXABYTES(1)) { |
384 | e3aff4f6 | aliguori | fmt = precise ? "%.f EiB" : "%.3f EiB"; |
385 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_EXABYTES(value)); |
386 | e3aff4f6 | aliguori | } else if (value >= PETABYTES(1)) { |
387 | e3aff4f6 | aliguori | fmt = precise ? "%.f PiB" : "%.3f PiB"; |
388 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_PETABYTES(value)); |
389 | e3aff4f6 | aliguori | } else if (value >= TERABYTES(1)) { |
390 | e3aff4f6 | aliguori | fmt = precise ? "%.f TiB" : "%.3f TiB"; |
391 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_TERABYTES(value)); |
392 | e3aff4f6 | aliguori | } else if (value >= GIGABYTES(1)) { |
393 | e3aff4f6 | aliguori | fmt = precise ? "%.f GiB" : "%.3f GiB"; |
394 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_GIGABYTES(value)); |
395 | e3aff4f6 | aliguori | } else if (value >= MEGABYTES(1)) { |
396 | e3aff4f6 | aliguori | fmt = precise ? "%.f MiB" : "%.3f MiB"; |
397 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_MEGABYTES(value)); |
398 | e3aff4f6 | aliguori | } else if (value >= KILOBYTES(1)) { |
399 | e3aff4f6 | aliguori | fmt = precise ? "%.f KiB" : "%.3f KiB"; |
400 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_KILOBYTES(value)); |
401 | e3aff4f6 | aliguori | } else {
|
402 | e3aff4f6 | aliguori | snprintf(str, size, "%f bytes", value);
|
403 | e3aff4f6 | aliguori | } |
404 | e3aff4f6 | aliguori | } |
405 | e3aff4f6 | aliguori | |
406 | e3aff4f6 | aliguori | struct timeval
|
407 | e3aff4f6 | aliguori | tsub(struct timeval t1, struct timeval t2) |
408 | e3aff4f6 | aliguori | { |
409 | e3aff4f6 | aliguori | t1.tv_usec -= t2.tv_usec; |
410 | e3aff4f6 | aliguori | if (t1.tv_usec < 0) { |
411 | e3aff4f6 | aliguori | t1.tv_usec += 1000000;
|
412 | e3aff4f6 | aliguori | t1.tv_sec--; |
413 | e3aff4f6 | aliguori | } |
414 | e3aff4f6 | aliguori | t1.tv_sec -= t2.tv_sec; |
415 | e3aff4f6 | aliguori | return t1;
|
416 | e3aff4f6 | aliguori | } |
417 | e3aff4f6 | aliguori | |
418 | e3aff4f6 | aliguori | double
|
419 | e3aff4f6 | aliguori | tdiv(double value, struct timeval tv) |
420 | e3aff4f6 | aliguori | { |
421 | e3aff4f6 | aliguori | return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); |
422 | e3aff4f6 | aliguori | } |
423 | e3aff4f6 | aliguori | |
424 | e3aff4f6 | aliguori | #define HOURS(sec) ((sec) / (60 * 60)) |
425 | e3aff4f6 | aliguori | #define MINUTES(sec) (((sec) % (60 * 60)) / 60) |
426 | e3aff4f6 | aliguori | #define SECONDS(sec) ((sec) % 60) |
427 | e3aff4f6 | aliguori | |
428 | e3aff4f6 | aliguori | void
|
429 | e3aff4f6 | aliguori | timestr( |
430 | e3aff4f6 | aliguori | struct timeval *tv,
|
431 | e3aff4f6 | aliguori | char *ts,
|
432 | e3aff4f6 | aliguori | size_t size, |
433 | e3aff4f6 | aliguori | int format)
|
434 | e3aff4f6 | aliguori | { |
435 | e3aff4f6 | aliguori | double usec = (double)tv->tv_usec / 1000000.0; |
436 | e3aff4f6 | aliguori | |
437 | e3aff4f6 | aliguori | if (format & TERSE_FIXED_TIME) {
|
438 | e3aff4f6 | aliguori | if (!HOURS(tv->tv_sec)) {
|
439 | e3aff4f6 | aliguori | snprintf(ts, size, "%u:%02u.%02u",
|
440 | e3aff4f6 | aliguori | (unsigned int) MINUTES(tv->tv_sec), |
441 | e3aff4f6 | aliguori | (unsigned int) SECONDS(tv->tv_sec), |
442 | e3aff4f6 | aliguori | (unsigned int) usec * 100); |
443 | e3aff4f6 | aliguori | return;
|
444 | e3aff4f6 | aliguori | } |
445 | e3aff4f6 | aliguori | format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
|
446 | e3aff4f6 | aliguori | } |
447 | e3aff4f6 | aliguori | |
448 | e3aff4f6 | aliguori | if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
|
449 | e3aff4f6 | aliguori | snprintf(ts, size, "%u:%02u:%02u.%02u",
|
450 | e3aff4f6 | aliguori | (unsigned int) HOURS(tv->tv_sec), |
451 | e3aff4f6 | aliguori | (unsigned int) MINUTES(tv->tv_sec), |
452 | e3aff4f6 | aliguori | (unsigned int) SECONDS(tv->tv_sec), |
453 | e3aff4f6 | aliguori | (unsigned int) usec * 100); |
454 | e3aff4f6 | aliguori | } else {
|
455 | e3aff4f6 | aliguori | snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000); |
456 | e3aff4f6 | aliguori | } |
457 | e3aff4f6 | aliguori | } |
458 | e3aff4f6 | aliguori | |
459 | e3aff4f6 | aliguori | |
460 | e3aff4f6 | aliguori | /* from libxcmd/quit.c */
|
461 | e3aff4f6 | aliguori | |
462 | e3aff4f6 | aliguori | static cmdinfo_t quit_cmd;
|
463 | e3aff4f6 | aliguori | |
464 | e3aff4f6 | aliguori | /* ARGSUSED */
|
465 | e3aff4f6 | aliguori | static int |
466 | e3aff4f6 | aliguori | quit_f( |
467 | e3aff4f6 | aliguori | int argc,
|
468 | e3aff4f6 | aliguori | char **argv)
|
469 | e3aff4f6 | aliguori | { |
470 | e3aff4f6 | aliguori | return 1; |
471 | e3aff4f6 | aliguori | } |
472 | e3aff4f6 | aliguori | |
473 | e3aff4f6 | aliguori | void
|
474 | e3aff4f6 | aliguori | quit_init(void)
|
475 | e3aff4f6 | aliguori | { |
476 | e3aff4f6 | aliguori | quit_cmd.name = _("quit");
|
477 | e3aff4f6 | aliguori | quit_cmd.altname = _("q");
|
478 | e3aff4f6 | aliguori | quit_cmd.cfunc = quit_f; |
479 | e3aff4f6 | aliguori | quit_cmd.argmin = -1;
|
480 | e3aff4f6 | aliguori | quit_cmd.argmax = -1;
|
481 | e3aff4f6 | aliguori | quit_cmd.flags = CMD_FLAG_GLOBAL; |
482 | e3aff4f6 | aliguori | quit_cmd.oneline = _("exit the program");
|
483 | e3aff4f6 | aliguori | |
484 | e3aff4f6 | aliguori | add_command(&quit_cmd); |
485 | e3aff4f6 | aliguori | } |
486 | e3aff4f6 | aliguori | |
487 | e3aff4f6 | aliguori | /* from libxcmd/help.c */
|
488 | e3aff4f6 | aliguori | |
489 | e3aff4f6 | aliguori | static cmdinfo_t help_cmd;
|
490 | e3aff4f6 | aliguori | static void help_onecmd(const char *cmd, const cmdinfo_t *ct); |
491 | e3aff4f6 | aliguori | static void help_oneline(const char *cmd, const cmdinfo_t *ct); |
492 | e3aff4f6 | aliguori | |
493 | e3aff4f6 | aliguori | static void |
494 | e3aff4f6 | aliguori | help_all(void)
|
495 | e3aff4f6 | aliguori | { |
496 | e3aff4f6 | aliguori | const cmdinfo_t *ct;
|
497 | e3aff4f6 | aliguori | |
498 | e3aff4f6 | aliguori | for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
|
499 | e3aff4f6 | aliguori | help_oneline(ct->name, ct); |
500 | e3aff4f6 | aliguori | printf(_("\nUse 'help commandname' for extended help.\n"));
|
501 | e3aff4f6 | aliguori | } |
502 | e3aff4f6 | aliguori | |
503 | e3aff4f6 | aliguori | static int |
504 | e3aff4f6 | aliguori | help_f( |
505 | e3aff4f6 | aliguori | int argc,
|
506 | e3aff4f6 | aliguori | char **argv)
|
507 | e3aff4f6 | aliguori | { |
508 | e3aff4f6 | aliguori | const cmdinfo_t *ct;
|
509 | e3aff4f6 | aliguori | |
510 | e3aff4f6 | aliguori | if (argc == 1) { |
511 | e3aff4f6 | aliguori | help_all(); |
512 | e3aff4f6 | aliguori | return 0; |
513 | e3aff4f6 | aliguori | } |
514 | e3aff4f6 | aliguori | ct = find_command(argv[1]);
|
515 | e3aff4f6 | aliguori | if (ct == NULL) { |
516 | e3aff4f6 | aliguori | printf(_("command %s not found\n"), argv[1]); |
517 | e3aff4f6 | aliguori | return 0; |
518 | e3aff4f6 | aliguori | } |
519 | e3aff4f6 | aliguori | help_onecmd(argv[1], ct);
|
520 | e3aff4f6 | aliguori | return 0; |
521 | e3aff4f6 | aliguori | } |
522 | e3aff4f6 | aliguori | |
523 | e3aff4f6 | aliguori | static void |
524 | e3aff4f6 | aliguori | help_onecmd( |
525 | e3aff4f6 | aliguori | const char *cmd, |
526 | e3aff4f6 | aliguori | const cmdinfo_t *ct)
|
527 | e3aff4f6 | aliguori | { |
528 | e3aff4f6 | aliguori | help_oneline(cmd, ct); |
529 | e3aff4f6 | aliguori | if (ct->help)
|
530 | e3aff4f6 | aliguori | ct->help(); |
531 | e3aff4f6 | aliguori | } |
532 | e3aff4f6 | aliguori | |
533 | e3aff4f6 | aliguori | static void |
534 | e3aff4f6 | aliguori | help_oneline( |
535 | e3aff4f6 | aliguori | const char *cmd, |
536 | e3aff4f6 | aliguori | const cmdinfo_t *ct)
|
537 | e3aff4f6 | aliguori | { |
538 | e3aff4f6 | aliguori | if (cmd)
|
539 | e3aff4f6 | aliguori | printf("%s ", cmd);
|
540 | e3aff4f6 | aliguori | else {
|
541 | e3aff4f6 | aliguori | printf("%s ", ct->name);
|
542 | e3aff4f6 | aliguori | if (ct->altname)
|
543 | e3aff4f6 | aliguori | printf("(or %s) ", ct->altname);
|
544 | e3aff4f6 | aliguori | } |
545 | e3aff4f6 | aliguori | if (ct->args)
|
546 | e3aff4f6 | aliguori | printf("%s ", ct->args);
|
547 | e3aff4f6 | aliguori | printf("-- %s\n", ct->oneline);
|
548 | e3aff4f6 | aliguori | } |
549 | e3aff4f6 | aliguori | |
550 | e3aff4f6 | aliguori | void
|
551 | e3aff4f6 | aliguori | help_init(void)
|
552 | e3aff4f6 | aliguori | { |
553 | e3aff4f6 | aliguori | help_cmd.name = _("help");
|
554 | e3aff4f6 | aliguori | help_cmd.altname = _("?");
|
555 | e3aff4f6 | aliguori | help_cmd.cfunc = help_f; |
556 | e3aff4f6 | aliguori | help_cmd.argmin = 0;
|
557 | e3aff4f6 | aliguori | help_cmd.argmax = 1;
|
558 | e3aff4f6 | aliguori | help_cmd.flags = CMD_FLAG_GLOBAL; |
559 | e3aff4f6 | aliguori | help_cmd.args = _("[command]");
|
560 | e3aff4f6 | aliguori | help_cmd.oneline = _("help for one or all commands");
|
561 | e3aff4f6 | aliguori | |
562 | e3aff4f6 | aliguori | add_command(&help_cmd); |
563 | e3aff4f6 | aliguori | } |