1 /* $NetBSD: el.c,v 1.57 2009/12/30 23:54:52 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.57 2009/12/30 23:54:52 christos Exp $");
42 #endif /* not lint && not SCCSID */
45 * el.c: EditLine interface functions
47 #include <sys/types.h>
48 #include <sys/param.h>
57 * Initialize editline and set default parameters.
60 el_init(const char *prog
, FILE *fin
, FILE *fout
, FILE *ferr
)
65 EditLine
*el
= (EditLine
*) el_malloc(sizeof(EditLine
));
70 memset(el
, 0, sizeof(EditLine
));
73 el
->el_outfile
= fout
;
74 el
->el_errfile
= ferr
;
76 el
->el_infd
= fileno(fin
);
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 ((locale
= setlocale(LC_CTYPE
, NULL
)) != NULL
){
90 if (strcasestr(locale
, ".UTF-8") != NULL
)
91 el
->el_flags
|= CHARSET_IS_UTF8
;
95 if (term_init(el
) == -1) {
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((ptr_t
) el
->el_prog
);
140 el_free((ptr_t
) el
->el_scratch
.cbuff
);
141 el_free((ptr_t
) el
->el_scratch
.wbuff
);
142 el_free((ptr_t
) el
->el_lgcyconv
.cbuff
);
143 el_free((ptr_t
) 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 case EL_RPROMPT_ESC
: {
184 el_pfunc_t p
= va_arg(ap
, el_pfunc_t
);
185 int c
= va_arg(ap
, int);
187 rv
= prompt_set(el
, p
, c
, op
, 1);
192 rv
= term_set(el
, va_arg(ap
, char *));
196 rv
= map_set_editor(el
, va_arg(ap
, Char
*));
201 el
->el_flags
|= HANDLE_SIGNALS
;
203 el
->el_flags
&= ~HANDLE_SIGNALS
;
212 const Char
*argv
[20];
215 for (i
= 1; i
< 20; i
++)
216 if ((argv
[i
] = va_arg(ap
, Char
*)) == NULL
)
221 argv
[0] = STR("bind");
222 rv
= map_bind(el
, i
, argv
);
226 argv
[0] = STR("telltc");
227 rv
= term_telltc(el
, i
, argv
);
231 argv
[0] = STR("settc");
232 rv
= term_settc(el
, i
, argv
);
236 argv
[0] = STR("echotc");
237 rv
= term_echotc(el
, i
, argv
);
241 argv
[0] = STR("setty");
242 rv
= tty_stty(el
, i
, argv
);
247 EL_ABORT((el
->el_errfile
, "Bad op %d\n", op
));
255 Char
*name
= va_arg(ap
, Char
*);
256 Char
*help
= va_arg(ap
, Char
*);
257 el_func_t func
= va_arg(ap
, el_func_t
);
259 rv
= map_addfunc(el
, name
, help
, func
);
265 hist_fun_t func
= va_arg(ap
, hist_fun_t
);
266 ptr_t ptr
= va_arg(ap
, ptr_t
);
268 rv
= hist_set(el
, func
, ptr
);
269 el
->el_flags
&= ~NARROW_HISTORY
;
275 el
->el_flags
&= ~EDIT_DISABLED
;
277 el
->el_flags
|= EDIT_DISABLED
;
283 el_rfunc_t rc
= va_arg(ap
, el_rfunc_t
);
284 rv
= el_read_setfn(el
, rc
);
285 el
->el_flags
&= ~NARROW_READ
;
290 el
->el_data
= va_arg(ap
, void *);
294 rv
= va_arg(ap
, int);
295 if (rv
&& !(el
->el_flags
& UNBUFFERED
)) {
296 el
->el_flags
|= UNBUFFERED
;
298 } else if (!rv
&& (el
->el_flags
& UNBUFFERED
)) {
299 el
->el_flags
&= ~UNBUFFERED
;
306 rv
= va_arg(ap
, int);
308 (void) tty_rawmode(el
);
310 (void) tty_cookedmode(el
);
319 what
= va_arg(ap
, int);
320 fp
= va_arg(ap
, FILE *);
326 el
->el_infd
= fileno(fp
);
342 re_clear_display(el
);
358 * retrieve the editline parameters
361 FUN(el
,get
)(EditLine
*el
, int op
, ...)
374 el_pfunc_t
*p
= va_arg(ap
, el_pfunc_t
*);
375 rv
= prompt_get(el
, p
, 0, op
);
379 case EL_RPROMPT_ESC
: {
380 el_pfunc_t
*p
= va_arg(ap
, el_pfunc_t
*);
381 Char
*c
= va_arg(ap
, Char
*);
383 rv
= prompt_get(el
, p
, c
, op
);
388 rv
= map_get_editor(el
, va_arg(ap
, const Char
**));
392 *va_arg(ap
, int *) = (el
->el_flags
& HANDLE_SIGNALS
);
397 *va_arg(ap
, int *) = !(el
->el_flags
& EDIT_DISABLED
);
402 term_get(el
, va_arg(ap
, const char **));
408 static char name
[] = "gettc";
412 for (i
= 1; i
< (int)(sizeof(argv
) / sizeof(argv
[0])); i
++)
413 if ((argv
[i
] = va_arg(ap
, char *)) == NULL
)
419 rv
= term_gettc(el
, i
, argv
);
424 EL_ABORT((el
->el_errfile
, "Bad op %d\n", op
));
431 *va_arg(ap
, el_rfunc_t
*) = el_read_getfn(el
);
436 *va_arg(ap
, void **) = el
->el_data
;
441 *va_arg(ap
, int *) = (!(el
->el_flags
& UNBUFFERED
));
450 what
= va_arg(ap
, int);
451 fpp
= va_arg(ap
, FILE **);
455 *fpp
= el
->el_infile
;
458 *fpp
= el
->el_outfile
;
461 *fpp
= el
->el_errfile
;
480 * Return editing info
482 public const TYPE(LineInfo
) *
483 FUN(el
,line
)(EditLine
*el
)
486 return (const TYPE(LineInfo
) *) (void *) &el
->el_line
;
494 el_source(EditLine
*el
, const char *fname
)
499 #ifdef HAVE_ISSETUGID
500 char path
[MAXPATHLEN
];
506 #ifdef HAVE_ISSETUGID
507 static const char elpath
[] = "/.editrc";
511 if ((ptr
= getenv("HOME")) == NULL
)
513 if (strlcpy(path
, ptr
, sizeof(path
)) >= sizeof(path
))
515 if (strlcat(path
, elpath
, sizeof(path
)) >= sizeof(path
))
520 * If issetugid() is missing, always return an error, in order
521 * to keep from inadvertently opening up the user to a security
528 fp
= fopen(fname
, "r");
532 while ((ptr
= fgetln(fp
, &len
)) != NULL
) {
533 dptr
= ct_decode_string(ptr
, &el
->el_scratch
);
536 if (len
> 0 && dptr
[len
- 1] == '\n')
539 /* loop until first non-space char or EOL */
540 while (*dptr
!= '\0' && Isspace(*dptr
))
543 continue; /* ignore, this is a comment line */
544 if (parse_line(el
, dptr
) == -1) {
556 * Called from program when terminal is resized
559 el_resize(EditLine
*el
)
564 (void) sigemptyset(&nset
);
565 (void) sigaddset(&nset
, SIGWINCH
);
566 (void) sigprocmask(SIG_BLOCK
, &nset
, &oset
);
568 /* get the correct window size */
569 if (term_get_size(el
, &lins
, &cols
))
570 term_change_size(el
, lins
, cols
);
572 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
577 * Called from the program to beep
580 el_beep(EditLine
*el
)
588 * Set the state of EDIT_DISABLED from the `edit' command.
592 el_editmode(EditLine
*el
, int argc
, const Char
**argv
)
596 if (argv
== NULL
|| argc
!= 2 || argv
[1] == NULL
)
600 if (Strcmp(how
, STR("on")) == 0) {
601 el
->el_flags
&= ~EDIT_DISABLED
;
603 } else if (Strcmp(how
, STR("off")) == 0) {
605 el
->el_flags
|= EDIT_DISABLED
;
608 (void) fprintf(el
->el_errfile
, "edit: Bad value `" FSTR
"'.\n",