File:  [Qemu by Fabrice Bellard] / qemu / cmd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:29 2018 UTC (2 years, 4 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0111, qemu0110, HEAD
qemu 0.11.0

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

unix.superglobalmegacorp.com