cmd.c 12 KB

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