[BACK]Return to el.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libedit

Annotation of src/lib/libedit/el.c, Revision 1.47.2.1

1.47.2.1! jym         1: /*     $NetBSD: el.c,v 1.52 2009/05/11 18:33:30 christos Exp $ */
1.2       lukem       2:
1.1       cgd         3: /*-
                      4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Christos Zoulas of Cornell University.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
1.32      agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
1.29      christos   35: #include "config.h"
1.1       cgd        36: #if !defined(lint) && !defined(SCCSID)
1.2       lukem      37: #if 0
1.1       cgd        38: static char sccsid[] = "@(#)el.c       8.2 (Berkeley) 1/3/94";
1.2       lukem      39: #else
1.47.2.1! jym        40: __RCSID("$NetBSD: el.c,v 1.52 2009/05/11 18:33:30 christos Exp $");
1.2       lukem      41: #endif
1.1       cgd        42: #endif /* not lint && not SCCSID */
                     43:
                     44: /*
                     45:  * el.c: EditLine interface functions
                     46:  */
                     47: #include <sys/types.h>
                     48: #include <sys/param.h>
                     49: #include <string.h>
                     50: #include <stdlib.h>
1.19      lukem      51: #include <stdarg.h>
1.1       cgd        52: #include "el.h"
                     53:
                     54: /* el_init():
                     55:  *     Initialize editline and set default parameters.
                     56:  */
                     57: public EditLine *
1.19      lukem      58: el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
1.1       cgd        59: {
1.18      chuck      60:
1.19      lukem      61:        EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
1.1       cgd        62:
1.19      lukem      63:        if (el == NULL)
                     64:                return (NULL);
1.1       cgd        65:
1.19      lukem      66:        memset(el, 0, sizeof(EditLine));
1.1       cgd        67:
1.44      christos   68:        el->el_infile = fin;
1.19      lukem      69:        el->el_outfile = fout;
                     70:        el->el_errfile = ferr;
1.44      christos   71:
                     72:        el->el_infd = fileno(fin);
                     73:
1.36      christos   74:        if ((el->el_prog = el_strdup(prog)) == NULL) {
                     75:                el_free(el);
                     76:                return NULL;
                     77:        }
1.19      lukem      78:
                     79:        /*
                     80:          * Initialize all the modules. Order is important!!!
                     81:          */
                     82:        el->el_flags = 0;
                     83:
1.25      christos   84:        if (term_init(el) == -1) {
1.36      christos   85:                el_free(el->el_prog);
1.25      christos   86:                el_free(el);
                     87:                return NULL;
                     88:        }
1.19      lukem      89:        (void) key_init(el);
                     90:        (void) map_init(el);
                     91:        if (tty_init(el) == -1)
                     92:                el->el_flags |= NO_TTY;
                     93:        (void) ch_init(el);
                     94:        (void) search_init(el);
                     95:        (void) hist_init(el);
                     96:        (void) prompt_init(el);
                     97:        (void) sig_init(el);
1.23      christos   98:        (void) read_init(el);
1.1       cgd        99:
1.19      lukem     100:        return (el);
                    101: }
1.1       cgd       102:
                    103:
                    104: /* el_end():
                    105:  *     Clean up.
                    106:  */
                    107: public void
1.19      lukem     108: el_end(EditLine *el)
1.1       cgd       109: {
                    110:
1.19      lukem     111:        if (el == NULL)
                    112:                return;
1.1       cgd       113:
1.19      lukem     114:        el_reset(el);
                    115:
                    116:        term_end(el);
                    117:        key_end(el);
                    118:        map_end(el);
                    119:        tty_end(el);
                    120:        ch_end(el);
                    121:        search_end(el);
                    122:        hist_end(el);
                    123:        prompt_end(el);
                    124:        sig_end(el);
                    125:
                    126:        el_free((ptr_t) el->el_prog);
                    127:        el_free((ptr_t) el);
                    128: }
1.1       cgd       129:
                    130:
                    131: /* el_reset():
                    132:  *     Reset the tty and the parser
                    133:  */
                    134: public void
