xref: /openbsd-src/lib/libedit/el.c (revision 5b133f3f277e80f096764111e64f3a1284acb179)
1*5b133f3fSguenther /*	$OpenBSD: el.c,v 1.38 2023/03/08 04:43:05 guenther Exp $	*/
25f805b19Sokan /*	$NetBSD: el.c,v 1.61 2011/01/27 23:11:40 christos Exp $	*/
3babb851aSmillert 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1992, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt  * Christos Zoulas of Cornell University.
10df930be7Sderaadt  *
11df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt  * modification, are permitted provided that the following conditions
13df930be7Sderaadt  * are met:
14df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
196580fee3Smillert  * 3. Neither the name of the University nor the names of its contributors
20df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
21df930be7Sderaadt  *    without specific prior written permission.
22df930be7Sderaadt  *
23df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt  * SUCH DAMAGE.
34df930be7Sderaadt  */
35df930be7Sderaadt 
36d484b7d0Sotto #include "config.h"
37df930be7Sderaadt 
38df930be7Sderaadt /*
39df930be7Sderaadt  * el.c: EditLine interface functions
40df930be7Sderaadt  */
41df930be7Sderaadt #include <sys/types.h>
42aed0ee81Snicm #include <ctype.h>
4359aed043Sschwarze #include <langinfo.h>
44aea60beeSderaadt #include <limits.h>
4559aed043Sschwarze #include <locale.h>
467ccfa089Sschwarze #include <stdarg.h>
477ccfa089Sschwarze #include <stdlib.h>
487ccfa089Sschwarze #include <string.h>
49624bc356Sschwarze 
50df930be7Sderaadt #include "el.h"
515564fb94Sschwarze #include "parse.h"
5204833be7Sschwarze #include "read.h"
53df930be7Sderaadt 
54df930be7Sderaadt /* el_init():
55df930be7Sderaadt  *	Initialize editline and set default parameters.
56df930be7Sderaadt  */
57ddc81437Sschwarze EditLine *
el_init(const char * prog,FILE * fin,FILE * fout,FILE * ferr)58d484b7d0Sotto el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
59df930be7Sderaadt {
607b6df1e2Stb 	EditLine *el = (EditLine *) calloc(1, sizeof(EditLine));
61df930be7Sderaadt 
62df930be7Sderaadt 	if (el == NULL)
6328d54ee8Sschwarze 		return NULL;
64df930be7Sderaadt 
65aed0ee81Snicm 	el->el_infile = fin;
66df930be7Sderaadt 	el->el_outfile = fout;
67d484b7d0Sotto 	el->el_errfile = ferr;
68aed0ee81Snicm 
69aed0ee81Snicm 	el->el_infd = fileno(fin);
705f805b19Sokan 	el->el_outfd = fileno(fout);
715f805b19Sokan 	el->el_errfd = fileno(ferr);
72aed0ee81Snicm 
735c93237dSschwarze 	el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch));
74aed0ee81Snicm 	if (el->el_prog == NULL) {
75014b1be8Sderaadt 		free(el);
766e02e073Sotto 		return NULL;
776e02e073Sotto 	}
78df930be7Sderaadt 
79df930be7Sderaadt 	/*
80df930be7Sderaadt          * Initialize all the modules. Order is important!!!
81df930be7Sderaadt          */
82d484b7d0Sotto 	el->el_flags = 0;
83aed0ee81Snicm 	if (setlocale(LC_CTYPE, NULL) != NULL){
84aed0ee81Snicm 		if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
85aed0ee81Snicm 			el->el_flags |= CHARSET_IS_UTF8;
86aed0ee81Snicm 	}
87d484b7d0Sotto 
88fd40972aSschwarze 	if (terminal_init(el) == -1) {
89014b1be8Sderaadt 		free(el->el_prog);
90014b1be8Sderaadt 		free(el);
91d484b7d0Sotto 		return NULL;
92d484b7d0Sotto 	}
9336facb13Sschwarze 	(void) keymacro_init(el);
94df930be7Sderaadt 	(void) map_init(el);
95d484b7d0Sotto 	if (tty_init(el) == -1)
96d484b7d0Sotto 		el->el_flags |= NO_TTY;
97df930be7Sderaadt 	(void) ch_init(el);
98df930be7Sderaadt 	(void) search_init(el);
99df930be7Sderaadt 	(void) hist_init(el);
100df930be7Sderaadt 	(void) prompt_init(el);
101df930be7Sderaadt 	(void) sig_init(el);
10204833be7Sschwarze 	if (read_init(el) == -1) {
10304833be7Sschwarze 		el_end(el);
10404833be7Sschwarze 		return NULL;
10504833be7Sschwarze 	}
10628d54ee8Sschwarze 	return el;
107d484b7d0Sotto }
108df930be7Sderaadt 
109df930be7Sderaadt 
110df930be7Sderaadt /* el_end():
111df930be7Sderaadt  *	Clean up.
112df930be7Sderaadt  */
113ddc81437Sschwarze void
el_end(EditLine * el)114d484b7d0Sotto el_end(EditLine *el)
115df930be7Sderaadt {
116d484b7d0Sotto 
117df930be7Sderaadt 	if (el == NULL)
118df930be7Sderaadt 		return;
119df930be7Sderaadt 
120df930be7Sderaadt 	el_reset(el);
121df930be7Sderaadt 
122fd40972aSschwarze 	terminal_end(el);
12336facb13Sschwarze 	keymacro_end(el);
124df930be7Sderaadt 	map_end(el);
125d484b7d0Sotto 	tty_end(el);
126df930be7Sderaadt 	ch_end(el);
1275161d913Sschwarze 	read_end(el->el_read);
128df930be7Sderaadt 	search_end(el);
129df930be7Sderaadt 	hist_end(el);
130df930be7Sderaadt 	prompt_end(el);
131df930be7Sderaadt 	sig_end(el);
132df930be7Sderaadt 
1337b85e16bSschwarze 	free(el->el_prog);
1347b85e16bSschwarze 	free(el->el_scratch.cbuff);
1357b85e16bSschwarze 	free(el->el_scratch.wbuff);
1367b85e16bSschwarze 	free(el->el_lgcyconv.cbuff);
1377b85e16bSschwarze 	free(el->el_lgcyconv.wbuff);
1387b85e16bSschwarze 	free(el);
139d484b7d0Sotto }
140df930be7Sderaadt 
141df930be7Sderaadt 
142df930be7Sderaadt /* el_reset():
143df930be7Sderaadt  *	Reset the tty and the parser
144df930be7Sderaadt  */
145ddc81437Sschwarze void
el_reset(EditLine * el)146d484b7d0Sotto el_reset(EditLine *el)
147df930be7Sderaadt {
148d484b7d0Sotto 
149df930be7Sderaadt 	tty_cookedmode(el);
1505161d913Sschwarze 	ch_reset(el);		/* XXX: Do we want that? */
151df930be7Sderaadt }
152df930be7Sderaadt 
153df930be7Sderaadt 
154df930be7Sderaadt /* el_set():
155df930be7Sderaadt  *	set the editline parameters
156df930be7Sderaadt  */
157ddc81437Sschwarze int
el_wset(EditLine * el,int op,...)1585c93237dSschwarze el_wset(EditLine *el, int op, ...)
159df930be7Sderaadt {
160aed0ee81Snicm 	va_list ap;
161d484b7d0Sotto 	int rv = 0;
162df930be7Sderaadt 
163d484b7d0Sotto 	if (el == NULL)
16428d54ee8Sschwarze 		return -1;
165aed0ee81Snicm 	va_start(ap, op);
166df930be7Sderaadt 
167df930be7Sderaadt 	switch (op) {
168df930be7Sderaadt 	case EL_PROMPT:
169aed0ee81Snicm 	case EL_RPROMPT: {
170aed0ee81Snicm 		el_pfunc_t p = va_arg(ap, el_pfunc_t);
171aed0ee81Snicm 
172aed0ee81Snicm 		rv = prompt_set(el, p, 0, op, 1);
173df930be7Sderaadt 		break;
174aed0ee81Snicm 	}
175aed0ee81Snicm 
1765f805b19Sokan 	case EL_RESIZE: {
1775f805b19Sokan 		el_zfunc_t p = va_arg(ap, el_zfunc_t);
1785f805b19Sokan 		void *arg = va_arg(ap, void *);
1795f805b19Sokan 		rv = ch_resizefun(el, p, arg);
1805f805b19Sokan 		break;
1815f805b19Sokan 	}
1825f805b19Sokan 
183aed0ee81Snicm 	case EL_PROMPT_ESC:
184aed0ee81Snicm 	case EL_RPROMPT_ESC: {
185aed0ee81Snicm 		el_pfunc_t p = va_arg(ap, el_pfunc_t);
186aed0ee81Snicm 		int c = va_arg(ap, int);
187aed0ee81Snicm 
188aed0ee81Snicm 		rv = prompt_set(el, p, c, op, 1);
189aed0ee81Snicm 		break;
190aed0ee81Snicm 	}
191df930be7Sderaadt 
192df930be7Sderaadt 	case EL_TERMINAL:
193fd40972aSschwarze 		rv = terminal_set(el, va_arg(ap, char *));
194df930be7Sderaadt 		break;
195df930be7Sderaadt 
196df930be7Sderaadt 	case EL_EDITOR:
197e3191321Sschwarze 		rv = map_set_editor(el, va_arg(ap, wchar_t *));
198df930be7Sderaadt 		break;
199df930be7Sderaadt 
200df930be7Sderaadt 	case EL_SIGNAL:
201aed0ee81Snicm 		if (va_arg(ap, int))
202df930be7Sderaadt 			el->el_flags |= HANDLE_SIGNALS;
203df930be7Sderaadt 		else
204df930be7Sderaadt 			el->el_flags &= ~HANDLE_SIGNALS;
205df930be7Sderaadt 		break;
206df930be7Sderaadt 
207df930be7Sderaadt 	case EL_BIND:
208df930be7Sderaadt 	case EL_TELLTC:
209df930be7Sderaadt 	case EL_SETTC:
210df930be7Sderaadt 	case EL_ECHOTC:
211df930be7Sderaadt 	case EL_SETTY:
212df930be7Sderaadt 	{
213e3191321Sschwarze 		const wchar_t *argv[20];
214df930be7Sderaadt 		int i;
215d484b7d0Sotto 
216df930be7Sderaadt 		for (i = 1; i < 20; i++)
217e3191321Sschwarze 			if ((argv[i] = va_arg(ap, wchar_t *)) == NULL)
218df930be7Sderaadt 				break;
219df930be7Sderaadt 
220df930be7Sderaadt 		switch (op) {
221df930be7Sderaadt 		case EL_BIND:
2225c93237dSschwarze 			argv[0] = L"bind";
223df930be7Sderaadt 			rv = map_bind(el, i, argv);
224df930be7Sderaadt 			break;
225df930be7Sderaadt 
226df930be7Sderaadt 		case EL_TELLTC:
2275c93237dSschwarze 			argv[0] = L"telltc";
228fd40972aSschwarze 			rv = terminal_telltc(el, i, argv);
229df930be7Sderaadt 			break;
230df930be7Sderaadt 
231df930be7Sderaadt 		case EL_SETTC:
2325c93237dSschwarze 			argv[0] = L"settc";
233fd40972aSschwarze 			rv = terminal_settc(el, i, argv);
234df930be7Sderaadt 			break;
235df930be7Sderaadt 
236df930be7Sderaadt 		case EL_ECHOTC:
2375c93237dSschwarze 			argv[0] = L"echotc";
238fd40972aSschwarze 			rv = terminal_echotc(el, i, argv);
239df930be7Sderaadt 			break;
240df930be7Sderaadt 
241df930be7Sderaadt 		case EL_SETTY:
2425c93237dSschwarze 			argv[0] = L"setty";
243df930be7Sderaadt 			rv = tty_stty(el, i, argv);
244df930be7Sderaadt 			break;
245df930be7Sderaadt 
246df930be7Sderaadt 		default:
247df930be7Sderaadt 			rv = -1;
248d484b7d0Sotto 			EL_ABORT((el->el_errfile, "Bad op %d\n", op));
249df930be7Sderaadt 			break;
250df930be7Sderaadt 		}
251df930be7Sderaadt 		break;
252d484b7d0Sotto 	}
253df930be7Sderaadt 
254df930be7Sderaadt 	case EL_ADDFN:
255df930be7Sderaadt 	{
256e3191321Sschwarze 		wchar_t *name = va_arg(ap, wchar_t *);
257e3191321Sschwarze 		wchar_t *help = va_arg(ap, wchar_t *);
258aed0ee81Snicm 		el_func_t func = va_arg(ap, el_func_t);
259d484b7d0Sotto 
260df930be7Sderaadt 		rv = map_addfunc(el, name, help, func);
261d484b7d0Sotto 		break;
262d484b7d0Sotto 	}
263d484b7d0Sotto 
264d484b7d0Sotto 	case EL_HIST:
265d484b7d0Sotto 	{
266aed0ee81Snicm 		hist_fun_t func = va_arg(ap, hist_fun_t);
2677b85e16bSschwarze 		void *ptr = va_arg(ap, void *);
268d484b7d0Sotto 
269d484b7d0Sotto 		rv = hist_set(el, func, ptr);
270aed0ee81Snicm 		if (!(el->el_flags & CHARSET_IS_UTF8))
271aed0ee81Snicm 			el->el_flags &= ~NARROW_HISTORY;
272d484b7d0Sotto 		break;
273d484b7d0Sotto 	}
274d484b7d0Sotto 
275d484b7d0Sotto 	case EL_EDITMODE:
276aed0ee81Snicm 		if (va_arg(ap, int))
277d484b7d0Sotto 			el->el_flags &= ~EDIT_DISABLED;
278d484b7d0Sotto 		else
279d484b7d0Sotto 			el->el_flags |= EDIT_DISABLED;
280d484b7d0Sotto 		rv = 0;
281d484b7d0Sotto 		break;
282d484b7d0Sotto 
283d484b7d0Sotto 	case EL_GETCFN:
284d484b7d0Sotto 	{
285aed0ee81Snicm 		el_rfunc_t rc = va_arg(ap, el_rfunc_t);
28604833be7Sschwarze 		rv = el_read_setfn(el->el_read, rc);
287d484b7d0Sotto 		break;
288d484b7d0Sotto 	}
289d484b7d0Sotto 
290d484b7d0Sotto 	case EL_CLIENTDATA:
291aed0ee81Snicm 		el->el_data = va_arg(ap, void *);
292d484b7d0Sotto 		break;
293d484b7d0Sotto 
294d484b7d0Sotto 	case EL_UNBUFFERED:
295aed0ee81Snicm 		rv = va_arg(ap, int);
296d484b7d0Sotto 		if (rv && !(el->el_flags & UNBUFFERED)) {
297d484b7d0Sotto 			el->el_flags |= UNBUFFERED;
298d484b7d0Sotto 			read_prepare(el);
299d484b7d0Sotto 		} else if (!rv && (el->el_flags & UNBUFFERED)) {
300d484b7d0Sotto 			el->el_flags &= ~UNBUFFERED;
301d484b7d0Sotto 			read_finish(el);
302d484b7d0Sotto 		}
303d484b7d0Sotto 		rv = 0;
304d484b7d0Sotto 		break;
305d484b7d0Sotto 
3066e02e073Sotto 	case EL_PREP_TERM:
307aed0ee81Snicm 		rv = va_arg(ap, int);
3086e02e073Sotto 		if (rv)
309aed0ee81Snicm 			(void) tty_rawmode(el);
3106e02e073Sotto 		else
311aed0ee81Snicm 			(void) tty_cookedmode(el);
3126e02e073Sotto 		rv = 0;
3136e02e073Sotto 		break;
3146e02e073Sotto 
315aed0ee81Snicm 	case EL_SETFP:
316aed0ee81Snicm 	{
317aed0ee81Snicm 		FILE *fp;
318aed0ee81Snicm 		int what;
319aed0ee81Snicm 
320aed0ee81Snicm 		what = va_arg(ap, int);
321aed0ee81Snicm 		fp = va_arg(ap, FILE *);
322aed0ee81Snicm 
323aed0ee81Snicm 		rv = 0;
324aed0ee81Snicm 		switch (what) {
325aed0ee81Snicm 		case 0:
326aed0ee81Snicm 			el->el_infile = fp;
327aed0ee81Snicm 			el->el_infd = fileno(fp);
328aed0ee81Snicm 			break;
329aed0ee81Snicm 		case 1:
330aed0ee81Snicm 			el->el_outfile = fp;
3315f805b19Sokan 			el->el_outfd = fileno(fp);
332aed0ee81Snicm 			break;
333aed0ee81Snicm 		case 2:
334aed0ee81Snicm 			el->el_errfile = fp;
3355f805b19Sokan 			el->el_errfd = fileno(fp);
336aed0ee81Snicm 			break;
337aed0ee81Snicm 		default:
338aed0ee81Snicm 			rv = -1;
339aed0ee81Snicm 			break;
340aed0ee81Snicm 		}
341aed0ee81Snicm 		break;
342aed0ee81Snicm 	}
343aed0ee81Snicm 
344aed0ee81Snicm 	case EL_REFRESH:
345aed0ee81Snicm 		re_clear_display(el);
346aed0ee81Snicm 		re_refresh(el);
347fd40972aSschwarze 		terminal__flush(el);
348aed0ee81Snicm 		break;
349aed0ee81Snicm 
350d484b7d0Sotto 	default:
351d484b7d0Sotto 		rv = -1;
352d484b7d0Sotto 		break;
353d484b7d0Sotto 	}
354d484b7d0Sotto 
355aed0ee81Snicm 	va_end(ap);
35628d54ee8Sschwarze 	return rv;
357d484b7d0Sotto }
358d484b7d0Sotto 
359d484b7d0Sotto 
360d484b7d0Sotto /* el_get():
361d484b7d0Sotto  *	retrieve the editline parameters
362d484b7d0Sotto  */
363ddc81437Sschwarze int
el_wget(EditLine * el,int op,...)3645c93237dSschwarze el_wget(EditLine *el, int op, ...)
365d484b7d0Sotto {
366aed0ee81Snicm 	va_list ap;
367d484b7d0Sotto 	int rv;
368d484b7d0Sotto 
369aed0ee81Snicm 	if (el == NULL)
370aed0ee81Snicm 		return -1;
371aed0ee81Snicm 
372aed0ee81Snicm 	va_start(ap, op);
373aed0ee81Snicm 
374d484b7d0Sotto 	switch (op) {
375d484b7d0Sotto 	case EL_PROMPT:
376aed0ee81Snicm 	case EL_RPROMPT: {
377aed0ee81Snicm 		el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
378aed0ee81Snicm 		rv = prompt_get(el, p, 0, op);
379d484b7d0Sotto 		break;
380aed0ee81Snicm 	}
381aed0ee81Snicm 	case EL_PROMPT_ESC:
382aed0ee81Snicm 	case EL_RPROMPT_ESC: {
383aed0ee81Snicm 		el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
384e3191321Sschwarze 		wchar_t *c = va_arg(ap, wchar_t *);
385aed0ee81Snicm 
386aed0ee81Snicm 		rv = prompt_get(el, p, c, op);
387aed0ee81Snicm 		break;
388aed0ee81Snicm 	}
389d484b7d0Sotto 
390d484b7d0Sotto 	case EL_EDITOR:
391e3191321Sschwarze 		rv = map_get_editor(el, va_arg(ap, const wchar_t **));
392d484b7d0Sotto 		break;
393d484b7d0Sotto 
394d484b7d0Sotto 	case EL_SIGNAL:
395aed0ee81Snicm 		*va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
396d484b7d0Sotto 		rv = 0;
397d484b7d0Sotto 		break;
398d484b7d0Sotto 
399d484b7d0Sotto 	case EL_EDITMODE:
400aed0ee81Snicm 		*va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
401d484b7d0Sotto 		rv = 0;
402d484b7d0Sotto 		break;
403d484b7d0Sotto 
404d484b7d0Sotto 	case EL_TERMINAL:
405fd40972aSschwarze 		terminal_get(el, va_arg(ap, const char **));
406d484b7d0Sotto 		rv = 0;
407d484b7d0Sotto 		break;
408d484b7d0Sotto 
409aed0ee81Snicm 	case EL_GETTC:
410d484b7d0Sotto 	{
411aed0ee81Snicm 		static char name[] = "gettc";
412aed0ee81Snicm 		char *argv[20];
413d484b7d0Sotto 		int i;
414d484b7d0Sotto 
415aed0ee81Snicm 		for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++)
416aed0ee81Snicm 			if ((argv[i] = va_arg(ap, char *)) == NULL)
417d484b7d0Sotto 				break;
418d484b7d0Sotto 
419d484b7d0Sotto 		switch (op) {
420aed0ee81Snicm 		case EL_GETTC:
421aed0ee81Snicm 			argv[0] = name;
422fd40972aSschwarze 			rv = terminal_gettc(el, i, argv);
423d484b7d0Sotto 			break;
424d484b7d0Sotto 
425d484b7d0Sotto 		default:
426d484b7d0Sotto 			rv = -1;
427aed0ee81Snicm 			EL_ABORT((el->el_errfile, "Bad op %d\n", op));
428d484b7d0Sotto 			break;
429df930be7Sderaadt 		}
430df930be7Sderaadt 		break;
431d484b7d0Sotto 	}
432d484b7d0Sotto 
433d484b7d0Sotto 	case EL_GETCFN:
43404833be7Sschwarze 		*va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read);
435d484b7d0Sotto 		rv = 0;
436d484b7d0Sotto 		break;
437d484b7d0Sotto 
438d484b7d0Sotto 	case EL_CLIENTDATA:
439aed0ee81Snicm 		*va_arg(ap, void **) = el->el_data;
440d484b7d0Sotto 		rv = 0;
441d484b7d0Sotto 		break;
442d484b7d0Sotto 
443d484b7d0Sotto 	case EL_UNBUFFERED:
444aed0ee81Snicm 		*va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
445d484b7d0Sotto 		rv = 0;
446d484b7d0Sotto 		break;
447df930be7Sderaadt 
448aed0ee81Snicm 	case EL_GETFP:
449aed0ee81Snicm 	{
450aed0ee81Snicm 		int what;
451aed0ee81Snicm 		FILE **fpp;
452aed0ee81Snicm 
453aed0ee81Snicm 		what = va_arg(ap, int);
454aed0ee81Snicm 		fpp = va_arg(ap, FILE **);
455aed0ee81Snicm 		rv = 0;
456aed0ee81Snicm 		switch (what) {
457aed0ee81Snicm 		case 0:
458aed0ee81Snicm 			*fpp = el->el_infile;
459aed0ee81Snicm 			break;
460aed0ee81Snicm 		case 1:
461aed0ee81Snicm 			*fpp = el->el_outfile;
462aed0ee81Snicm 			break;
463aed0ee81Snicm 		case 2:
464aed0ee81Snicm 			*fpp = el->el_errfile;
465aed0ee81Snicm 			break;
466df930be7Sderaadt 		default:
467df930be7Sderaadt 			rv = -1;
468aed0ee81Snicm 			break;
469df930be7Sderaadt 		}
470aed0ee81Snicm 		break;
471aed0ee81Snicm 	}
472aed0ee81Snicm 	default:
473aed0ee81Snicm 		rv = -1;
474aed0ee81Snicm 		break;
475aed0ee81Snicm 	}
476aed0ee81Snicm 	va_end(ap);
477df930be7Sderaadt 
47828d54ee8Sschwarze 	return rv;
479d484b7d0Sotto }
480df930be7Sderaadt 
481df930be7Sderaadt 
482df930be7Sderaadt /* el_line():
483df930be7Sderaadt  *	Return editing info
484df930be7Sderaadt  */
485ddc81437Sschwarze const LineInfoW *
el_wline(EditLine * el)4865c93237dSschwarze el_wline(EditLine *el)
487df930be7Sderaadt {
488d484b7d0Sotto 
4895c93237dSschwarze 	return (const LineInfoW *)(void *)&el->el_line;
490df930be7Sderaadt }
491df930be7Sderaadt 
492df930be7Sderaadt 
493df930be7Sderaadt /* el_source():
494df930be7Sderaadt  *	Source a file
495df930be7Sderaadt  */
496ddc81437Sschwarze int
el_source(EditLine * el,const char * fname)497d484b7d0Sotto el_source(EditLine *el, const char *fname)
498df930be7Sderaadt {
499df930be7Sderaadt 	FILE *fp;
500df930be7Sderaadt 	size_t len;
501f3a50c9eSschwarze 	ssize_t slen;
502f3a50c9eSschwarze 	char *ptr;
503aed0ee81Snicm #ifdef HAVE_ISSETUGID
504aea60beeSderaadt 	char path[PATH_MAX];
505aed0ee81Snicm #endif
506e3191321Sschwarze 	const wchar_t *dptr;
507df930be7Sderaadt 
508d484b7d0Sotto 	fp = NULL;
509df930be7Sderaadt 	if (fname == NULL) {
510d484b7d0Sotto #ifdef HAVE_ISSETUGID
511d484b7d0Sotto 		static const char elpath[] = "/.editrc";
512df930be7Sderaadt 
513d484b7d0Sotto 		if (issetugid())
51428d54ee8Sschwarze 			return -1;
515d484b7d0Sotto 		if ((ptr = getenv("HOME")) == NULL)
51628d54ee8Sschwarze 			return -1;
517d484b7d0Sotto 		if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
51828d54ee8Sschwarze 			return -1;
519d484b7d0Sotto 		if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
52028d54ee8Sschwarze 			return -1;
521d484b7d0Sotto 		fname = path;
522d484b7d0Sotto #else
523d484b7d0Sotto 		/*
524d484b7d0Sotto 		 * If issetugid() is missing, always return an error, in order
525d484b7d0Sotto 		 * to keep from inadvertently opening up the user to a security
526d484b7d0Sotto 		 * hole.
527d484b7d0Sotto 		 */
52828d54ee8Sschwarze 		return -1;
529d484b7d0Sotto #endif
530d484b7d0Sotto 	}
531d484b7d0Sotto 	if (fp == NULL)
532d484b7d0Sotto 		fp = fopen(fname, "r");
533d484b7d0Sotto 	if (fp == NULL)
53428d54ee8Sschwarze 		return -1;
535df930be7Sderaadt 
536f3a50c9eSschwarze 	ptr = NULL;
537f3a50c9eSschwarze 	len = 0;
538f3a50c9eSschwarze 	while ((slen = getline(&ptr, &len, fp)) != -1) {
539f3a50c9eSschwarze 		if (*ptr == '\n')
540f3a50c9eSschwarze 			continue;	/* Empty line. */
541f3a50c9eSschwarze 		if (slen > 0 && ptr[--slen] == '\n')
542f3a50c9eSschwarze 			ptr[slen] = '\0';
543b51eafdaSotto 
544aed0ee81Snicm 		dptr = ct_decode_string(ptr, &el->el_scratch);
545aed0ee81Snicm 		if (!dptr)
546aed0ee81Snicm 			continue;
547aed0ee81Snicm 		/* loop until first non-space char or EOL */
548565aa7e8Sschwarze 		while (*dptr != '\0' && iswspace(*dptr))
549aed0ee81Snicm 			dptr++;
550aed0ee81Snicm 		if (*dptr == '#')
551aed0ee81Snicm 			continue;   /* ignore, this is a comment line */
552aed0ee81Snicm 		if (parse_line(el, dptr) == -1) {
553f3a50c9eSschwarze 			free(ptr);
554df930be7Sderaadt 			(void) fclose(fp);
55528d54ee8Sschwarze 			return -1;
556df930be7Sderaadt 		}
557f840f2e0Smillert 	}
558f3a50c9eSschwarze 	free(ptr);
559df930be7Sderaadt 	(void) fclose(fp);
56028d54ee8Sschwarze 	return 0;
561df930be7Sderaadt }
562df930be7Sderaadt 
563df930be7Sderaadt 
564df930be7Sderaadt /* el_resize():
565df930be7Sderaadt  *	Called from program when terminal is resized
566df930be7Sderaadt  */
567ddc81437Sschwarze void
el_resize(EditLine * el)568d484b7d0Sotto el_resize(EditLine *el)
569df930be7Sderaadt {
570df930be7Sderaadt 	int lins, cols;
571df930be7Sderaadt 	sigset_t oset, nset;
572d484b7d0Sotto 
573df930be7Sderaadt 	(void) sigemptyset(&nset);
574df930be7Sderaadt 	(void) sigaddset(&nset, SIGWINCH);
575df930be7Sderaadt 	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
576df930be7Sderaadt 
577df930be7Sderaadt 	/* get the correct window size */
578fd40972aSschwarze 	if (terminal_get_size(el, &lins, &cols))
579fd40972aSschwarze 		terminal_change_size(el, lins, cols);
580df930be7Sderaadt 
581df930be7Sderaadt 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
582df930be7Sderaadt }
583d484b7d0Sotto 
584d484b7d0Sotto 
585d484b7d0Sotto /* el_beep():
586d484b7d0Sotto  *	Called from the program to beep
587d484b7d0Sotto  */
588ddc81437Sschwarze void
el_beep(EditLine * el)589d484b7d0Sotto el_beep(EditLine *el)
590d484b7d0Sotto {
591d484b7d0Sotto 
592fd40972aSschwarze 	terminal_beep(el);
593d484b7d0Sotto }
594d484b7d0Sotto 
595d484b7d0Sotto 
596d484b7d0Sotto /* el_editmode()
597d484b7d0Sotto  *	Set the state of EDIT_DISABLED from the `edit' command.
598d484b7d0Sotto  */
599d484b7d0Sotto protected int
el_editmode(EditLine * el,int argc,const wchar_t ** argv)600e3191321Sschwarze el_editmode(EditLine *el, int argc, const wchar_t **argv)
601d484b7d0Sotto {
602e3191321Sschwarze 	const wchar_t *how;
603d484b7d0Sotto 
604d484b7d0Sotto 	if (argv == NULL || argc != 2 || argv[1] == NULL)
60528d54ee8Sschwarze 		return -1;
606d484b7d0Sotto 
607d484b7d0Sotto 	how = argv[1];
6085c93237dSschwarze 	if (wcscmp(how, L"on") == 0) {
609d484b7d0Sotto 		el->el_flags &= ~EDIT_DISABLED;
610aed0ee81Snicm 		tty_rawmode(el);
6115c93237dSschwarze 	} else if (wcscmp(how, L"off") == 0) {
612aed0ee81Snicm 		tty_cookedmode(el);
613d484b7d0Sotto 		el->el_flags |= EDIT_DISABLED;
614aed0ee81Snicm 	}
615d484b7d0Sotto 	else {
616565aa7e8Sschwarze 		(void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n",
617aed0ee81Snicm 		    how);
61828d54ee8Sschwarze 		return -1;
619d484b7d0Sotto 	}
62028d54ee8Sschwarze 	return 0;
621d484b7d0Sotto }
622