diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-10-31 08:42:25 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-10-31 08:42:25 +0000 |
commit | 6ff1c1765c2b4495f0292fe730d9bb9a5daef063 (patch) | |
tree | f9b79c5d3b01533c847610f8410f66661df68535 /lib/libedit/el.c | |
parent | 4c1c60ce562b0cf6d8cb6e2e49e2b53193359874 (diff) |
Update to NetBSD libedit (from Oct 1, 2003), adding some string
cleaning and history bug fixes. The code includes GNU libreadline
functionality, but the corresponding header files are not installed,
since some libreadline functions are missing. There are some minor API
changes, notably:
old: EditLine *el_init(const char *, FILE *, FILE *);
new: EditLine *el_init(const char *, FILE *, FILE *, FILE *);
old: HistEvent *history(History *h, int op, ...);
new: int history(History *h, HistEvent *ev, int op, ...); plus some
changes in operation names. See editline(3) for details.
Tested by djm@, mouring@, jmc@.
ok deraadt@
Diffstat (limited to 'lib/libedit/el.c')
-rw-r--r-- | lib/libedit/el.c | 573 |
1 files changed, 387 insertions, 186 deletions
diff --git a/lib/libedit/el.c b/lib/libedit/el.c index a6f48afa854..d798dad8491 100644 --- a/lib/libedit/el.c +++ b/lib/libedit/el.c @@ -1,5 +1,5 @@ -/* $OpenBSD: el.c,v 1.11 2003/06/02 20:18:40 millert Exp $ */ -/* $NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $ */ +/* $OpenBSD: el.c,v 1.12 2003/10/31 08:42:24 otto Exp $ */ +/* $NetBSD: el.c,v 1.34 2003/09/26 17:44:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,117 +33,105 @@ * SUCH DAMAGE. */ +#include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -static const char rcsid[] = "$OpenBSD: el.c,v 1.11 2003/06/02 20:18:40 millert Exp $"; +static const char rcsid[] = "$OpenBSD: el.c,v 1.12 2003/10/31 08:42:24 otto Exp $"; #endif #endif /* not lint && not SCCSID */ /* * el.c: EditLine interface functions */ -#include "sys.h" - #include <sys/types.h> #include <sys/param.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> -#include <unistd.h> #include "el.h" /* el_init(): * Initialize editline and set default parameters. */ public EditLine * -el_init(prog, fin, fout) - const char *prog; - FILE *fin, *fout; +el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) { - EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); -#ifdef DEBUG - char *tty; -#endif - if (el == NULL) - return NULL; + EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); + + if (el == NULL) + return (NULL); - memset(el, 0, sizeof(EditLine)); + memset(el, 0, sizeof(EditLine)); - el->el_infd = fileno(fin); - el->el_outfile = fout; - el->el_prog = strdup(prog); + el->el_infd = fileno(fin); + el->el_outfile = fout; + el->el_errfile = ferr; + el->el_prog = strdup(prog); -#ifdef DEBUG - if (issetugid() == 0 && (tty = getenv("DEBUGTTY")) != NULL) { - el->el_errfile = fopen(tty, "w"); - if (el->el_errfile == NULL) { - extern errno; - (void)fprintf(stderr, "Cannot open %s (%s).\n", - tty, strerror(errno)); + /* + * Initialize all the modules. Order is important!!! + */ + el->el_flags = 0; + + if (term_init(el) == -1) { + free(el->el_prog); + el_free(el); return NULL; } - } - else -#endif - el->el_errfile = stderr; - - /* - * Initialize all the modules. Order is important!!! - */ - (void)term_init(el); - (void)tty_init(el); - (void)key_init(el); - (void)map_init(el); - (void)ch_init(el); - (void)search_init(el); - (void)hist_init(el); - (void)prompt_init(el); - (void)sig_init(el); - el->el_flags = 0; - - return el; -} /* end el_init */ + (void) key_init(el); + (void) map_init(el); + if (tty_init(el) == -1) + el->el_flags |= NO_TTY; + (void) ch_init(el); + (void) search_init(el); + (void) hist_init(el); + (void) prompt_init(el); + (void) sig_init(el); + (void) read_init(el); + + return (el); +} /* el_end(): * Clean up. */ public void -el_end(el) - EditLine *el; +el_end(EditLine *el) { - if (el == NULL) - return; - el_reset(el); + if (el == NULL) + return; - term_end(el); - tty_end(el); - key_end(el); - map_end(el); - ch_end(el); - search_end(el); - hist_end(el); - prompt_end(el); - sig_end(el); + el_reset(el); - el_free((ptr_t) el->el_prog); - el_free((ptr_t) el); -} /* end el_end */ + term_end(el); + key_end(el); + map_end(el); + tty_end(el); + ch_end(el); + search_end(el); + hist_end(el); + prompt_end(el); + sig_end(el); + + el_free((ptr_t) el->el_prog); + el_free((ptr_t) el); +} /* el_reset(): * Reset the tty and the parser */ public void -el_reset(el) - EditLine *el; +el_reset(EditLine *el) { - tty_cookedmode(el); - ch_reset(el); /* XXX: Do we want that? */ + + tty_cookedmode(el); + ch_reset(el); /* XXX: Do we want that? */ } @@ -153,151 +141,328 @@ el_reset(el) public int el_set(EditLine *el, int op, ...) { - va_list va; - int rv; - - va_start(va, op); - - switch (op) { - case EL_PROMPT: - rv = prompt_set(el, va_arg(va, el_pfunc_t)); - break; - - case EL_TERMINAL: - rv = term_set(el, va_arg(va, char *)); - break; - - case EL_EDITOR: - rv = map_set_editor(el, va_arg(va, char *)); - break; - - case EL_SIGNAL: - if (va_arg(va, int)) - el->el_flags |= HANDLE_SIGNALS; - else - el->el_flags &= ~HANDLE_SIGNALS; - rv = 0; - break; - - case EL_BIND: - case EL_TELLTC: - case EL_SETTC: - case EL_ECHOTC: - case EL_SETTY: + va_list va; + int rv = 0; + + if (el == NULL) + return (-1); + va_start(va, op); + + switch (op) { + case EL_PROMPT: + case EL_RPROMPT: + rv = prompt_set(el, va_arg(va, el_pfunc_t), op); + break; + + case EL_TERMINAL: + rv = term_set(el, va_arg(va, char *)); + break; + + case EL_EDITOR: + rv = map_set_editor(el, va_arg(va, char *)); + break; + + case EL_SIGNAL: + if (va_arg(va, int)) + el->el_flags |= HANDLE_SIGNALS; + else + el->el_flags &= ~HANDLE_SIGNALS; + break; + + case EL_BIND: + case EL_TELLTC: + case EL_SETTC: + case EL_ECHOTC: + case EL_SETTY: { - char *argv[20]; - int i; - for (i = 1; i < 20; i++) - if ((argv[i] = va_arg(va, char *)) == NULL) - break; - - switch (op) { - case EL_BIND: - argv[0] = "bind"; - rv = map_bind(el, i, argv); + const char *argv[20]; + int i; + + for (i = 1; i < 20; i++) + if ((argv[i] = va_arg(va, char *)) == NULL) + break; + + switch (op) { + case EL_BIND: + argv[0] = "bind"; + rv = map_bind(el, i, argv); + break; + + case EL_TELLTC: + argv[0] = "telltc"; + rv = term_telltc(el, i, argv); + break; + + case EL_SETTC: + argv[0] = "settc"; + rv = term_settc(el, i, argv); + break; + + case EL_ECHOTC: + argv[0] = "echotc"; + rv = term_echotc(el, i, argv); + break; + + case EL_SETTY: + argv[0] = "setty"; + rv = tty_stty(el, i, argv); + break; + + default: + rv = -1; + EL_ABORT((el->el_errfile, "Bad op %d\n", op)); + break; + } break; + } - case EL_TELLTC: - argv[0] = "telltc"; - rv = term_telltc(el, i, argv); + case EL_ADDFN: + { + char *name = va_arg(va, char *); + char *help = va_arg(va, char *); + el_func_t func = va_arg(va, el_func_t); + + rv = map_addfunc(el, name, help, func); + break; + } + + case EL_HIST: + { + hist_fun_t func = va_arg(va, hist_fun_t); + ptr_t ptr = va_arg(va, char *); + + rv = hist_set(el, func, ptr); break; + } - case EL_SETTC: - argv[0] = "settc"; - rv = term_settc(el, i, argv); + case EL_EDITMODE: + if (va_arg(va, int)) + el->el_flags &= ~EDIT_DISABLED; + else + el->el_flags |= EDIT_DISABLED; + rv = 0; + break; + + case EL_GETCFN: + { + el_rfunc_t rc = va_arg(va, el_rfunc_t); + rv = el_read_setfn(el, rc); break; + } - case EL_ECHOTC: - argv[0] = "echotc"; - rv = term_echotc(el, i, argv); + case EL_CLIENTDATA: + el->el_data = va_arg(va, void *); break; - case EL_SETTY: - argv[0] = "setty"; - rv = tty_stty(el, i, argv); + case EL_UNBUFFERED: + rv = va_arg(va, int); + if (rv && !(el->el_flags & UNBUFFERED)) { + el->el_flags |= UNBUFFERED; + read_prepare(el); + } else if (!rv && (el->el_flags & UNBUFFERED)) { + el->el_flags &= ~UNBUFFERED; + read_finish(el); + } + rv = 0; break; - default: + default: rv = -1; - abort(); break; - } } - break; - - case EL_ADDFN: + + va_end(va); + return (rv); +} + + +/* el_get(): + * retrieve the editline parameters + */ +public int +el_get(EditLine *el, int op, void *ret) +{ + int rv; + + if (el == NULL || ret == NULL) + return (-1); + switch (op) { + case EL_PROMPT: + case EL_RPROMPT: + rv = prompt_get(el, (void *) &ret, op); + break; + + case EL_EDITOR: + rv = map_get_editor(el, (void *) &ret); + break; + + case EL_SIGNAL: + *((int *) ret) = (el->el_flags & HANDLE_SIGNALS); + rv = 0; + break; + + case EL_EDITMODE: + *((int *) ret) = (!(el->el_flags & EDIT_DISABLED)); + rv = 0; + break; + + case EL_TERMINAL: + term_get(el, (const char **)ret); + rv = 0; + break; + +#if 0 /* XXX */ + case EL_BIND: + case EL_TELLTC: + case EL_SETTC: + case EL_ECHOTC: + case EL_SETTY: { - char *name = va_arg(va, char *); - char *help = va_arg(va, char *); - el_func_t func = va_arg(va, el_func_t); - rv = map_addfunc(el, name, help, func); + const char *argv[20]; + int i; + + for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++) + if ((argv[i] = va_arg(va, char *)) == NULL) + break; + + switch (op) { + case EL_BIND: + argv[0] = "bind"; + rv = map_bind(el, i, argv); + break; + + case EL_TELLTC: + argv[0] = "telltc"; + rv = term_telltc(el, i, argv); + break; + + case EL_SETTC: + argv[0] = "settc"; + rv = term_settc(el, i, argv); + break; + + case EL_ECHOTC: + argv[0] = "echotc"; + rv = term_echotc(el, i, argv); + break; + + case EL_SETTY: + argv[0] = "setty"; + rv = tty_stty(el, i, argv); + break; + + default: + rv = -1; + EL_ABORT((el->errfile, "Bad op %d\n", op)); + break; + } + break; } - break; - case EL_HIST: + case EL_ADDFN: { - hist_fun_t func = va_arg(va, hist_fun_t); - ptr_t ptr = va_arg(va, char *); - rv = hist_set(el, func, ptr); + char *name = va_arg(va, char *); + char *help = va_arg(va, char *); + el_func_t func = va_arg(va, el_func_t); + + rv = map_addfunc(el, name, help, func); + break; } - break; - default: - rv = -1; - } + case EL_HIST: + { + hist_fun_t func = va_arg(va, hist_fun_t); + ptr_t ptr = va_arg(va, char *); + rv = hist_set(el, func, ptr); + } + break; +#endif /* XXX */ + + case EL_GETCFN: + *((el_rfunc_t *)ret) = el_read_getfn(el); + rv = 0; + break; + + case EL_CLIENTDATA: + *((void **)ret) = el->el_data; + rv = 0; + break; + + case EL_UNBUFFERED: + *((int *) ret) = (!(el->el_flags & UNBUFFERED)); + rv = 0; + break; + + default: + rv = -1; + } - va_end(va); - return rv; -} /* end el_set */ + return (rv); +} /* el_line(): * Return editing info */ public const LineInfo * -el_line(el) - EditLine *el; +el_line(EditLine *el) { - return (const LineInfo *) &el->el_line; + + return (const LineInfo *) (void *) &el->el_line; } -static const char elpath[] = "/.editrc"; /* el_source(): * Source a file */ public int -el_source(el, fname) - EditLine *el; - const char *fname; +el_source(EditLine *el, const char *fname) { - FILE *fp; - size_t len; - char *ptr, path[MAXPATHLEN]; - - if (fname == NULL) { - ptr = getenv("HOME"); - if (issetugid() != 0 || ptr == NULL || *ptr == '\0') - return -1; - (void) snprintf(path, sizeof(path), "%s%s", ptr, elpath); - fname = path; - } - - if ((fp = fopen(fname, "r")) == NULL) - return -1; - - while ((ptr = fgetln(fp, &len)) != NULL) { - if (ptr[len - 1] == '\n') - --len; - ptr[len] = '\0'; - if (parse_line(el, ptr) == -1) { - (void)fclose(fp); - return -1; + FILE *fp; + size_t len; + char *ptr; + + fp = NULL; + if (fname == NULL) { +#ifdef HAVE_ISSETUGID + static const char elpath[] = "/.editrc"; + char path[MAXPATHLEN]; + + if (issetugid()) + return (-1); + if ((ptr = getenv("HOME")) == NULL) + return (-1); + if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) + return (-1); + if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) + return (-1); + fname = path; +#else + /* + * If issetugid() is missing, always return an error, in order + * to keep from inadvertently opening up the user to a security + * hole. + */ + return (-1); +#endif + } + if (fp == NULL) + fp = fopen(fname, "r"); + if (fp == NULL) + return (-1); + + while ((ptr = fgetln(fp, &len)) != NULL) { + if (len > 0 && ptr[len - 1] == '\n') + --len; + ptr[len] = '\0'; + if (parse_line(el, ptr) == -1) { + (void) fclose(fp); + return (-1); + } } - } - (void)fclose(fp); - return 0; + (void) fclose(fp); + return (0); } @@ -305,18 +470,54 @@ el_source(el, fname) * Called from program when terminal is resized */ public void -el_resize(el) - EditLine *el; +el_resize(EditLine *el) +{ + int lins, cols; + sigset_t oset, nset; + + (void) sigemptyset(&nset); + (void) sigaddset(&nset, SIGWINCH); + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + /* get the correct window size */ + if (term_get_size(el, &lins, &cols)) + term_change_size(el, lins, cols); + + (void) sigprocmask(SIG_SETMASK, &oset, NULL); +} + + +/* el_beep(): + * Called from the program to beep + */ +public void +el_beep(EditLine *el) { - int lins, cols; - sigset_t oset, nset; - (void)sigemptyset(&nset); - (void)sigaddset(&nset, SIGWINCH); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - /* get the correct window size */ - if (term_get_size(el, &lins, &cols)) - term_change_size(el, lins, cols); + term_beep(el); +} + - (void)sigprocmask(SIG_SETMASK, &oset, NULL); +/* el_editmode() + * Set the state of EDIT_DISABLED from the `edit' command. + */ +protected int +/*ARGSUSED*/ +el_editmode(EditLine *el, int argc, const char **argv) +{ + const char *how; + + if (argv == NULL || argc != 2 || argv[1] == NULL) + return (-1); + + how = argv[1]; + if (strcmp(how, "on") == 0) + el->el_flags &= ~EDIT_DISABLED; + else if (strcmp(how, "off") == 0) + el->el_flags |= EDIT_DISABLED; + else { + (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how); + return (-1); + } + return (0); } |