1.19      lukem     135: el_reset(EditLine *el)
1.1       cgd       136: {
1.19      lukem     137:
                    138:        tty_cookedmode(el);
1.40      christos  139:        ch_reset(el, 0);                /* XXX: Do we want that? */
1.1       cgd       140: }
                    141:
                    142:
                    143: /* el_set():
                    144:  *     set the editline parameters
                    145:  */
                    146: public int
                    147: el_set(EditLine *el, int op, ...)
                    148: {
1.44      christos  149:        va_list ap;
1.27      christos  150:        int rv = 0;
1.1       cgd       151:
1.19      lukem     152:        if (el == NULL)
                    153:                return (-1);
1.44      christos  154:        va_start(ap, op);
1.22      wiz       155:
1.19      lukem     156:        switch (op) {
                    157:        case EL_PROMPT:
1.47.2.1! jym       158:        case EL_RPROMPT: {
        !           159:                el_pfunc_t p = va_arg(ap, el_pfunc_t);
        !           160:
        !           161:                rv = prompt_set(el, p, 0, op);
        !           162:                break;
        !           163:        }
        !           164:
        !           165:        case EL_PROMPT_ESC:
        !           166:        case EL_RPROMPT_ESC: {
        !           167:                el_pfunc_t p = va_arg(ap, el_pfunc_t);
        !           168:                char c = va_arg(ap, int);
        !           169:
        !           170:                rv = prompt_set(el, p, c, op);
1.19      lukem     171:                break;
1.47.2.1! jym       172:        }
1.13      simonb    173:
1.19      lukem     174:        case EL_TERMINAL:
1.44      christos  175:                rv = term_set(el, va_arg(ap, char *));
1.19      lukem     176:                break;
1.1       cgd       177:
1.19      lukem     178:        case EL_EDITOR:
1.44      christos  179:                rv = map_set_editor(el, va_arg(ap, char *));
1.1       cgd       180:                break;
                    181:
1.19      lukem     182:        case EL_SIGNAL:
1.44      christos  183:                if (va_arg(ap, int))
1.19      lukem     184:                        el->el_flags |= HANDLE_SIGNALS;
                    185:                else
                    186:                        el->el_flags &= ~HANDLE_SIGNALS;
1.1       cgd       187:                break;
                    188:
1.19      lukem     189:        case EL_BIND:
                    190:        case EL_TELLTC:
                    191:        case EL_SETTC:
1.42      christos  192:        case EL_GETTC:
1.19      lukem     193:        case EL_ECHOTC:
                    194:        case EL_SETTY:
                    195:        {
1.29      christos  196:                const char *argv[20];
1.19      lukem     197:                int i;
                    198:
                    199:                for (i = 1; i < 20; i++)
1.44      christos  200:                        if ((argv[i] = va_arg(ap, char *)) == NULL)
1.19      lukem     201:                                break;
                    202:
                    203:                switch (op) {
                    204:                case EL_BIND:
                    205:                        argv[0] = "bind";
                    206:                        rv = map_bind(el, i, argv);
                    207:                        break;
                    208:
                    209:                case EL_TELLTC:
                    210:                        argv[0] = "telltc";
                    211:                        rv = term_telltc(el, i, argv);
                    212:                        break;
                    213:
                    214:                case EL_SETTC:
                    215:                        argv[0] = "settc";
                    216:                        rv = term_settc(el, i, argv);
                    217:                        break;
                    218:
                    219:                case EL_ECHOTC:
                    220:                        argv[0] = "echotc";
                    221:                        rv = term_echotc(el, i, argv);
                    222:                        break;
                    223:
                    224:                case EL_SETTY:
                    225:                        argv[0] = "setty";
                    226:                        rv = tty_stty(el, i, argv);
                    227:                        break;
                    228:
                    229:                default:
                    230:                        rv = -1;
1.20      christos  231:                        EL_ABORT((el->el_errfile, "Bad op %d\n", op));
1.19      lukem     232:                        break;
                    233:                }
1.1       cgd       234:                break;
1.19      lukem     235:        }
                    236:
                    237:        case EL_ADDFN:
                    238:        {
1.44      christos  239:                char *name = va_arg(ap, char *);
                    240:                char *help = va_arg(ap, char *);
                    241:                el_func_t func = va_arg(ap, el_func_t);
1.1       cgd       242:
1.19      lukem     243:                rv = map_addfunc(el, name, help, func);
1.1       cgd       244:                break;
1.19      lukem     245:        }
                    246:
                    247:        case EL_HIST:
                    248:        {
1.44      christos  249:                hist_fun_t func = va_arg(ap, hist_fun_t);
                    250:                ptr_t ptr = va_arg(ap, char *);
1.1       cgd       251:
1.19      lukem     252:                rv = hist_set(el, func, ptr);
1.1       cgd       253:                break;
1.19      lukem     254:        }
1.1       cgd       255:
1.19      lukem     256:        case EL_EDITMODE:
1.44      christos  257:                if (va_arg(ap, int))
1.19      lukem     258:                        el->el_flags &= ~EDIT_DISABLED;
                    259:                else
                    260:                        el->el_flags |= EDIT_DISABLED;
                    261:                rv = 0;
1.1       cgd       262:                break;
1.13      simonb    263:
1.23      christos  264:        case EL_GETCFN:
                    265:        {
1.44      christos  266:                el_rfunc_t rc = va_arg(ap, el_rfunc_t);
1.23      christos  267:                rv = el_read_setfn(el, rc);
                    268:                break;
                    269:        }
                    270:
1.24      christos  271:        case EL_CLIENTDATA:
1.44      christos  272:                el->el_data = va_arg(ap, void *);
1.24      christos  273:                break;
                    274:
1.34      christos  275:        case EL_UNBUFFERED:
1.44      christos  276:                rv = va_arg(ap, int);
1.34      christos  277:                if (rv && !(el->el_flags & UNBUFFERED)) {
                    278:                        el->el_flags |= UNBUFFERED;
                    279:                        read_prepare(el);
                    280:                } else if (!rv && (el->el_flags & UNBUFFERED)) {
                    281:                        el->el_flags &= ~UNBUFFERED;
                    282:                        read_finish(el);
                    283:                }
1.35      christos  284:                rv = 0;
                    285:                break;
                    286:
                    287:        case EL_PREP_TERM:
1.44      christos  288:                rv = va_arg(ap, int);
1.35      christos  289:                if (rv)
1.38      christos  290:                        (void) tty_rawmode(el);
1.35      christos  291:                else
1.38      christos  292:                        (void) tty_cookedmode(el);
1.34      christos  293:                rv = 0;
                    294:                break;
                    295:
1.44      christos  296:        case EL_SETFP:
                    297:        {
                    298:                FILE *fp;
                    299:                int what;
                    300:
                    301:                what = va_arg(ap, int);
                    302:                fp = va_arg(ap, FILE *);
                    303:
                    304:                rv = 0;
                    305:                switch (what) {
                    306:                case 0:
                    307:                        el->el_infile = fp;
                    308:                        el->el_infd = fileno(fp);
                    309:                        break;
                    310:                case 1:
                    311:                        el->el_outfile = fp;
                    312:                        break;
                    313:                case 2:
                    314:                        el->el_errfile = fp;
                    315:                        break;
                    316:                default:
                    317:                        rv = -1;
                    318:                        break;
                    319:                }
                    320:                break;
                    321:        }
                    322:
1.45      christos  323:        case EL_REFRESH:
                    324:                re_clear_display(el);
                    325:                re_refresh(el);
1.46      christos  326:                term__flush(el);
1.45      christos  327:                break;
                    328:
1.19      lukem     329:        default:
                    330:                rv = -1;
1.27      christos  331:                break;
1.1       cgd       332:        }
                    333:
1.44      christos  334:        va_end(ap);
1.19      lukem     335:        return (rv);
                    336: }
