1 /* $NetBSD: el.c,v 1.73 2014/06/18 18:12:28 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.73 2014/06/18 18:12:28 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 return el_init_fd(prog
, fin
, fout
, ferr
, fileno(fin
), fileno(fout
),
68 el_init_fd(const char *prog
, FILE *fin
, FILE *fout
, FILE *ferr
,
69 int fdin
, int fdout
, int fderr
)
71 EditLine
*el
= el_malloc(sizeof(*el
));
76 memset(el
, 0, sizeof(EditLine
));
79 el
->el_outfile
= fout
;
80 el
->el_errfile
= ferr
;
86 el
->el_prog
= Strdup(ct_decode_string(prog
, &el
->el_scratch
));
87 if (el
->el_prog
== NULL
) {
93 * Initialize all the modules. Order is important!!!
97 if (setlocale(LC_CTYPE
, NULL
) != NULL
){
98 if (strcmp(nl_langinfo(CODESET
), "UTF-8") == 0)
99 el
->el_flags
|= CHARSET_IS_UTF8
;
103 if (terminal_init(el
) == -1) {
104 el_free(el
->el_prog
);
108 (void) keymacro_init(el
);
110 if (tty_init(el
) == -1)
111 el
->el_flags
|= NO_TTY
;
113 (void) search_init(el
);
114 (void) hist_init(el
);
115 (void) prompt_init(el
);
117 (void) read_init(el
);
145 el_free(el
->el_prog
);
147 el_free(el
->el_scratch
.cbuff
);
148 el_free(el
->el_scratch
.wbuff
);
149 el_free(el
->el_lgcyconv
.cbuff
);
150 el_free(el
->el_lgcyconv
.wbuff
);
157 * Reset the tty and the parser
160 el_reset(EditLine
*el
)
164 ch_reset(el
, 0); /* XXX: Do we want that? */
169 * set the editline parameters
172 FUN(el
,set
)(EditLine
*el
, int op
, ...)
184 el_pfunc_t p
= va_arg(ap
, el_pfunc_t
);
186 rv
= prompt_set(el
, p
, 0, op
, 1);
191 el_zfunc_t p
= va_arg(ap
, el_zfunc_t
);
192 void *arg
= va_arg(ap
, void *);
193 rv
= ch_resizefun(el
, p
, arg
);
197 case EL_ALIAS_TEXT
: {
198 el_afunc_t p
= va_arg(ap
, el_afunc_t
);
199 void *arg
= va_arg(ap
, void *);
200 rv
= ch_aliasfun(el
, p
, arg
);
205 case EL_RPROMPT_ESC
: {
206 el_pfunc_t p
= va_arg(ap
, el_pfunc_t
);
207 int c
= va_arg(ap
, int);
209 rv
= prompt_set(el
, p
, c
, op
, 1);
214 rv
= terminal_set(el
, va_arg(ap
, char *));
218 rv
= map_set_editor(el
, va_arg(ap
, Char
*));
223 el
->el_flags
|= HANDLE_SIGNALS
;
225 el
->el_flags
&= ~HANDLE_SIGNALS
;
234 const Char
*argv
[20];
237 for (i
= 1; i
< (int)__arraycount(argv
); i
++)
238 if ((argv
[i
] = va_arg(ap
, Char
*)) == NULL
)
243 argv
[0] = STR("bind");
244 rv
= map_bind(el
, i
, argv
);
248 argv
[0] = STR("telltc");
249 rv
= terminal_telltc(el
, i
, argv
);
253 argv
[0] = STR("settc");
254 rv
= terminal_settc(el
, i
, argv
);
258 argv
[0] = STR("echotc");
259 rv
= terminal_echotc(el
, i
, argv
);
263 argv
[0] = STR("setty");
264 rv
= tty_stty(el
, i
, argv
);
269 EL_ABORT((el
->el_errfile
, "Bad op %d\n", op
));
277 Char
*name
= va_arg(ap
, Char
*);
278 Char
*help
= va_arg(ap
, Char
*);
279 el_func_t func
= va_arg(ap
, el_func_t
);
281 rv
= map_addfunc(el
, name
, help
, func
);
287 hist_fun_t func
= va_arg(ap
, hist_fun_t
);
288 void *ptr
= va_arg(ap
, void *);
290 rv
= hist_set(el
, func
, ptr
);
291 if (!(el
->el_flags
& CHARSET_IS_UTF8
))
292 el
->el_flags
&= ~NARROW_HISTORY
;
298 el
->el_flags
&= ~EDIT_DISABLED
;
300 el
->el_flags
|= EDIT_DISABLED
;
306 el_rfunc_t rc
= va_arg(ap
, el_rfunc_t
);
307 rv
= el_read_setfn(el
, rc
);
308 el
->el_flags
&= ~NARROW_READ
;
313 el
->el_data
= va_arg(ap
, void *);
317 rv
= va_arg(ap
, int);
318 if (rv
&& !(el
->el_flags
& UNBUFFERED
)) {
319 el
->el_flags
|= UNBUFFERED
;
321 } else if (!rv
&& (el
->el_flags
& UNBUFFERED
)) {
322 el
->el_flags
&= ~UNBUFFERED
;
329 rv
= va_arg(ap
, int);
331 (void) tty_rawmode(el
);
333 (void) tty_cookedmode(el
);
342 what
= va_arg(ap
, int);
343 fp
= va_arg(ap
, FILE *);
349 el
->el_infd
= fileno(fp
);
353 el
->el_outfd
= fileno(fp
);
357 el
->el_errfd
= fileno(fp
);
367 re_clear_display(el
);
383 * retrieve the editline parameters
386 FUN(el
,get
)(EditLine
*el
, int op
, ...)
399 el_pfunc_t
*p
= va_arg(ap
, el_pfunc_t
*);
400 rv
= prompt_get(el
, p
, 0, op
);
404 case EL_RPROMPT_ESC
: {
405 el_pfunc_t
*p
= va_arg(ap
, el_pfunc_t
*);
406 Char
*c
= va_arg(ap
, Char
*);
408 rv
= prompt_get(el
, p
, c
, op
);
413 rv
= map_get_editor(el
, va_arg(ap
, const Char
**));
417 *va_arg(ap
, int *) = (el
->el_flags
& HANDLE_SIGNALS
);
422 *va_arg(ap
, int *) = !(el
->el_flags
& EDIT_DISABLED
);
427 terminal_get(el
, va_arg(ap
, const char **));
433 static char name
[] = "gettc";
437 for (i
= 1; i
< (int)__arraycount(argv
); i
++)
438 if ((argv
[i
] = va_arg(ap
, char *)) == NULL
)
442 rv
= terminal_gettc(el
, i
, argv
);
447 *va_arg(ap
, el_rfunc_t
*) = el_read_getfn(el
);
452 *va_arg(ap
, void **) = el
->el_data
;
457 *va_arg(ap
, int *) = (el
->el_flags
& UNBUFFERED
) != 0;
466 what
= va_arg(ap
, int);
467 fpp
= va_arg(ap
, FILE **);
471 *fpp
= el
->el_infile
;
474 *fpp
= el
->el_outfile
;
477 *fpp
= el
->el_errfile
;
496 * Return editing info
498 public const TYPE(LineInfo
) *
499 FUN(el
,line
)(EditLine
*el
)
502 return (const TYPE(LineInfo
) *)(void *)&el
->el_line
;
510 el_source(EditLine
*el
, const char *fname
)
521 #ifdef HAVE_ISSETUGID
522 static const char elpath
[] = "/.editrc";
523 size_t plen
= sizeof(elpath
);
527 if ((ptr
= getenv("HOME")) == NULL
)
530 if ((path
= el_malloc(plen
* sizeof(*path
))) == NULL
)
532 (void)snprintf(path
, plen
, "%s%s", ptr
, elpath
);
536 * If issetugid() is missing, always return an error, in order
537 * to keep from inadvertently opening up the user to a security
544 fp
= fopen(fname
, "r");
550 while ((ptr
= fgetln(fp
, &len
)) != NULL
) {
552 continue; /* Empty line. */
553 dptr
= ct_decode_string(ptr
, &el
->el_scratch
);
556 if (len
> 0 && dptr
[len
- 1] == '\n')
559 /* loop until first non-space char or EOL */
560 while (*dptr
!= '\0' && Isspace(*dptr
))
563 continue; /* ignore, this is a comment line */
564 if ((error
= parse_line(el
, dptr
)) == -1)
575 * Called from program when terminal is resized
578 el_resize(EditLine
*el
)
583 (void) sigemptyset(&nset
);
584 (void) sigaddset(&nset
, SIGWINCH
);
585 (void) sigprocmask(SIG_BLOCK
, &nset
, &oset
);
587 /* get the correct window size */
588 if (terminal_get_size(el
, &lins
, &cols
))
589 terminal_change_size(el
, lins
, cols
);
591 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
596 * Called from the program to beep
599 el_beep(EditLine
*el
)
607 * Set the state of EDIT_DISABLED from the `edit' command.
611 el_editmode(EditLine
*el
, int argc
, const Char
**argv
)
615 if (argv
== NULL
|| argc
!= 2 || argv
[1] == NULL
)
619 if (Strcmp(how
, STR("on")) == 0) {
620 el
->el_flags
&= ~EDIT_DISABLED
;
622 } else if (Strcmp(how
, STR("off")) == 0) {
624 el
->el_flags
|= EDIT_DISABLED
;
627 (void) fprintf(el
->el_errfile
, "edit: Bad value `" FSTR
"'.\n",