]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxcmd/command.c
libxcmd: merge command() and iterate_command()
[thirdparty/xfsprogs-dev.git] / libxcmd / command.c
CommitLineData
e246ba5f 1/*
da23017d
NS
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
dfc130f3 4 *
da23017d
NS
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
e246ba5f 7 * published by the Free Software Foundation.
dfc130f3 8 *
da23017d
NS
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
dfc130f3 13 *
da23017d
NS
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
e246ba5f 17 */
dfc130f3 18
dcabd4e7 19#include "platform_defs.h"
6b803e5a
CH
20#include "command.h"
21#include "input.h"
e246ba5f
NS
22
23cmdinfo_t *cmdtab;
24int ncmds;
25
ef346a25 26static iterfunc_t iter_func;
3d93ccb7
NS
27static checkfunc_t check_func;
28static int ncmdline;
29static char **cmdline;
30
e246ba5f 31static int
3d93ccb7 32compare(const void *a, const void *b)
e246ba5f
NS
33{
34 return strcmp(((const cmdinfo_t *)a)->name,
35 ((const cmdinfo_t *)b)->name);
36}
37
38void
39add_command(
40 const cmdinfo_t *ci)
41{
42 cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
43 cmdtab[ncmds - 1] = *ci;
3d93ccb7
NS
44 qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
45}
46
47static int
48check_command(
49 const cmdinfo_t *ci)
50{
51 if (check_func)
52 return check_func(ci);
53 return 1;
54}
55
56void
57add_check_command(
58 checkfunc_t cf)
59{
60 check_func = cf;
e246ba5f
NS
61}
62
48c46ee3
NS
63int
64command_usage(
65 const cmdinfo_t *ci)
66{
3d93ccb7 67 printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
48c46ee3
NS
68 return 0;
69}
70
e246ba5f
NS
71int
72command(
802d66e3 73 const cmdinfo_t *ct,
e246ba5f
NS
74 int argc,
75 char **argv)
76{
802d66e3 77 char *cmd = argv[0];
e246ba5f 78
3d93ccb7 79 if (!check_command(ct))
48c46ee3 80 return 0;
802d66e3 81
e246ba5f
NS
82 if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
83 if (ct->argmax == -1)
84 fprintf(stderr,
85 _("bad argument count %d to %s, expected at least %d arguments\n"),
86 argc-1, cmd, ct->argmin);
87 else if (ct->argmin == ct->argmax)
88 fprintf(stderr,
89 _("bad argument count %d to %s, expected %d arguments\n"),
90 argc-1, cmd, ct->argmin);
91 else
92 fprintf(stderr,
93 _("bad argument count %d to %s, expected between %d and %d arguments\n"),
94 argc-1, cmd, ct->argmin, ct->argmax);
95 return 0;
96 }
c0211f67 97 platform_getoptreset();
e246ba5f
NS
98 return ct->cfunc(argc, argv);
99}
100
101const cmdinfo_t *
102find_command(
103 const char *cmd)
104{
105 cmdinfo_t *ct;
106
107 for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
108 if (strcmp(ct->name, cmd) == 0 ||
109 (ct->altname && strcmp(ct->altname, cmd) == 0))
110 return (const cmdinfo_t *)ct;
111 }
112 return NULL;
113}
3d93ccb7
NS
114
115void
116add_user_command(char *optarg)
117{
118 ncmdline++;
119 cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
120 if (!cmdline) {
121 perror("realloc");
122 exit(1);
123 }
124 cmdline[ncmdline-1] = optarg;
125}
126
7a9b7314 127/*
d6ac0462
DC
128 * Run a command, iterating as necessary. Return 0 for success, non-zero
129 * if an error occurred. Errors terminate loop iteration immediately.
7a9b7314 130 */
3d93ccb7 131static int
ef346a25 132iterate_command(
7a9b7314 133 const cmdinfo_t *ct,
d6ac0462
DC
134 int argc,
135 char **argv)
3d93ccb7 136{
d6ac0462
DC
137 int error = 0;
138 int j;
139
140 /* if there's nothing to iterate, we're done! */
141 if (!iter_func)
7a9b7314 142 return 0;
d6ac0462
DC
143
144 for (j = iter_func(0); j; j = iter_func(j)) {
145 error = command(ct, argc, argv);
146 if (error)
147 break;
148
149 }
150
151 return error;
3d93ccb7
NS
152}
153
154void
ef346a25
DC
155add_command_iterator(
156 iterfunc_t func)
3d93ccb7 157{
ef346a25 158 iter_func = func;
3d93ccb7
NS
159}
160
d6ac0462
DC
161static int
162process_input(
163 char *input,
164 bool iterate)
3d93ccb7 165{
802d66e3
BN
166 char **v;
167 const cmdinfo_t *ct;
d6ac0462
DC
168 int c = 0;
169 int error = 0;
170
171 v = breakline(input, &c);
172 if (!c)
173 goto out;
174
175 ct = find_command(v[0]);
176 if (!ct) {
177 fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
178 goto out;
179 }
180
181 /* oneshot commands don't iterate */
182 if (!iterate || (ct->flags & CMD_FLAG_ONESHOT))
183 error = command(ct, c, v);
184 else
185 error = iterate_command(ct, c, v);
186out:
187 doneline(input, v);
188 return error;
189}
190
191void
192command_loop(void)
193{
194 char *input;
195 int done = 0;
196 int i;
197
198 if (!cmdline) {
199 /* interactive mode */
200 while (!done) {
201 input = fetchline();
202 if (!input)
203 break;
204 done = process_input(input, false);
205 }
206 return;
207 }
3d93ccb7 208
d6ac0462 209 /* command line mode */
3d93ccb7 210 for (i = 0; !done && i < ncmdline; i++) {
802d66e3
BN
211 input = strdup(cmdline[i]);
212 if (!input) {
213 fprintf(stderr,
214 _("cannot strdup command '%s': %s\n"),
215 cmdline[i], strerror(errno));
216 exit(1);
217 }
d6ac0462 218 done = process_input(input, true);
3d93ccb7 219 }
d6ac0462
DC
220 free(cmdline);
221 return;
3d93ccb7 222}
a9b61ce9
DW
223
224void
225report_io_times(
226 const char *verb,
227 struct timeval *t2,
228 long long offset,
229 long long count,
230 long long total,
231 int ops,
232 int compact)
233{
234 char s1[64], s2[64], ts[64];
235
236 timestr(t2, ts, sizeof(ts), compact ? VERBOSE_FIXED_TIME : 0);
237 if (!compact) {
238 cvtstr((double)total, s1, sizeof(s1));
239 cvtstr(tdiv((double)total, *t2), s2, sizeof(s2));
240 printf(_("%s %lld/%lld bytes at offset %lld\n"),
241 verb, total, count, (long long)offset);
242 printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
243 s1, ops, ts, s2, tdiv((double)ops, *t2));
244 } else {/* bytes,ops,time,bytes/sec,ops/sec */
245 printf("%lld,%d,%s,%.3f,%.3f\n",
246 total, ops, ts,
247 tdiv((double)total, *t2), tdiv((double)ops, *t2));
248 }
249}