1.1       cgd       337:
                    338:
1.10      lukem     339: /* el_get():
                    340:  *     retrieve the editline parameters
                    341:  */
                    342: public int
1.42      christos  343: el_get(EditLine *el, int op, ...)
1.10      lukem     344: {
1.42      christos  345:        va_list ap;
1.19      lukem     346:        int rv;
1.10      lukem     347:
1.42      christos  348:        if (el == NULL)
                    349:                return -1;
                    350:
                    351:        va_start(ap, op);
                    352:
1.19      lukem     353:        switch (op) {
                    354:        case EL_PROMPT:
1.47.2.1! jym       355:        case EL_RPROMPT: {
        !           356:                el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
        !           357:                char *c = va_arg(ap, char *);
        !           358:
        !           359:                rv = prompt_get(el, p, c, op);
1.19      lukem     360:                break;
1.47.2.1! jym       361:        }
1.10      lukem     362:
1.19      lukem     363:        case EL_EDITOR:
1.42      christos  364:                rv = map_get_editor(el, va_arg(ap, const char **));
1.10      lukem     365:                break;
                    366:
1.19      lukem     367:        case EL_SIGNAL:
1.42      christos  368:                *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
1.19      lukem     369:                rv = 0;
1.10      lukem     370:                break;
                    371:
1.19      lukem     372:        case EL_EDITMODE:
1.42      christos  373:                *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
1.19      lukem     374:                rv = 0;
1.10      lukem     375:                break;
                    376:
1.19      lukem     377:        case EL_TERMINAL:
1.42      christos  378:                term_get(el, va_arg(ap, const char **));
1.33      christos  379:                rv = 0;
1.10      lukem     380:                break;
                    381:
1.42      christos  382:        case EL_GETTC:
1.19      lukem     383:        {
1.42      christos  384:                static char name[] = "gettc";
                    385:                char *argv[20];
1.19      lukem     386:                int i;
1.10      lukem     387:
1.47      lukem     388:                for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++)
1.42      christos  389:                        if ((argv[i] = va_arg(ap, char *)) == NULL)
1.19      lukem     390:                                break;
                    391:
                    392:                switch (op) {
1.42      christos  393:                case EL_GETTC:
                    394:                        argv[0] = name;
                    395:                        rv = term_gettc(el, i, argv);
1.19      lukem     396:                        break;
                    397:
                    398:                default:
                    399:                        rv = -1;
1.43      freza     400:                        EL_ABORT((el->el_errfile, "Bad op %d\n", op));
1.19      lukem     401:                        break;
                    402:                }
1.10      lukem     403:                break;
                    404:        }
1.13      simonb    405:
1.42      christos  406: #if 0 /* XXX */
1.19      lukem     407:        case EL_ADDFN:
1.10      lukem     408:        {
1.44      christos  409:                char *name = va_arg(ap, char *);
                    410:                char *help = va_arg(ap, char *);
                    411:                el_func_t func = va_arg(ap, el_func_t);
1.19      lukem     412:
                    413:                rv = map_addfunc(el, name, help, func);
                    414:                break;
1.10      lukem     415:        }
                    416:
1.19      lukem     417:        case EL_HIST:
                    418:                {
1.44      christos  419:                        hist_fun_t func = va_arg(ap, hist_fun_t);
                    420:                        ptr_t ptr = va_arg(ap, char *);
1.19      lukem     421:                        rv = hist_set(el, func, ptr);
                    422:                }
                    423:                break;
                    424: #endif /* XXX */
1.23      christos  425:
                    426:        case EL_GETCFN:
1.42      christos  427:                *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
1.24      christos  428:                rv = 0;
                    429:                break;
                    430:
                    431:        case EL_CLIENTDATA:
1.42      christos  432:                *va_arg(ap, void **) = el->el_data;
1.34      christos  433:                rv = 0;
                    434:                break;
                    435:
                    436:        case EL_UNBUFFERED:
1.42      christos  437:                *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
1.23      christos  438:                rv = 0;
                    439:                break;
1.19      lukem     440:
1.44      christos  441:        case EL_GETFP:
                    442:        {
                    443:                int what;
                    444:                FILE **fpp;
                    445:
                    446:                what = va_arg(ap, int);
                    447:                fpp = va_arg(ap, FILE **);
                    448:                rv = 0;
                    449:                switch (what) {
                    450:                case 0:
                    451:                        *fpp = el->el_infile;
                    452:                        break;
                    453:                case 1:
                    454:                        *fpp = el->el_outfile;
                    455:                        break;
                    456:                case 2:
                    457:                        *fpp = el->el_errfile;
                    458:                        break;
                    459:                default:
                    460:                        rv = -1;
                    461:                        break;
                    462:                }
                    463:                break;
                    464:        }
1.19      lukem     465:        default:
                    466:                rv = -1;
1.44      christos  467:                break;
1.19      lukem     468:        }
1.42      christos  469:        va_end(ap);
1.10      lukem     470:
1.19      lukem     471:        return (rv);
                    472: }
