diff options
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); } |