Annotation of qemu/cmd.c, revision 1.1

1.1     ! root        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