1.10      lukem     473:
                    474:
1.1       cgd       475: /* el_line():
                    476:  *     Return editing info
                    477:  */
                    478: public const LineInfo *
1.19      lukem     479: el_line(EditLine *el)
1.1       cgd       480: {
1.19      lukem     481:
                    482:        return (const LineInfo *) (void *) &el->el_line;
1.1       cgd       483: }
                    484:
                    485:
                    486: /* el_source():
                    487:  *     Source a file
                    488:  */
                    489: public int
1.19      lukem     490: el_source(EditLine *el, const char *fname)
1.1       cgd       491: {
1.19      lukem     492:        FILE *fp;
                    493:        size_t len;
1.27      christos  494:        char *ptr;
1.19      lukem     495:
                    496:        fp = NULL;
                    497:        if (fname == NULL) {
1.29      christos  498: #ifdef HAVE_ISSETUGID
1.27      christos  499:                static const char elpath[] = "/.editrc";
                    500:                char path[MAXPATHLEN];
                    501:
1.19      lukem     502:                if (issetugid())
                    503:                        return (-1);
                    504:                if ((ptr = getenv("HOME")) == NULL)
                    505:                        return (-1);
                    506:                if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
                    507:                        return (-1);
                    508:                if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
                    509:                        return (-1);
                    510:                fname = path;
1.27      christos  511: #else
                    512:                /*
                    513:                 * If issetugid() is missing, always return an error, in order
                    514:                 * to keep from inadvertently opening up the user to a security
                    515:                 * hole.
                    516:                 */
                    517:                return (-1);
                    518: #endif
1.19      lukem     519:        }
                    520:        if (fp == NULL)
                    521:                fp = fopen(fname, "r");
                    522:        if (fp == NULL)
                    523:                return (-1);
                    524:
                    525:        while ((ptr = fgetln(fp, &len)) != NULL) {
                    526:                if (len > 0 && ptr[len - 1] == '\n')
                    527:                        --len;
                    528:                ptr[len] = '\0';
                    529:                if (parse_line(el, ptr) == -1) {
                    530:                        (void) fclose(fp);
                    531:                        return (-1);
                    532:                }
1.1       cgd       533:        }
                    534:
1.19      lukem     535:        (void) fclose(fp);
                    536:        return (0);
1.1       cgd       537: }
                    538:
                    539:
                    540: /* el_resize():
                    541:  *     Called from program when terminal is resized
                    542:  */
                    543: public void
