cmd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  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. #include "main-loop.h"
  27. #define _(x) x /* not gettext support yet */
  28. /* from libxcmd/command.c */
  29. cmdinfo_t *cmdtab;
  30. int ncmds;
  31. static argsfunc_t args_func;
  32. static checkfunc_t check_func;
  33. static int ncmdline;
  34. static char **cmdline;
  35. static int
  36. compare(const void *a, const void *b)
  37. {
  38. return strcmp(((const cmdinfo_t *)a)->name,
  39. ((const cmdinfo_t *)b)->name);
  40. }
  41. void add_command(const cmdinfo_t *ci)
  42. {
  43. cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
  44. cmdtab[ncmds - 1] = *ci;
  45. qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
  46. }
  47. static int
  48. check_command(
  49. const cmdinfo_t *ci)
  50. {
  51. if (check_func)
  52. return check_func(ci);
  53. return 1;
  54. }
  55. void
  56. add_check_command(
  57. checkfunc_t cf)
  58. {
  59. check_func = cf;
  60. }
  61. int
  62. command_usage(
  63. const cmdinfo_t *ci)
  64. {
  65. printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
  66. return 0;
  67. }
  68. int
  69. command(
  70. const cmdinfo_t *ct,
  71. int argc,
  72. char **argv)
  73. {
  74. char *cmd = argv[0];
  75. if (!check_command(ct))
  76. return 0;
  77. if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
  78. if (ct->argmax == -1)
  79. fprintf(stderr,
  80. _("bad argument count %d to %s, expected at least %d arguments\n"),
  81. argc-1, cmd, ct->argmin);
  82. else if (ct->argmin == ct->argmax)
  83. fprintf(stderr,
  84. _("bad argument count %d to %s, expected %d arguments\n"),
  85. argc-1, cmd, ct->argmin);
  86. else
  87. fprintf(stderr,
  88. _("bad argument count %d to %s, expected between %d and %d arguments\n"),
  89. argc-1, cmd, ct->argmin, ct->argmax);
  90. return 0;
  91. }
  92. optind = 0;
  93. return ct->cfunc(argc, argv);
  94. }
  95. const cmdinfo_t *
  96. find_command(
  97. const char *cmd)
  98. {
  99. cmdinfo_t *ct;
  100. for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
  101. if (strcmp(ct->name, cmd) == 0 ||
  102. (ct->altname && strcmp(ct->altname, cmd) == 0))
  103. return (const cmdinfo_t *)ct;
  104. }
  105. return NULL;
  106. }
  107. void add_user_command(char *optarg)
  108. {
  109. cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
  110. cmdline[ncmdline-1] = optarg;
  111. }
  112. static int
  113. args_command(
  114. int index)
  115. {
  116. if (args_func)
  117. return args_func(index);
  118. return 0;
  119. }
  120. void
  121. add_args_command(
  122. argsfunc_t af)
  123. {
  124. args_func = af;
  125. }
  126. static void prep_fetchline(void *opaque)
  127. {
  128. int *fetchable = opaque;
  129. qemu_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL);
  130. *fetchable= 1;
  131. }
  132. static char *get_prompt(void);
  133. void command_loop(void)
  134. {
  135. int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
  136. char *input;
  137. char **v;
  138. const cmdinfo_t *ct;
  139. for (i = 0; !done && i < ncmdline; i++) {
  140. input = strdup(cmdline[i]);
  141. if (!input) {
  142. fprintf(stderr, _("cannot strdup command '%s': %s\n"),
  143. cmdline[i], strerror(errno));
  144. exit(1);
  145. }
  146. v = breakline(input, &c);
  147. if (c) {
  148. ct = find_command(v[0]);
  149. if (ct) {
  150. if (ct->flags & CMD_FLAG_GLOBAL) {
  151. done = command(ct, c, v);
  152. } else {
  153. j = 0;
  154. while (!done && (j = args_command(j))) {
  155. done = command(ct, c, v);
  156. }
  157. }
  158. } else {
  159. fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
  160. }
  161. }
  162. doneline(input, v);
  163. }
  164. if (cmdline) {
  165. g_free(cmdline);
  166. return;
  167. }
  168. while (!done) {
  169. if (!prompted) {
  170. printf("%s", get_prompt());
  171. fflush(stdout);
  172. qemu_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, &fetchable);
  173. prompted = 1;
  174. }
  175. main_loop_wait(false);
  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_set_fd_handler(STDIN_FILENO, 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. char *trim;
  374. const char *suffix;
  375. if (value >= EXABYTES(1)) {
  376. suffix = " EiB";
  377. snprintf(str, size - 4, "%.3f", TO_EXABYTES(value));
  378. } else if (value >= PETABYTES(1)) {
  379. suffix = " PiB";
  380. snprintf(str, size - 4, "%.3f", TO_PETABYTES(value));
  381. } else if (value >= TERABYTES(1)) {
  382. suffix = " TiB";
  383. snprintf(str, size - 4, "%.3f", TO_TERABYTES(value));
  384. } else if (value >= GIGABYTES(1)) {
  385. suffix = " GiB";
  386. snprintf(str, size - 4, "%.3f", TO_GIGABYTES(value));
  387. } else if (value >= MEGABYTES(1)) {
  388. suffix = " MiB";
  389. snprintf(str, size - 4, "%.3f", TO_MEGABYTES(value));
  390. } else if (value >= KILOBYTES(1)) {
  391. suffix = " KiB";
  392. snprintf(str, size - 4, "%.3f", TO_KILOBYTES(value));
  393. } else {
  394. suffix = " bytes";
  395. snprintf(str, size - 6, "%f", value);
  396. }
  397. trim = strstr(str, ".000");
  398. if (trim) {
  399. strcpy(trim, suffix);
  400. } else {
  401. strcat(str, suffix);
  402. }
  403. }
  404. struct timeval
  405. tsub(struct timeval t1, struct timeval t2)
  406. {
  407. t1.tv_usec -= t2.tv_usec;
  408. if (t1.tv_usec < 0) {
  409. t1.tv_usec += 1000000;
  410. t1.tv_sec--;
  411. }
  412. t1.tv_sec -= t2.tv_sec;
  413. return t1;
  414. }
  415. double
  416. tdiv(double value, struct timeval tv)
  417. {
  418. return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));
  419. }
  420. #define HOURS(sec) ((sec) / (60 * 60))
  421. #define MINUTES(sec) (((sec) % (60 * 60)) / 60)
  422. #define SECONDS(sec) ((sec) % 60)
  423. void
  424. timestr(
  425. struct timeval *tv,
  426. char *ts,
  427. size_t size,
  428. int format)
  429. {
  430. double usec = (double)tv->tv_usec / 1000000.0;
  431. if (format & TERSE_FIXED_TIME) {
  432. if (!HOURS(tv->tv_sec)) {
  433. snprintf(ts, size, "%u:%02u.%02u",
  434. (unsigned int) MINUTES(tv->tv_sec),
  435. (unsigned int) SECONDS(tv->tv_sec),
  436. (unsigned int) (usec * 100));
  437. return;
  438. }
  439. format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
  440. }
  441. if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
  442. snprintf(ts, size, "%u:%02u:%02u.%02u",
  443. (unsigned int) HOURS(tv->tv_sec),
  444. (unsigned int) MINUTES(tv->tv_sec),
  445. (unsigned int) SECONDS(tv->tv_sec),
  446. (unsigned int) (usec * 100));
  447. } else {
  448. snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
  449. }
  450. }
  451. /* from libxcmd/quit.c */
  452. static cmdinfo_t quit_cmd;
  453. /* ARGSUSED */
  454. static int
  455. quit_f(
  456. int argc,
  457. char **argv)
  458. {
  459. return 1;
  460. }
  461. void
  462. quit_init(void)
  463. {
  464. quit_cmd.name = _("quit");
  465. quit_cmd.altname = _("q");
  466. quit_cmd.cfunc = quit_f;
  467. quit_cmd.argmin = -1;
  468. quit_cmd.argmax = -1;
  469. quit_cmd.flags = CMD_FLAG_GLOBAL;
  470. quit_cmd.oneline = _("exit the program");
  471. add_command(&quit_cmd);
  472. }
  473. /* from libxcmd/help.c */
  474. static cmdinfo_t help_cmd;
  475. static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
  476. static void help_oneline(const char *cmd, const cmdinfo_t *ct);
  477. static void
  478. help_all(void)
  479. {
  480. const cmdinfo_t *ct;
  481. for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
  482. help_oneline(ct->name, ct);
  483. printf(_("\nUse 'help commandname' for extended help.\n"));
  484. }
  485. static int
  486. help_f(
  487. int argc,
  488. char **argv)
  489. {
  490. const cmdinfo_t *ct;
  491. if (argc == 1) {
  492. help_all();
  493. return 0;
  494. }
  495. ct = find_command(argv[1]);
  496. if (ct == NULL) {
  497. printf(_("command %s not found\n"), argv[1]);
  498. return 0;
  499. }
  500. help_onecmd(argv[1], ct);
  501. return 0;
  502. }
  503. static void
  504. help_onecmd(
  505. const char *cmd,
  506. const cmdinfo_t *ct)
  507. {
  508. help_oneline(cmd, ct);
  509. if (ct->help)
  510. ct->help();
  511. }
  512. static void
  513. help_oneline(
  514. const char *cmd,
  515. const cmdinfo_t *ct)
  516. {
  517. if (cmd)
  518. printf("%s ", cmd);
  519. else {
  520. printf("%s ", ct->name);
  521. if (ct->altname)
  522. printf("(or %s) ", ct->altname);
  523. }
  524. if (ct->args)
  525. printf("%s ", ct->args);
  526. printf("-- %s\n", ct->oneline);
  527. }
  528. void
  529. help_init(void)
  530. {
  531. help_cmd.name = _("help");
  532. help_cmd.altname = _("?");
  533. help_cmd.cfunc = help_f;
  534. help_cmd.argmin = 0;
  535. help_cmd.argmax = 1;
  536. help_cmd.flags = CMD_FLAG_GLOBAL;
  537. help_cmd.args = _("[command]");
  538. help_cmd.oneline = _("help for one or all commands");
  539. add_command(&help_cmd);
  540. }