1 /* $NetBSD: el.c,v 1.71 2012/09/11 11:58:53 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.71 2012/09/11 11:58:53 christos Exp $");
42 #endif /* not lint && not SCCSID */
45 * el.c: EditLine interface functions
47 #include <sys/types.h>
48 #include <sys/param.h>
58 * Initialize editline and set default parameters.
61 el_init(const char *prog
, FILE *fin
, FILE *fout
, FILE *ferr
)
63 EditLine
*el
= el_malloc(sizeof(*el
));
68 memset(el
, 0, sizeof(EditLine
));
71 el
->el_outfile
= fout
;
72 el
->el_errfile
= ferr
;
74 el
->el_infd
= fileno(fin
);
75 el
->el_outfd
= fileno(fout
);
76 el
->el_errfd
= fileno(ferr
);
78 el
->el_prog
= Strdup(ct_decode_string(prog
, &el
->el_scratch
));
79 if (el
->el_prog
== NULL
) {
85 * Initialize all the modules. Order is important!!!
89 if (setlocale(LC_CTYPE
, NULL
) != NULL
){
90 if (strcmp(nl_langinfo(CODESET
), "UTF-8") == 0)
91 el
->el_flags
|= CHARSET_IS_UTF8
;
95 if (terminal_init(el
) == -1) {
100 (void) keymacro_init(el
);
102 if (tty_init(el
) == -1)
103 el
->el_flags
|= NO_TTY
;
105 (void) search_init(el
);
106 (void) hist_init(el
);
107 (void) prompt_init(el
);
109 (void) read_init(el
);
137 el_free(el
->el_prog
);
139 el_free(el
->el_scratch
.cbuff
);
140 el_free(el
->el_scratch
.wbuff
);
141 el_free(el
->el_lgcyconv
.cbuff
);
142 el_free(el
->el_lgcyconv
.wbuff
);
149 * Reset the tty and the parser
152 el_reset(EditLine
*el
)
156 ch_reset(el
, 0); /* XXX: Do we want that? */
161 * set the editline parameters
164 FUN(el
,set
)(EditLine
*el
, int op
, ...)
176 el_pfunc_t p
= va_arg(ap
, el_pfunc_t
);
178 rv
= prompt_set(el
, p
, 0, op
, 1);
183 el_zfunc_t p
= va_arg(ap
, el_zfunc_t
);
184 void *arg
= va_arg(ap
, void *);
185 rv
= ch_resizefun(el
, p
, arg
);
190 case EL_RPROMPT_ESC
: {
191 el_pfunc_t p
= va_arg(ap
, el_pfunc_t
);
192 int c
= va_arg(ap
, int);
194 rv
= prompt_set(el
, p
, c
, op
, 1);
199 rv
= terminal_set(el
, va_arg(ap
, char *));
203 rv
= map_set_editor(el
, va_arg(ap
, Char
*));
208 el
->el_flags
|= HANDLE_SIGNALS
;
210 el
->el_flags
&= ~HANDLE_SIGNALS
;
219 const Char
*argv
[20];
222 for (i
= 1; i
< (int)__arraycount(argv
); i
++)
223 if ((argv
[i
] = va_arg(ap
, Char
*)) == NULL
)
228 argv
[0] = STR("bind");
229 rv
= map_bind(el
, i
, argv
);
233 argv
[0] = STR("telltc");
234 rv
= terminal_telltc(el
, i
, argv
);
238 argv
[0] = STR("settc");
239 rv
= terminal_settc(el
, i
, argv
);
243 argv
[0] = STR("echotc");
244 rv
= terminal_echotc(el
, i
, argv
);
248 argv
[0] = STR("setty");
249 rv
= tty_stty(el
, i
, argv
);
254 EL_ABORT((el
->el_errfile
, "Bad op %d\n", op
));
262 Char
*name
= va_arg(ap
, Char
*);
263 Char
*help
= va_arg(ap
, Char
*);
264 el_func_t func
= va_arg(ap
, el_func_t
);
266 rv
= map_addfunc(el
, name
, help
, func
);
272 hist_fun_t func
= va_arg(ap
, hist_fun_t
);
273 void *ptr
= va_arg(ap
, void *);
275 rv
= hist_set(el
, func
, ptr
);
276 if (!(el
->el_flags
& CHARSET_IS_UTF8
))
277 el
->el_flags
&= ~NARROW_HISTORY
;
283 el
->el_flags
&= ~EDIT_DISABLED
;
285 el
->el_flags
|= EDIT_DISABLED
;
291 el_rfunc_t rc
= va_arg(ap
, el_rfunc_t
);
292 rv
= el_read_setfn(el
, rc
);
293 el
->el_flags
&= ~NARROW_READ
;
298 el
->el_data
= va_arg(ap
, void *);
302 rv
= va_arg(ap
, int);
303 if (rv
&& !(el
->el_flags
& UNBUFFERED
)) {
304 el
->el_flags
|= UNBUFFERED
;
306 } else if (!rv
&& (el
->el_flags
& UNBUFFERED
)) {
307 el
->el_flags
&= ~UNBUFFERED
;
314 rv
= va_arg(ap
, int);
316 (void) tty_rawmode(el
);
318 (void) tty_cookedmode(el
);
327 what
= va_arg(ap
, int);
328 fp
= va_arg(ap
, FILE *);
334 el
->el_infd
= fileno(fp
);
338 el
->el_outfd
= fileno(fp
);
342 el
->el_errfd
= fileno(fp
);
352 re_clear_display(el
);
368 * retrieve the editline parameters
371 FUN(el
,get
)(EditLine
*el
, int op
, ...)
384 el_pfunc_t
*p
= va_arg(ap
, el_pfunc_t
*);
385 rv
= prompt_get(el
, p
, 0, op
);
389 case EL_RPROMPT_ESC
: {
390 el_pfunc_t
*p
= va_arg(ap
, el_pfunc_t
*);
391 Char
*c
= va_arg(ap
, Char
*);
393 rv
= prompt_get(el
, p
, c
, op
);
398 rv
= map_get_editor(el
, va_arg(ap
, const Char
**));
402 *va_arg(ap
, int *) = (el
->el_flags
& HANDLE_SIGNALS
);
407 *va_arg(ap
, int *) = !(el
->el_flags
& EDIT_DISABLED
);
412 terminal_get(el
, va_arg(ap
, const char **));
418 static char name
[] = "gettc";
422 for (i
= 1; i
< (int)__arraycount(argv
); i
++)
423 if ((argv
[i
] = va_arg(ap
, char *)) == NULL
)
427 rv
= terminal_gettc(el
, i
, argv
);
432 *va_arg(ap
, el_rfunc_t
*) = el_read_getfn(el
);
437 *va_arg(ap
, void **) = el
->el_data
;
442 *va_arg(ap
, int *) = (el
->el_flags
& UNBUFFERED
) != 0;
451 what
= va_arg(ap
, int);
452 fpp
= va_arg(ap
, FILE **);
456 *fpp
= el
->el_infile
;
459 *fpp
= el
->el_outfile
;
462 *fpp
= el
->el_errfile
;
481 * Return editing info
483 public const TYPE(LineInfo
) *
484 FUN(el
,line
)(EditLine
*el
)
487 return (const TYPE(LineInfo
) *)(void *)&el
->el_line
;
495 el_source(EditLine
*el
, const char *fname
)
506 #ifdef HAVE_ISSETUGID
507 static const char elpath
[] = "/.editrc";
508 size_t plen
= sizeof(elpath
);
512 if ((ptr
= getenv("HOME")) == NULL
)
515 if ((path
= el_malloc(plen
* sizeof(*path
))) == NULL
)
517 (void)snprintf(path
, plen
, "%s%s", ptr
, elpath
);
521 * If issetugid() is missing, always return an error, in order
522 * to keep from inadvertently opening up the user to a security
529 fp
= fopen(fname
, "r");
535 while ((ptr
= fgetln(fp
, &len
)) != NULL
) {
537 continue; /* Empty line. */
538 dptr
= ct_decode_string(ptr
, &el
->el_scratch
);
541 if (len
> 0 && dptr
[len
- 1] == '\n')
544 /* loop until first non-space char or EOL */
545 while (*dptr
!= '\0' && Isspace(*dptr
))
548 continue; /* ignore, this is a comment line */
549 if ((error
= parse_line(el
, dptr
)) == -1)
560 * Called from program when terminal is resized
563 el_resize(EditLine
*el
)
568 (void) sigemptyset(&nset
);
569 (void) sigaddset(&nset
, SIGWINCH
);
570 (void) sigprocmask(SIG_BLOCK
, &nset
, &oset
);
572 /* get the correct window size */
573 if (terminal_get_size(el
, &lins
, &cols
))
574 terminal_change_size(el
, lins
, cols
);
576 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
581 * Called from the program to beep
584 el_beep(EditLine
*el
)
592 * Set the state of EDIT_DISABLED from the `edit' command.
596 el_editmode(EditLine
*el
, int argc
, const Char
**argv
)
600 if (argv
== NULL
|| argc
!= 2 || argv
[1] == NULL
)
604 if (Strcmp(how
, STR("on")) == 0) {
605 el
->el_flags
&= ~EDIT_DISABLED
;
607 } else if (Strcmp(how
, STR("off")) == 0) {
609 el
->el_flags
|= EDIT_DISABLED
;
612 (void) fprintf(el
->el_errfile
, "edit: Bad value `" FSTR
"'.\n",