1.19      lukem     544: el_resize(EditLine *el)
1.1       cgd       545: {
1.19      lukem     546:        int lins, cols;
                    547:        sigset_t oset, nset;
                    548:
                    549:        (void) sigemptyset(&nset);
                    550:        (void) sigaddset(&nset, SIGWINCH);
                    551:        (void) sigprocmask(SIG_BLOCK, &nset, &oset);
                    552:
                    553:        /* get the correct window size */
                    554:        if (term_get_size(el, &lins, &cols))
                    555:                term_change_size(el, lins, cols);
1.1       cgd       556:
1.19      lukem     557:        (void) sigprocmask(SIG_SETMASK, &oset, NULL);
1.9       christos  558: }
1.14      lukem     559:
1.9       christos  560:
                    561: /* el_beep():
                    562:  *     Called from the program to beep
                    563:  */
                    564: public void
1.19      lukem     565: el_beep(EditLine *el)
1.9       christos  566: {
1.19      lukem     567:
                    568:        term_beep(el);
1.1       cgd       569: }
1.10      lukem     570:
                    571:
                    572: /* el_editmode()
                    573:  *     Set the state of EDIT_DISABLED from the `edit' command.
                    574:  */
                    575: protected int
                    576: /*ARGSUSED*/
1.29      christos  577: el_editmode(EditLine *el, int argc, const char **argv)
1.10      lukem     578: {
1.19      lukem     579:        const char *how;
1.10      lukem     580:
1.19      lukem     581:        if (argv == NULL || argc != 2 || argv[1] == NULL)
                    582:                return (-1);
1.10      lukem     583:
1.19      lukem     584:        how = argv[1];
1.39      christos  585:        if (strcmp(how, "on") == 0) {
1.19      lukem     586:                el->el_flags &= ~EDIT_DISABLED;
1.39      christos  587:                tty_rawmode(el);
                    588:        } else if (strcmp(how, "off") == 0) {
                    589:                tty_cookedmode(el);
1.19      lukem     590:                el->el_flags |= EDIT_DISABLED;
1.39      christos  591:        }
1.19      lukem     592:        else {
                    593:                (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
                    594:                return (-1);
                    595:        }
                    596:        return (0);
                    597: }

CVSweb <webmaster@jp.NetBSD.org>