1 /* $NetBSD: el.c,v 1.70 2012/03/11 21:14:56 christos Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
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
36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
40 __RCSID("$NetBSD: el.c,v 1.70 2012/03/11 21:14:56 christos Exp $");
42 #endif /* not lint && not SCCSID */
45 #define MAXPATHLEN 4096
49 * el.c: EditLine interface functions
51 #include <sys/types.h>
52 #include <sys/param.h>
62 * Initialize editline and set default parameters.
65 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
67 EditLine *el = el_malloc(sizeof(*el));
72 memset(el, 0, sizeof(EditLine));
75 el->el_outfile = fout;
76 el->el_errfile = ferr;
78 el->el_infd = fileno(fin);
79 el->el_outfd = fileno(fout);
80 el->el_errfd = fileno(ferr);
82 el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
83 if (el->el_prog == NULL) {
89 * Initialize all the modules. Order is important!!!
93 if (setlocale(LC_CTYPE, NULL) != NULL){
94 if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
95 el->el_flags |= CHARSET_IS_UTF8;
99 if (terminal_init(el) == -1) {
100 el_free(el->el_prog);
104 (void) keymacro_init(el);
106 if (tty_init(el) == -1)
107 el->el_flags |= NO_TTY;
109 (void) search_init(el);
110 (void) hist_init(el);
111 (void) prompt_init(el);
113 (void) read_init(el);
141 el_free(el->el_prog);
143 el_free(el->el_scratch.cbuff);
144 el_free(el->el_scratch.wbuff);
145 el_free(el->el_lgcyconv.cbuff);
146 el_free(el->el_lgcyconv.wbuff);
153 * Reset the tty and the parser
156 el_reset(EditLine *el)
160 ch_reset(el, 0); /* XXX: Do we want that? */
165 * set the editline parameters
168 FUN(el,set)(EditLine *el, int op, ...)
180 el_pfunc_t p = va_arg(ap, el_pfunc_t);
182 rv = prompt_set(el, p, 0, op, 1);
187 el_zfunc_t p = va_arg(ap, el_zfunc_t);
188 void *arg = va_arg(ap, void *);
189 rv = ch_resizefun(el, p, arg);
194 case EL_RPROMPT_ESC: {
195 el_pfunc_t p = va_arg(ap, el_pfunc_t);
196 int c = va_arg(ap, int);
198 rv = prompt_set(el, p, c, op, 1);
203 rv = terminal_set(el, va_arg(ap, char *));
207 rv = map_set_editor(el, va_arg(ap, Char *));
212 el->el_flags |= HANDLE_SIGNALS;
214 el->el_flags &= ~HANDLE_SIGNALS;
223 const Char *argv[20];
226 for (i = 1; i < (int)__arraycount(argv); i++)
227 if ((argv[i] = va_arg(ap, Char *)) == NULL)
232 argv[0] = STR("bind");
233 rv = map_bind(el, i, argv);
237 argv[0] = STR("telltc");
238 rv = terminal_telltc(el, i, argv);
242 argv[0] = STR("settc");
243 rv = terminal_settc(el, i, argv);
247 argv[0] = STR("echotc");
248 rv = terminal_echotc(el, i, argv);
252 argv[0] = STR("setty");
253 rv = tty_stty(el, i, argv);
258 EL_ABORT((el->el_errfile, "Bad op %d\n", op));
266 Char *name = va_arg(ap, Char *);
267 Char *help = va_arg(ap, Char *);
268 el_func_t func = va_arg(ap, el_func_t);
270 rv = map_addfunc(el, name, help, func);
276 hist_fun_t func = va_arg(ap, hist_fun_t);
277 void *ptr = va_arg(ap, void *);
279 rv = hist_set(el, func, ptr);
280 if (!(el->el_flags & CHARSET_IS_UTF8))
281 el->el_flags &= ~NARROW_HISTORY;
287 el->el_flags &= ~EDIT_DISABLED;
289 el->el_flags |= EDIT_DISABLED;
295 el_rfunc_t rc = va_arg(ap, el_rfunc_t);
296 rv = el_read_setfn(el, rc);
297 el->el_flags &= ~NARROW_READ;
302 el->el_data = va_arg(ap, void *);
306 rv = va_arg(ap, int);
307 if (rv && !(el->el_flags & UNBUFFERED)) {
308 el->el_flags |= UNBUFFERED;
310 } else if (!rv && (el->el_flags & UNBUFFERED)) {
311 el->el_flags &= ~UNBUFFERED;
318 rv = va_arg(ap, int);
320 (void) tty_rawmode(el);
322 (void) tty_cookedmode(el);
331 what = va_arg(ap, int);
332 fp = va_arg(ap, FILE *);
338 el->el_infd = fileno(fp);
342 el->el_outfd = fileno(fp);
346 el->el_errfd = fileno(fp);
356 re_clear_display(el);
372 * retrieve the editline parameters
375 FUN(el,get)(EditLine *el, int op, ...)
388 el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
389 rv = prompt_get(el, p, 0, op);
393 case EL_RPROMPT_ESC: {
394 el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
395 Char *c = va_arg(ap, Char *);
397 rv = prompt_get(el, p, c, op);
402 rv = map_get_editor(el, va_arg(ap, const Char **));
406 *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
411 *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
416 terminal_get(el, va_arg(ap, const char **));
422 static char name[] = "gettc";
426 for (i = 1; i < (int)__arraycount(argv); i++)
427 if ((argv[i] = va_arg(ap, char *)) == NULL)
431 rv = terminal_gettc(el, i, argv);
436 *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
441 *va_arg(ap, void **) = el->el_data;
446 *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
455 what = va_arg(ap, int);
456 fpp = va_arg(ap, FILE **);
460 *fpp = el->el_infile;
463 *fpp = el->el_outfile;
466 *fpp = el->el_errfile;
485 * Return editing info
487 public const TYPE(LineInfo) *
488 FUN(el,line)(EditLine *el)
491 return (const TYPE(LineInfo) *)(void *)&el->el_line;
499 el_source(EditLine *el, const char *fname)
510 static const char elpath[] = "/.editrc";
511 size_t plen = sizeof(elpath);
513 #ifdef HAVE_ISSETUGID
516 if ((ptr = getenv("HOME")) == NULL)
519 if ((path = el_malloc(plen * sizeof(*path))) == NULL)
521 (void)snprintf(path, plen, "%s%s", ptr, elpath);
525 * If issetugid() is missing, always return an error, in order
526 * to keep from inadvertently opening up the user to a security
533 fp = fopen(fname, "r");
539 while ((ptr = fgetln(fp, &len)) != NULL) {
541 continue; /* Empty line. */
542 dptr = ct_decode_string(ptr, &el->el_scratch);
545 if (len > 0 && dptr[len - 1] == '\n')
548 /* loop until first non-space char or EOL */
549 while (*dptr != '\0' && Isspace(*dptr))
552 continue; /* ignore, this is a comment line */
553 if ((error = parse_line(el, dptr)) == -1)
564 * Called from program when terminal is resized
567 el_resize(EditLine *el)
572 (void) sigemptyset(&nset);
573 (void) sigaddset(&nset, SIGWINCH);
574 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
576 /* get the correct window size */
577 if (terminal_get_size(el, &lins, &cols))
578 terminal_change_size(el, lins, cols);
580 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
585 * Called from the program to beep
588 el_beep(EditLine *el)
596 * Set the state of EDIT_DISABLED from the `edit' command.
600 el_editmode(EditLine *el, int argc, const Char **argv)
604 if (argv == NULL || argc != 2 || argv[1] == NULL)
608 if (Strcmp(how, STR("on")) == 0) {
609 el->el_flags &= ~EDIT_DISABLED;
611 } else if (Strcmp(how, STR("off")) == 0) {
613 el->el_flags |= EDIT_DISABLED;
616 (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n",