el.c

Go to the documentation of this file.
00001 /* $NetBSD: el.c,v 1.29 2002/03/18 16:00:52 christos Exp $  */
00002 
00003 /*-
00004  * Copyright (c) 1992, 1993
00005  * The Regents of the University of California.  All rights reserved.
00006  *
00007  * This code is derived from software contributed to Berkeley by
00008  * Christos Zoulas of Cornell University.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  * 3. All advertising materials mentioning features or use of this software
00019  *    must display the following acknowledgement:
00020  * This product includes software developed by the University of
00021  * California, Berkeley and its contributors.
00022  * 4. Neither the name of the University nor the names of its contributors
00023  *    may be used to endorse or promote products derived from this software
00024  *    without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00027  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00030  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00031  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00032  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00033  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00034  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00035  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00036  * SUCH DAMAGE.
00037  */
00038 
00039 #include "config.h"
00040 #if !defined(lint) && !defined(SCCSID)
00041 #if 0
00042 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
00043 #else
00044 __RCSID("$NetBSD: el.c,v 1.29 2002/03/18 16:00:52 christos Exp $");
00045 #endif
00046 #endif /* not lint && not SCCSID */
00047 
00048 /*
00049  * el.c: EditLine interface functions
00050  */
00051 #include <sys/types.h>
00052 #include <sys/param.h>
00053 #include <string.h>
00054 #include <stdlib.h>
00055 #include <stdarg.h>
00056 #include "el.h"
00057 
00058 /* el_init():
00059  * Initialize editline and set default parameters.
00060  */
00061 public EditLine *
00062 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
00063 {
00064 
00065    EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
00066 
00067    if (el == NULL)
00068       return (NULL);
00069 
00070    memset(el, 0, sizeof(EditLine));
00071 
00072    el->el_infd = fileno(fin);
00073    el->el_outfile = fout;
00074    el->el_errfile = ferr;
00075    el->el_prog = strdup(prog);
00076 
00077    /*
00078          * Initialize all the modules. Order is important!!!
00079          */
00080    el->el_flags = 0;
00081 
00082    if (term_init(el) == -1) {
00083       free(el->el_prog);
00084       el_free(el);
00085       return NULL;
00086    }
00087    (void) key_init(el);
00088    (void) map_init(el);
00089    if (tty_init(el) == -1)
00090       el->el_flags |= NO_TTY;
00091    (void) ch_init(el);
00092    (void) search_init(el);
00093    (void) hist_init(el);
00094    (void) prompt_init(el);
00095    (void) sig_init(el);
00096    (void) read_init(el);
00097 
00098    return (el);
00099 }
00100 
00101 
00102 /* el_end():
00103  * Clean up.
00104  */
00105 public void
00106 el_end(EditLine *el)
00107 {
00108 
00109    if (el == NULL)
00110       return;
00111 
00112    el_reset(el);
00113 
00114    term_end(el);
00115    key_end(el);
00116    map_end(el);
00117    tty_end(el);
00118    ch_end(el);
00119    search_end(el);
00120    hist_end(el);
00121    prompt_end(el);
00122    sig_end(el);
00123 
00124    if (el->el_prog)
00125       el_free((ptr_t) el->el_prog);
00126    el_free((ptr_t) el);
00127 }
00128 
00129 
00130 /* el_reset():
00131  * Reset the tty and the parser
00132  */
00133 public void
00134 el_reset(EditLine *el)
00135 {
00136 
00137    tty_cookedmode(el);
00138    ch_reset(el);     /* XXX: Do we want that? */
00139 }
00140 
00141 
00142 /* el_set():
00143  * set the editline parameters
00144  */
00145 public int
00146 el_set(EditLine *el, int op, ...)
00147 {
00148    va_list va;
00149    int rv = 0;
00150 
00151    if (el == NULL)
00152       return (-1);
00153    va_start(va, op);
00154 
00155    switch (op) {
00156    case EL_PROMPT:
00157    case EL_RPROMPT:
00158       rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
00159       break;
00160 
00161    case EL_TERMINAL:
00162       rv = term_set(el, va_arg(va, char *));
00163       break;
00164 
00165    case EL_EDITOR:
00166       rv = map_set_editor(el, va_arg(va, char *));
00167       break;
00168 
00169    case EL_SIGNAL:
00170       if (va_arg(va, int))
00171          el->el_flags |= HANDLE_SIGNALS;
00172       else
00173          el->el_flags &= ~HANDLE_SIGNALS;
00174       break;
00175 
00176    case EL_BIND:
00177    case EL_TELLTC:
00178    case EL_SETTC:
00179    case EL_ECHOTC:
00180    case EL_SETTY:
00181    {
00182       const char *argv[20];
00183       int i;
00184 
00185       for (i = 1; i < 20; i++)
00186          if ((argv[i] = va_arg(va, char *)) == NULL)
00187             break;
00188 
00189       switch (op) {
00190       case EL_BIND:
00191          argv[0] = "bind";
00192          rv = map_bind(el, i, argv);
00193          break;
00194 
00195       case EL_TELLTC:
00196          argv[0] = "telltc";
00197          rv = term_telltc(el, i, argv);
00198          break;
00199 
00200       case EL_SETTC:
00201          argv[0] = "settc";
00202          rv = term_settc(el, i, argv);
00203          break;
00204 
00205       case EL_ECHOTC:
00206          argv[0] = "echotc";
00207          rv = term_echotc(el, i, argv);
00208          break;
00209 
00210       case EL_SETTY:
00211          argv[0] = "setty";
00212          rv = tty_stty(el, i, argv);
00213          break;
00214 
00215       default:
00216          rv = -1;
00217          EL_ABORT((el->el_errfile, "Bad op %d\n", op));
00218          break;
00219       }
00220       break;
00221    }
00222 
00223    case EL_ADDFN:
00224    {
00225       char *name = va_arg(va, char *);
00226       char *help = va_arg(va, char *);
00227       el_func_t func = va_arg(va, el_func_t);
00228 
00229       rv = map_addfunc(el, name, help, func);
00230       break;
00231    }
00232 
00233    case EL_HIST:
00234    {
00235       hist_fun_t func = va_arg(va, hist_fun_t);
00236       ptr_t ptr = va_arg(va, char *);
00237 
00238       rv = hist_set(el, func, ptr);
00239       break;
00240    }
00241 
00242    case EL_EDITMODE:
00243       if (va_arg(va, int))
00244          el->el_flags &= ~EDIT_DISABLED;
00245       else
00246          el->el_flags |= EDIT_DISABLED;
00247       rv = 0;
00248       break;
00249 
00250    case EL_GETCFN:
00251    {
00252       el_rfunc_t rc = va_arg(va, el_rfunc_t);
00253       rv = el_read_setfn(el, rc);
00254       break;
00255    }
00256 
00257    case EL_CLIENTDATA:
00258       el->el_data = va_arg(va, void *);
00259       break;
00260 
00261    default:
00262       rv = -1;
00263       break;
00264    }
00265 
00266    va_end(va);
00267    return (rv);
00268 }
00269 
00270 
00271 /* el_get():
00272  * retrieve the editline parameters
00273  */
00274 public int
00275 el_get(EditLine *el, int op, void *ret)
00276 {
00277    int rv;
00278 
00279    if (el == NULL || ret == NULL)
00280       return (-1);
00281    switch (op) {
00282    case EL_PROMPT:
00283    case EL_RPROMPT:
00284       rv = prompt_get(el, (el_pfunc_t *) & ret, op);
00285       break;
00286 
00287    case EL_EDITOR:
00288       rv = map_get_editor(el, (const char **) &ret);
00289       break;
00290 
00291    case EL_SIGNAL:
00292       *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
00293       rv = 0;
00294       break;
00295 
00296    case EL_EDITMODE:
00297       *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
00298       rv = 0;
00299       break;
00300 
00301 #if 0          /* XXX */
00302    case EL_TERMINAL:
00303       rv = term_get(el, (const char *) &ret);
00304       break;
00305 
00306    case EL_BIND:
00307    case EL_TELLTC:
00308    case EL_SETTC:
00309    case EL_ECHOTC:
00310    case EL_SETTY:
00311    {
00312       char *argv[20];
00313       int i;
00314 
00315       for (i = 1; i < 20; i++)
00316          if ((argv[i] = va_arg(va, char *)) == NULL)
00317             break;
00318 
00319       switch (op) {
00320       case EL_BIND:
00321          argv[0] = "bind";
00322          rv = map_bind(el, i, argv);
00323          break;
00324 
00325       case EL_TELLTC:
00326          argv[0] = "telltc";
00327          rv = term_telltc(el, i, argv);
00328          break;
00329 
00330       case EL_SETTC:
00331          argv[0] = "settc";
00332          rv = term_settc(el, i, argv);
00333          break;
00334 
00335       case EL_ECHOTC:
00336          argv[0] = "echotc";
00337          rv = term_echotc(el, i, argv);
00338          break;
00339 
00340       case EL_SETTY:
00341          argv[0] = "setty";
00342          rv = tty_stty(el, i, argv);
00343          break;
00344 
00345       default:
00346          rv = -1;
00347          EL_ABORT((el->errfile, "Bad op %d\n", op));
00348          break;
00349       }
00350       break;
00351    }
00352 
00353    case EL_ADDFN:
00354    {
00355       char *name = va_arg(va, char *);
00356       char *help = va_arg(va, char *);
00357       el_func_t func = va_arg(va, el_func_t);
00358 
00359       rv = map_addfunc(el, name, help, func);
00360       break;
00361    }
00362 
00363    case EL_HIST:
00364       {
00365          hist_fun_t func = va_arg(va, hist_fun_t);
00366          ptr_t ptr = va_arg(va, char *);
00367          rv = hist_set(el, func, ptr);
00368       }
00369       break;
00370 #endif /* XXX */
00371 
00372    case EL_GETCFN:
00373       *((el_rfunc_t *)ret) = el_read_getfn(el);
00374       rv = 0;
00375       break;
00376 
00377    case EL_CLIENTDATA:
00378       *((void **)ret) = el->el_data;
00379       rv = 0;
00380       break;
00381 
00382    default:
00383       rv = -1;
00384    }
00385 
00386    return (rv);
00387 }
00388 
00389 
00390 /* el_line():
00391  * Return editing info
00392  */
00393 public const LineInfo *
00394 el_line(EditLine *el)
00395 {
00396 
00397    return (const LineInfo *) (void *) &el->el_line;
00398 }
00399 
00400 
00401 /* el_source():
00402  * Source a file
00403  */
00404 public int
00405 el_source(EditLine *el, const char *fname)
00406 {
00407    FILE *fp;
00408    size_t len;
00409    char *ptr;
00410 
00411    fp = NULL;
00412    if (fname == NULL) {
00413 #ifdef HAVE_ISSETUGID
00414       static const char elpath[] = "/.editrc";
00415       char path[MAXPATHLEN];
00416 
00417       if (issetugid())
00418          return (-1);
00419       if ((ptr = getenv("HOME")) == NULL)
00420          return (-1);
00421       if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
00422          return (-1);
00423       if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
00424          return (-1);
00425       fname = path;
00426 #else
00427       /*
00428        * If issetugid() is missing, always return an error, in order
00429        * to keep from inadvertently opening up the user to a security
00430        * hole.
00431        */
00432       return (-1);
00433 #endif
00434    }
00435    if (fp == NULL)
00436       fp = fopen(fname, "r");
00437    if (fp == NULL)
00438       return (-1);
00439 
00440    while ((ptr = fgetln(fp, &len)) != NULL) {
00441       if (len > 0 && ptr[len - 1] == '\n')
00442          --len;
00443       ptr[len] = '\0';
00444       if (parse_line(el, ptr) == -1) {
00445          (void) fclose(fp);
00446          return (-1);
00447       }
00448    }
00449 
00450    (void) fclose(fp);
00451    return (0);
00452 }
00453 
00454 
00455 /* el_resize():
00456  * Called from program when terminal is resized
00457  */
00458 public void
00459 el_resize(EditLine *el)
00460 {
00461    int lins, cols;
00462    sigset_t oset, nset;
00463 
00464    (void) sigemptyset(&nset);
00465    (void) sigaddset(&nset, SIGWINCH);
00466    (void) sigprocmask(SIG_BLOCK, &nset, &oset);
00467 
00468    /* get the correct window size */
00469    if (term_get_size(el, &lins, &cols))
00470       term_change_size(el, lins, cols);
00471 
00472    (void) sigprocmask(SIG_SETMASK, &oset, NULL);
00473 }
00474 
00475 
00476 /* el_beep():
00477  * Called from the program to beep
00478  */
00479 public void
00480 el_beep(EditLine *el)
00481 {
00482 
00483    term_beep(el);
00484 }
00485 
00486 
00487 /* el_editmode()
00488  * Set the state of EDIT_DISABLED from the `edit' command.
00489  */
00490 protected int
00491 /*ARGSUSED*/
00492 el_editmode(EditLine *el, int argc, const char **argv)
00493 {
00494    const char *how;
00495 
00496    if (argv == NULL || argc != 2 || argv[1] == NULL)
00497       return (-1);
00498 
00499    how = argv[1];
00500    if (strcmp(how, "on") == 0)
00501       el->el_flags &= ~EDIT_DISABLED;
00502    else if (strcmp(how, "off") == 0)
00503       el->el_flags |= EDIT_DISABLED;
00504    else {
00505       (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
00506       return (-1);
00507    }
00508    return (0);
00509 }

Generated on Thu Apr 16 06:27:33 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6