[BACK]Return to clit.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pmdb

Annotation of src/usr.bin/pmdb/clit.c, Revision 1.7

1.7     ! nicm        1: /*     $OpenBSD: clit.c,v 1.6 2007/09/02 15:19:33 deraadt Exp $        */
1.1       art         2: /*
                      3:  * Copyright (c) 2002 Artur Grabowski <art@openbsd.org>
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  *
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. The name of the author may not be used to endorse or promote products
                     13:  *    derived from this software without specific prior written permission.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26:
                     27: #include <stdlib.h>
                     28: #include <stdio.h>
                     29: #include <histedit.h>
                     30: #include <err.h>
                     31: #include <string.h>
                     32:
                     33: #include "clit.h"
                     34:
                     35: extern char *__progname;
                     36:
                     37: char *prompt_add;
                     38:
                     39: static char *
                     40: prompt(EditLine *el)
                     41: {
                     42:        static char p[64];
                     43:
                     44:        snprintf(p, sizeof(p), "%s%s> ", __progname,
                     45:            prompt_add ? prompt_add : "");
                     46:
                     47:        return p;
                     48: }
                     49:
                     50: /*
                     51:  * Returns number of commands that (at least partially) match "name".
                     52:  */
                     53: static int
                     54: name_to_cmd(const char *name, struct clit *cmds, int ncmds, struct clit **res)
                     55: {
                     56:        int i, len, ret;
                     57:
                     58:        len = strlen(name);
                     59:        ret = 0;
                     60:
                     61:        for (i = 0; i < ncmds; i++) {
                     62:                if (strncmp(cmds[i].cmd, name, len) == 0) {
                     63:                        *res = &cmds[i];
                     64:                        ret++;
                     65:                }
                     66:        }
                     67:
                     68:        return ret;
                     69: }
                     70:
                     71: struct clitenv {
                     72:        struct clit *cmds;
                     73:        int ncmds;
                     74:        EditLine *el;
                     75:        History *hist;
                     76: };
                     77:
                     78: int
                     79: cmd_help(int argc, char **argv, void *arg)
                     80: {
                     81:        struct clitenv *env = arg;
                     82:        struct clit *cmds = env->cmds, *cmdp;
                     83:        int ncmds = env->ncmds;
                     84:        int i, res;
                     85:
                     86:        if (argc > 1) {
                     87:                res = name_to_cmd(argv[1], cmds, ncmds, &cmdp);
                     88:                if (res == 1) {
                     89:                        printf("%s\t%s\n", cmdp->cmd, cmdp->help);
                     90:                } else {
                     91:                        fprintf(stderr, "%s command: %s\n",
                     92:                            res == 0 ? "unknown" : "ambiguous", argv[1]);
                     93:                }
                     94:
                     95:                return 0;
                     96:        }
                     97:        for (i = 0; i < ncmds; i++) {
                     98:                cmdp = &cmds[i];
                     99:
                    100:                printf("%s\t%s\n", cmdp->cmd, cmdp->help);
                    101:        }
                    102:
                    103:        return 0;
                    104: }
                    105:
                    106: /*
                    107:  * XXX - there is no way to push external args into this function.
                    108:  */
                    109: unsigned char
                    110: complt(EditLine *el, int ch)
                    111: {
                    112:        const LineInfo *line;
                    113:        char str[1024];
                    114:        int len, ret;
                    115:
                    116:        line = el_line(el);
                    117:        if (line->cursor != line->lastchar)
                    118:                return CC_ERROR;
                    119:
                    120:        len = line->lastchar - line->buffer;
                    121:
                    122:        if (len >= 1023)
                    123:                return CC_ERROR;
                    124:
                    125:        memcpy(str, line->buffer, len);
                    126:        str[len] = '\0';
                    127:
                    128:        ret = cmd_complt(str, sizeof(str));
                    129:
                    130:        el_push(el, &str[len]);
                    131:
                    132:        return ret ? CC_ERROR : CC_REDISPLAY;
                    133: }
                    134:
                    135: void *
                    136: cmdinit(struct clit *cmds, int ncmds)
                    137: {
                    138:        struct clitenv *env;
                    139:        HistEvent ev;
                    140:
                    141:        if ((env = malloc(sizeof(*env))) == NULL)
                    142:                err(1, "Can't init cmd interpreter.");
                    143:
                    144:        env->cmds = cmds;
                    145:        env->ncmds = ncmds;
                    146:
                    147:        env->hist = history_init();
                    148:        history(env->hist, &ev, H_SETSIZE, 100);
                    149:
                    150:        env->el = el_init(__progname, stdin, stdout, stderr);
1.5       otto      151:
1.1       art       152:        el_set(env->el, EL_EDITOR, "emacs");
                    153:        el_set(env->el, EL_PROMPT, prompt);
                    154:        el_set(env->el, EL_HIST, history, env->hist);
                    155:        el_set(env->el, EL_ADDFN, "complt", "complete", complt);
1.7     ! nicm      156:        el_set(env->el, EL_BIND, "\t", "complt", NULL);
1.1       art       157:        el_source(env->el, NULL);
                    158:
                    159:        /* XXX - EL_SIGNAL ? */
                    160:
                    161:        return env;
                    162: }
                    163:
                    164: void
                    165: cmdend(void *arg)
                    166: {
                    167:        struct clitenv *env = arg;
                    168:
                    169:        el_end(env->el);
                    170:        history_end(env->hist);
                    171:
                    172:        free(env);
                    173: }
                    174:
                    175: int
                    176: cmdloop(void *arg)
                    177: {
                    178:        struct clitenv *env = arg;
                    179:        EditLine *el = env->el;
                    180:        History *hist = env->hist;
                    181:        const char *elline;
                    182:        int cnt;
                    183:        char **argv;
                    184:        int maxargs = 16;       /* XXX */
                    185:        int stop;
                    186:
                    187:        stop = 0;
                    188:
1.6       deraadt   189:        if ((argv = calloc(sizeof(char *), maxargs)) == NULL)
1.1       art       190:                err(1, "malloc");
                    191:
                    192:        while (!stop && (elline = el_gets(el, &cnt)) != NULL) {
                    193:                char *line, *orgline;
                    194:                struct clit *cmdp;
                    195:                char **ap;
                    196:                int argc, res;
                    197:                HistEvent ev;
                    198:
1.4       aaron     199:                memset(argv, 0, sizeof(char *) * maxargs);
1.1       art       200:
                    201:                history(hist, &ev, H_ENTER, elline);
                    202:
                    203:                orgline = line = strdup(elline);
1.3       deraadt   204:                if (line == NULL)
                    205:                        err(1, "strdup");
1.1       art       206:
                    207:                argc = 0;
                    208:                for (ap = argv; (*ap = strsep(&line, " \t\n")) != NULL;) {
                    209:                        if (**ap != '\0') {
                    210:                                ++ap;
                    211:                                if (++argc == maxargs)
                    212:                                        break;
                    213:                        }
                    214:                }
                    215:                if (argc == maxargs) {
                    216:                        fprintf(stderr, "Too many arguments\n");
                    217:                        goto cmdout;
                    218:                }
                    219:                if (!argc)
                    220:                        goto cmdout;
                    221:
                    222:                /*
                    223:                 * Editline commands.
                    224:                 */
1.5       otto      225:                if (el_parse(el, argc, (const char **)argv) != -1)
1.1       art       226:                        goto cmdout;
                    227:
                    228:                if ((res = name_to_cmd(argv[0], env->cmds, env->ncmds,
                    229:                    &cmdp)) == 1) {
                    230:                        if (argc - 1 > cmdp->maxargc)
                    231:                                fprintf(stderr, "Too many arguments\n");
                    232:                        else if (argc - 1 < cmdp->minargc)
                    233:                                fprintf(stderr, "Too few arguments\n");
                    234:                        else
                    235:                                stop = (*cmdp->handler)(argc, argv,
                    236:                                    cmdp->arg ? cmdp->arg : env);
                    237:                } else {
                    238:                        fprintf(stderr, "%s command: %s\n",
                    239:                            res == 0 ? "unknown" : "ambiguous", argv[0]);
                    240:                }
                    241: cmdout:
                    242:                free(orgline);
                    243:        }
                    244:        free(argv);
                    245:
                    246:        return stop;
                    247: }
                    248: