File:  [Qemu by Fabrice Bellard] / qemu / cmd.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:35:24 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

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

unix.superglobalmegacorp.com