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