cmd.c 12 KB

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