xref: /freebsd-src/contrib/libedit/el.c (revision baff81958c8efef2a44f4b769743eeb7101bee9e)
1*baff8195SBaptiste Daroussin /*	$NetBSD: el.c,v 1.101 2022/10/30 19:11:31 christos Exp $	*/
2d0ef721eSBaptiste Daroussin 
3d0ef721eSBaptiste Daroussin /*-
4d0ef721eSBaptiste Daroussin  * Copyright (c) 1992, 1993
5d0ef721eSBaptiste Daroussin  *	The Regents of the University of California.  All rights reserved.
6d0ef721eSBaptiste Daroussin  *
7d0ef721eSBaptiste Daroussin  * This code is derived from software contributed to Berkeley by
8d0ef721eSBaptiste Daroussin  * Christos Zoulas of Cornell University.
9d0ef721eSBaptiste Daroussin  *
10d0ef721eSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
11d0ef721eSBaptiste Daroussin  * modification, are permitted provided that the following conditions
12d0ef721eSBaptiste Daroussin  * are met:
13d0ef721eSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
14d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
15d0ef721eSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
16d0ef721eSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
17d0ef721eSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
18d0ef721eSBaptiste Daroussin  * 3. Neither the name of the University nor the names of its contributors
19d0ef721eSBaptiste Daroussin  *    may be used to endorse or promote products derived from this software
20d0ef721eSBaptiste Daroussin  *    without specific prior written permission.
21d0ef721eSBaptiste Daroussin  *
22d0ef721eSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23d0ef721eSBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24d0ef721eSBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25d0ef721eSBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26d0ef721eSBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27d0ef721eSBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28d0ef721eSBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29d0ef721eSBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30d0ef721eSBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31d0ef721eSBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32d0ef721eSBaptiste Daroussin  * SUCH DAMAGE.
33d0ef721eSBaptiste Daroussin  */
34d0ef721eSBaptiste Daroussin 
35d0ef721eSBaptiste Daroussin #include "config.h"
36d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID)
37d0ef721eSBaptiste Daroussin #if 0
38d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";
39d0ef721eSBaptiste Daroussin #else
40*baff8195SBaptiste Daroussin __RCSID("$NetBSD: el.c,v 1.101 2022/10/30 19:11:31 christos Exp $");
41d0ef721eSBaptiste Daroussin #endif
42d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */
43d0ef721eSBaptiste Daroussin 
44d0ef721eSBaptiste Daroussin /*
45d0ef721eSBaptiste Daroussin  * el.c: EditLine interface functions
46d0ef721eSBaptiste Daroussin  */
47d0ef721eSBaptiste Daroussin #include <sys/types.h>
48d0ef721eSBaptiste Daroussin #include <sys/param.h>
49d0ef721eSBaptiste Daroussin #include <ctype.h>
50d0ef721eSBaptiste Daroussin #include <langinfo.h>
51d0ef721eSBaptiste Daroussin #include <locale.h>
52d0ef721eSBaptiste Daroussin #include <stdarg.h>
53d0ef721eSBaptiste Daroussin #include <stdlib.h>
54d0ef721eSBaptiste Daroussin #include <string.h>
55d0ef721eSBaptiste Daroussin 
56d0ef721eSBaptiste Daroussin #include "el.h"
57d0ef721eSBaptiste Daroussin #include "parse.h"
58d0ef721eSBaptiste Daroussin #include "read.h"
59d0ef721eSBaptiste Daroussin 
60d0ef721eSBaptiste Daroussin /* el_init():
61d0ef721eSBaptiste Daroussin  *	Initialize editline and set default parameters.
62d0ef721eSBaptiste Daroussin  */
63d0ef721eSBaptiste Daroussin EditLine *
el_init(const char * prog,FILE * fin,FILE * fout,FILE * ferr)64d0ef721eSBaptiste Daroussin el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
65d0ef721eSBaptiste Daroussin {
66d0ef721eSBaptiste Daroussin     return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout),
67d0ef721eSBaptiste Daroussin 	fileno(ferr));
68d0ef721eSBaptiste Daroussin }
69d0ef721eSBaptiste Daroussin 
70d0ef721eSBaptiste Daroussin libedit_private EditLine *
el_init_internal(const char * prog,FILE * fin,FILE * fout,FILE * ferr,int fdin,int fdout,int fderr,int flags)71d0ef721eSBaptiste Daroussin el_init_internal(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
72d0ef721eSBaptiste Daroussin     int fdin, int fdout, int fderr, int flags)
73d0ef721eSBaptiste Daroussin {
74d0ef721eSBaptiste Daroussin 	EditLine *el = el_calloc(1, sizeof(*el));
75d0ef721eSBaptiste Daroussin 
76d0ef721eSBaptiste Daroussin 	if (el == NULL)
77d0ef721eSBaptiste Daroussin 		return NULL;
78d0ef721eSBaptiste Daroussin 
79d0ef721eSBaptiste Daroussin 	el->el_infile = fin;
80d0ef721eSBaptiste Daroussin 	el->el_outfile = fout;
81d0ef721eSBaptiste Daroussin 	el->el_errfile = ferr;
82d0ef721eSBaptiste Daroussin 
83d0ef721eSBaptiste Daroussin 	el->el_infd = fdin;
84d0ef721eSBaptiste Daroussin 	el->el_outfd = fdout;
85d0ef721eSBaptiste Daroussin 	el->el_errfd = fderr;
86d0ef721eSBaptiste Daroussin 
87d0ef721eSBaptiste Daroussin 	el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch));
88d0ef721eSBaptiste Daroussin 	if (el->el_prog == NULL) {
89d0ef721eSBaptiste Daroussin 		el_free(el);
90d0ef721eSBaptiste Daroussin 		return NULL;
91d0ef721eSBaptiste Daroussin 	}
92d0ef721eSBaptiste Daroussin 
93d0ef721eSBaptiste Daroussin 	/*
94d0ef721eSBaptiste Daroussin          * Initialize all the modules. Order is important!!!
95d0ef721eSBaptiste Daroussin          */
96d0ef721eSBaptiste Daroussin 	el->el_flags = flags;
97d0ef721eSBaptiste Daroussin 
98d0ef721eSBaptiste Daroussin 	if (terminal_init(el) == -1) {
99d0ef721eSBaptiste Daroussin 		el_free(el->el_prog);
100d0ef721eSBaptiste Daroussin 		el_free(el);
101d0ef721eSBaptiste Daroussin 		return NULL;
102d0ef721eSBaptiste Daroussin 	}
103d0ef721eSBaptiste Daroussin 	(void) keymacro_init(el);
104d0ef721eSBaptiste Daroussin 	(void) map_init(el);
105d0ef721eSBaptiste Daroussin 	if (tty_init(el) == -1)
106d0ef721eSBaptiste Daroussin 		el->el_flags |= NO_TTY;
107d0ef721eSBaptiste Daroussin 	(void) ch_init(el);
108d0ef721eSBaptiste Daroussin 	(void) search_init(el);
109d0ef721eSBaptiste Daroussin 	(void) hist_init(el);
110d0ef721eSBaptiste Daroussin 	(void) prompt_init(el);
111d0ef721eSBaptiste Daroussin 	(void) sig_init(el);
112d0ef721eSBaptiste Daroussin 	(void) literal_init(el);
113d0ef721eSBaptiste Daroussin 	if (read_init(el) == -1) {
114d0ef721eSBaptiste Daroussin 		el_end(el);
115d0ef721eSBaptiste Daroussin 		return NULL;
116d0ef721eSBaptiste Daroussin 	}
117d0ef721eSBaptiste Daroussin 	return el;
118d0ef721eSBaptiste Daroussin }
119d0ef721eSBaptiste Daroussin 
120d0ef721eSBaptiste Daroussin EditLine *
el_init_fd(const char * prog,FILE * fin,FILE * fout,FILE * ferr,int fdin,int fdout,int fderr)121d0ef721eSBaptiste Daroussin el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
122d0ef721eSBaptiste Daroussin     int fdin, int fdout, int fderr)
123d0ef721eSBaptiste Daroussin {
124d0ef721eSBaptiste Daroussin 	return el_init_internal(prog, fin, fout, ferr, fdin, fdout, fderr, 0);
125d0ef721eSBaptiste Daroussin }
126d0ef721eSBaptiste Daroussin 
127d0ef721eSBaptiste Daroussin /* el_end():
128d0ef721eSBaptiste Daroussin  *	Clean up.
129d0ef721eSBaptiste Daroussin  */
130d0ef721eSBaptiste Daroussin void
el_end(EditLine * el)131d0ef721eSBaptiste Daroussin el_end(EditLine *el)
132d0ef721eSBaptiste Daroussin {
133d0ef721eSBaptiste Daroussin 
134d0ef721eSBaptiste Daroussin 	if (el == NULL)
135d0ef721eSBaptiste Daroussin 		return;
136d0ef721eSBaptiste Daroussin 
137d0ef721eSBaptiste Daroussin 	el_reset(el);
138d0ef721eSBaptiste Daroussin 
139d0ef721eSBaptiste Daroussin 	terminal_end(el);
140d0ef721eSBaptiste Daroussin 	keymacro_end(el);
141d0ef721eSBaptiste Daroussin 	map_end(el);
142d0ef721eSBaptiste Daroussin 	if (!(el->el_flags & NO_TTY))
143d0ef721eSBaptiste Daroussin 		tty_end(el, TCSAFLUSH);
144d0ef721eSBaptiste Daroussin 	ch_end(el);
145*baff8195SBaptiste Daroussin 	read_end(el);
146d0ef721eSBaptiste Daroussin 	search_end(el);
147d0ef721eSBaptiste Daroussin 	hist_end(el);
148d0ef721eSBaptiste Daroussin 	prompt_end(el);
149d0ef721eSBaptiste Daroussin 	sig_end(el);
150d0ef721eSBaptiste Daroussin 	literal_end(el);
151d0ef721eSBaptiste Daroussin 
152d0ef721eSBaptiste Daroussin 	el_free(el->el_prog);
153d0ef721eSBaptiste Daroussin 	el_free(el->el_visual.cbuff);
154d0ef721eSBaptiste Daroussin 	el_free(el->el_visual.wbuff);
155d0ef721eSBaptiste Daroussin 	el_free(el->el_scratch.cbuff);
156d0ef721eSBaptiste Daroussin 	el_free(el->el_scratch.wbuff);
157d0ef721eSBaptiste Daroussin 	el_free(el->el_lgcyconv.cbuff);
158d0ef721eSBaptiste Daroussin 	el_free(el->el_lgcyconv.wbuff);
159d0ef721eSBaptiste Daroussin 	el_free(el);
160d0ef721eSBaptiste Daroussin }
161d0ef721eSBaptiste Daroussin 
162d0ef721eSBaptiste Daroussin 
163d0ef721eSBaptiste Daroussin /* el_reset():
164d0ef721eSBaptiste Daroussin  *	Reset the tty and the parser
165d0ef721eSBaptiste Daroussin  */
166d0ef721eSBaptiste Daroussin void
el_reset(EditLine * el)167d0ef721eSBaptiste Daroussin el_reset(EditLine *el)
168d0ef721eSBaptiste Daroussin {
169d0ef721eSBaptiste Daroussin 
170d0ef721eSBaptiste Daroussin 	tty_cookedmode(el);
171d0ef721eSBaptiste Daroussin 	ch_reset(el);		/* XXX: Do we want that? */
172d0ef721eSBaptiste Daroussin }
173d0ef721eSBaptiste Daroussin 
174d0ef721eSBaptiste Daroussin 
175d0ef721eSBaptiste Daroussin /* el_set():
176d0ef721eSBaptiste Daroussin  *	set the editline parameters
177d0ef721eSBaptiste Daroussin  */
178d0ef721eSBaptiste Daroussin int
el_wset(EditLine * el,int op,...)179d0ef721eSBaptiste Daroussin el_wset(EditLine *el, int op, ...)
180d0ef721eSBaptiste Daroussin {
181d0ef721eSBaptiste Daroussin 	va_list ap;
182d0ef721eSBaptiste Daroussin 	int rv = 0;
183d0ef721eSBaptiste Daroussin 
184d0ef721eSBaptiste Daroussin 	if (el == NULL)
185d0ef721eSBaptiste Daroussin 		return -1;
186d0ef721eSBaptiste Daroussin 	va_start(ap, op);
187d0ef721eSBaptiste Daroussin 
188d0ef721eSBaptiste Daroussin 	switch (op) {
189d0ef721eSBaptiste Daroussin 	case EL_PROMPT:
190d0ef721eSBaptiste Daroussin 	case EL_RPROMPT: {
191d0ef721eSBaptiste Daroussin 		el_pfunc_t p = va_arg(ap, el_pfunc_t);
192d0ef721eSBaptiste Daroussin 
193d0ef721eSBaptiste Daroussin 		rv = prompt_set(el, p, 0, op, 1);
194d0ef721eSBaptiste Daroussin 		break;
195d0ef721eSBaptiste Daroussin 	}
196d0ef721eSBaptiste Daroussin 
197d0ef721eSBaptiste Daroussin 	case EL_RESIZE: {
198d0ef721eSBaptiste Daroussin 		el_zfunc_t p = va_arg(ap, el_zfunc_t);
199d0ef721eSBaptiste Daroussin 		void *arg = va_arg(ap, void *);
200d0ef721eSBaptiste Daroussin 		rv = ch_resizefun(el, p, arg);
201d0ef721eSBaptiste Daroussin 		break;
202d0ef721eSBaptiste Daroussin 	}
203d0ef721eSBaptiste Daroussin 
204d0ef721eSBaptiste Daroussin 	case EL_ALIAS_TEXT: {
205d0ef721eSBaptiste Daroussin 		el_afunc_t p = va_arg(ap, el_afunc_t);
206d0ef721eSBaptiste Daroussin 		void *arg = va_arg(ap, void *);
207d0ef721eSBaptiste Daroussin 		rv = ch_aliasfun(el, p, arg);
208d0ef721eSBaptiste Daroussin 		break;
209d0ef721eSBaptiste Daroussin 	}
210d0ef721eSBaptiste Daroussin 
211d0ef721eSBaptiste Daroussin 	case EL_PROMPT_ESC:
212d0ef721eSBaptiste Daroussin 	case EL_RPROMPT_ESC: {
213d0ef721eSBaptiste Daroussin 		el_pfunc_t p = va_arg(ap, el_pfunc_t);
214d0ef721eSBaptiste Daroussin 		int c = va_arg(ap, int);
215d0ef721eSBaptiste Daroussin 
216d0ef721eSBaptiste Daroussin 		rv = prompt_set(el, p, (wchar_t)c, op, 1);
217d0ef721eSBaptiste Daroussin 		break;
218d0ef721eSBaptiste Daroussin 	}
219d0ef721eSBaptiste Daroussin 
220d0ef721eSBaptiste Daroussin 	case EL_TERMINAL:
221d0ef721eSBaptiste Daroussin 		rv = terminal_set(el, va_arg(ap, char *));
222d0ef721eSBaptiste Daroussin 		break;
223d0ef721eSBaptiste Daroussin 
224d0ef721eSBaptiste Daroussin 	case EL_EDITOR:
225d0ef721eSBaptiste Daroussin 		rv = map_set_editor(el, va_arg(ap, wchar_t *));
226d0ef721eSBaptiste Daroussin 		break;
227d0ef721eSBaptiste Daroussin 
228d0ef721eSBaptiste Daroussin 	case EL_SIGNAL:
229d0ef721eSBaptiste Daroussin 		if (va_arg(ap, int))
230d0ef721eSBaptiste Daroussin 			el->el_flags |= HANDLE_SIGNALS;
231d0ef721eSBaptiste Daroussin 		else
232d0ef721eSBaptiste Daroussin 			el->el_flags &= ~HANDLE_SIGNALS;
233d0ef721eSBaptiste Daroussin 		break;
234d0ef721eSBaptiste Daroussin 
235d0ef721eSBaptiste Daroussin 	case EL_BIND:
236d0ef721eSBaptiste Daroussin 	case EL_TELLTC:
237d0ef721eSBaptiste Daroussin 	case EL_SETTC:
238d0ef721eSBaptiste Daroussin 	case EL_ECHOTC:
239d0ef721eSBaptiste Daroussin 	case EL_SETTY:
240d0ef721eSBaptiste Daroussin 	{
241d0ef721eSBaptiste Daroussin 		const wchar_t *argv[20];
242d0ef721eSBaptiste Daroussin 		int i;
243d0ef721eSBaptiste Daroussin 
244d0ef721eSBaptiste Daroussin 		for (i = 1; i < (int)__arraycount(argv); i++)
245d0ef721eSBaptiste Daroussin 			if ((argv[i] = va_arg(ap, wchar_t *)) == NULL)
246d0ef721eSBaptiste Daroussin 				break;
247d0ef721eSBaptiste Daroussin 
248d0ef721eSBaptiste Daroussin 		switch (op) {
249d0ef721eSBaptiste Daroussin 		case EL_BIND:
250d0ef721eSBaptiste Daroussin 			argv[0] = L"bind";
251d0ef721eSBaptiste Daroussin 			rv = map_bind(el, i, argv);
252d0ef721eSBaptiste Daroussin 			break;
253d0ef721eSBaptiste Daroussin 
254d0ef721eSBaptiste Daroussin 		case EL_TELLTC:
255d0ef721eSBaptiste Daroussin 			argv[0] = L"telltc";
256d0ef721eSBaptiste Daroussin 			rv = terminal_telltc(el, i, argv);
257d0ef721eSBaptiste Daroussin 			break;
258d0ef721eSBaptiste Daroussin 
259d0ef721eSBaptiste Daroussin 		case EL_SETTC:
260d0ef721eSBaptiste Daroussin 			argv[0] = L"settc";
261d0ef721eSBaptiste Daroussin 			rv = terminal_settc(el, i, argv);
262d0ef721eSBaptiste Daroussin 			break;
263d0ef721eSBaptiste Daroussin 
264d0ef721eSBaptiste Daroussin 		case EL_ECHOTC:
265d0ef721eSBaptiste Daroussin 			argv[0] = L"echotc";
266d0ef721eSBaptiste Daroussin 			rv = terminal_echotc(el, i, argv);
267d0ef721eSBaptiste Daroussin 			break;
268d0ef721eSBaptiste Daroussin 
269d0ef721eSBaptiste Daroussin 		case EL_SETTY:
270d0ef721eSBaptiste Daroussin 			argv[0] = L"setty";
271d0ef721eSBaptiste Daroussin 			rv = tty_stty(el, i, argv);
272d0ef721eSBaptiste Daroussin 			break;
273d0ef721eSBaptiste Daroussin 
274d0ef721eSBaptiste Daroussin 		default:
275d0ef721eSBaptiste Daroussin 			rv = -1;
276d0ef721eSBaptiste Daroussin 			EL_ABORT((el->el_errfile, "Bad op %d\n", op));
277d0ef721eSBaptiste Daroussin 			break;
278d0ef721eSBaptiste Daroussin 		}
279d0ef721eSBaptiste Daroussin 		break;
280d0ef721eSBaptiste Daroussin 	}
281d0ef721eSBaptiste Daroussin 
282d0ef721eSBaptiste Daroussin 	case EL_ADDFN:
283d0ef721eSBaptiste Daroussin 	{
284d0ef721eSBaptiste Daroussin 		wchar_t *name = va_arg(ap, wchar_t *);
285d0ef721eSBaptiste Daroussin 		wchar_t *help = va_arg(ap, wchar_t *);
286d0ef721eSBaptiste Daroussin 		el_func_t func = va_arg(ap, el_func_t);
287d0ef721eSBaptiste Daroussin 
288d0ef721eSBaptiste Daroussin 		rv = map_addfunc(el, name, help, func);
289d0ef721eSBaptiste Daroussin 		break;
290d0ef721eSBaptiste Daroussin 	}
291d0ef721eSBaptiste Daroussin 
292d0ef721eSBaptiste Daroussin 	case EL_HIST:
293d0ef721eSBaptiste Daroussin 	{
294d0ef721eSBaptiste Daroussin 		hist_fun_t func = va_arg(ap, hist_fun_t);
295d0ef721eSBaptiste Daroussin 		void *ptr = va_arg(ap, void *);
296d0ef721eSBaptiste Daroussin 
297d0ef721eSBaptiste Daroussin 		rv = hist_set(el, func, ptr);
298d0ef721eSBaptiste Daroussin 		if (MB_CUR_MAX == 1)
299d0ef721eSBaptiste Daroussin 			el->el_flags &= ~NARROW_HISTORY;
300d0ef721eSBaptiste Daroussin 		break;
301d0ef721eSBaptiste Daroussin 	}
302d0ef721eSBaptiste Daroussin 
30391f76417SBaptiste Daroussin 	case EL_SAFEREAD:
30491f76417SBaptiste Daroussin 		if (va_arg(ap, int))
30591f76417SBaptiste Daroussin 			el->el_flags |= FIXIO;
30691f76417SBaptiste Daroussin 		else
30791f76417SBaptiste Daroussin 			el->el_flags &= ~FIXIO;
30891f76417SBaptiste Daroussin 		rv = 0;
30991f76417SBaptiste Daroussin 		break;
31091f76417SBaptiste Daroussin 
311d0ef721eSBaptiste Daroussin 	case EL_EDITMODE:
312d0ef721eSBaptiste Daroussin 		if (va_arg(ap, int))
313d0ef721eSBaptiste Daroussin 			el->el_flags &= ~EDIT_DISABLED;
314d0ef721eSBaptiste Daroussin 		else
315d0ef721eSBaptiste Daroussin 			el->el_flags |= EDIT_DISABLED;
316d0ef721eSBaptiste Daroussin 		rv = 0;
317d0ef721eSBaptiste Daroussin 		break;
318d0ef721eSBaptiste Daroussin 
319d0ef721eSBaptiste Daroussin 	case EL_GETCFN:
320d0ef721eSBaptiste Daroussin 	{
321d0ef721eSBaptiste Daroussin 		el_rfunc_t rc = va_arg(ap, el_rfunc_t);
322d0ef721eSBaptiste Daroussin 		rv = el_read_setfn(el->el_read, rc);
323d0ef721eSBaptiste Daroussin 		break;
324d0ef721eSBaptiste Daroussin 	}
325d0ef721eSBaptiste Daroussin 
326d0ef721eSBaptiste Daroussin 	case EL_CLIENTDATA:
327d0ef721eSBaptiste Daroussin 		el->el_data = va_arg(ap, void *);
328d0ef721eSBaptiste Daroussin 		break;
329d0ef721eSBaptiste Daroussin 
330d0ef721eSBaptiste Daroussin 	case EL_UNBUFFERED:
331d0ef721eSBaptiste Daroussin 		rv = va_arg(ap, int);
332d0ef721eSBaptiste Daroussin 		if (rv && !(el->el_flags & UNBUFFERED)) {
333d0ef721eSBaptiste Daroussin 			el->el_flags |= UNBUFFERED;
334d0ef721eSBaptiste Daroussin 			read_prepare(el);
335d0ef721eSBaptiste Daroussin 		} else if (!rv && (el->el_flags & UNBUFFERED)) {
336d0ef721eSBaptiste Daroussin 			el->el_flags &= ~UNBUFFERED;
337d0ef721eSBaptiste Daroussin 			read_finish(el);
338d0ef721eSBaptiste Daroussin 		}
339d0ef721eSBaptiste Daroussin 		rv = 0;
340d0ef721eSBaptiste Daroussin 		break;
341d0ef721eSBaptiste Daroussin 
342d0ef721eSBaptiste Daroussin 	case EL_PREP_TERM:
343d0ef721eSBaptiste Daroussin 		rv = va_arg(ap, int);
344d0ef721eSBaptiste Daroussin 		if (rv)
345d0ef721eSBaptiste Daroussin 			(void) tty_rawmode(el);
346d0ef721eSBaptiste Daroussin 		else
347d0ef721eSBaptiste Daroussin 			(void) tty_cookedmode(el);
348d0ef721eSBaptiste Daroussin 		rv = 0;
349d0ef721eSBaptiste Daroussin 		break;
350d0ef721eSBaptiste Daroussin 
351d0ef721eSBaptiste Daroussin 	case EL_SETFP:
352d0ef721eSBaptiste Daroussin 	{
353d0ef721eSBaptiste Daroussin 		FILE *fp;
354d0ef721eSBaptiste Daroussin 		int what;
355d0ef721eSBaptiste Daroussin 
356d0ef721eSBaptiste Daroussin 		what = va_arg(ap, int);
357d0ef721eSBaptiste Daroussin 		fp = va_arg(ap, FILE *);
358d0ef721eSBaptiste Daroussin 
359d0ef721eSBaptiste Daroussin 		rv = 0;
360d0ef721eSBaptiste Daroussin 		switch (what) {
361d0ef721eSBaptiste Daroussin 		case 0:
362d0ef721eSBaptiste Daroussin 			el->el_infile = fp;
363d0ef721eSBaptiste Daroussin 			el->el_infd = fileno(fp);
364d0ef721eSBaptiste Daroussin 			break;
365d0ef721eSBaptiste Daroussin 		case 1:
366d0ef721eSBaptiste Daroussin 			el->el_outfile = fp;
367d0ef721eSBaptiste Daroussin 			el->el_outfd = fileno(fp);
368d0ef721eSBaptiste Daroussin 			break;
369d0ef721eSBaptiste Daroussin 		case 2:
370d0ef721eSBaptiste Daroussin 			el->el_errfile = fp;
371d0ef721eSBaptiste Daroussin 			el->el_errfd = fileno(fp);
372d0ef721eSBaptiste Daroussin 			break;
373d0ef721eSBaptiste Daroussin 		default:
374d0ef721eSBaptiste Daroussin 			rv = -1;
375d0ef721eSBaptiste Daroussin 			break;
376d0ef721eSBaptiste Daroussin 		}
377d0ef721eSBaptiste Daroussin 		break;
378d0ef721eSBaptiste Daroussin 	}
379d0ef721eSBaptiste Daroussin 
380d0ef721eSBaptiste Daroussin 	case EL_REFRESH:
381d0ef721eSBaptiste Daroussin 		re_clear_display(el);
382d0ef721eSBaptiste Daroussin 		re_refresh(el);
383d0ef721eSBaptiste Daroussin 		terminal__flush(el);
384d0ef721eSBaptiste Daroussin 		break;
385d0ef721eSBaptiste Daroussin 
386d0ef721eSBaptiste Daroussin 	default:
387d0ef721eSBaptiste Daroussin 		rv = -1;
388d0ef721eSBaptiste Daroussin 		break;
389d0ef721eSBaptiste Daroussin 	}
390d0ef721eSBaptiste Daroussin 
391d0ef721eSBaptiste Daroussin 	va_end(ap);
392d0ef721eSBaptiste Daroussin 	return rv;
393d0ef721eSBaptiste Daroussin }
394d0ef721eSBaptiste Daroussin 
395d0ef721eSBaptiste Daroussin 
396d0ef721eSBaptiste Daroussin /* el_get():
397d0ef721eSBaptiste Daroussin  *	retrieve the editline parameters
398d0ef721eSBaptiste Daroussin  */
399d0ef721eSBaptiste Daroussin int
el_wget(EditLine * el,int op,...)400d0ef721eSBaptiste Daroussin el_wget(EditLine *el, int op, ...)
401d0ef721eSBaptiste Daroussin {
402d0ef721eSBaptiste Daroussin 	va_list ap;
403d0ef721eSBaptiste Daroussin 	int rv;
404d0ef721eSBaptiste Daroussin 
405d0ef721eSBaptiste Daroussin 	if (el == NULL)
406d0ef721eSBaptiste Daroussin 		return -1;
407d0ef721eSBaptiste Daroussin 
408d0ef721eSBaptiste Daroussin 	va_start(ap, op);
409d0ef721eSBaptiste Daroussin 
410d0ef721eSBaptiste Daroussin 	switch (op) {
411d0ef721eSBaptiste Daroussin 	case EL_PROMPT:
412d0ef721eSBaptiste Daroussin 	case EL_RPROMPT: {
413d0ef721eSBaptiste Daroussin 		el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
414d0ef721eSBaptiste Daroussin 		rv = prompt_get(el, p, 0, op);
415d0ef721eSBaptiste Daroussin 		break;
416d0ef721eSBaptiste Daroussin 	}
417d0ef721eSBaptiste Daroussin 	case EL_PROMPT_ESC:
418d0ef721eSBaptiste Daroussin 	case EL_RPROMPT_ESC: {
419d0ef721eSBaptiste Daroussin 		el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
420d0ef721eSBaptiste Daroussin 		wchar_t *c = va_arg(ap, wchar_t *);
421d0ef721eSBaptiste Daroussin 
422d0ef721eSBaptiste Daroussin 		rv = prompt_get(el, p, c, op);
423d0ef721eSBaptiste Daroussin 		break;
424d0ef721eSBaptiste Daroussin 	}
425d0ef721eSBaptiste Daroussin 
426d0ef721eSBaptiste Daroussin 	case EL_EDITOR:
427d0ef721eSBaptiste Daroussin 		rv = map_get_editor(el, va_arg(ap, const wchar_t **));
428d0ef721eSBaptiste Daroussin 		break;
429d0ef721eSBaptiste Daroussin 
430d0ef721eSBaptiste Daroussin 	case EL_SIGNAL:
431d0ef721eSBaptiste Daroussin 		*va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
432d0ef721eSBaptiste Daroussin 		rv = 0;
433d0ef721eSBaptiste Daroussin 		break;
434d0ef721eSBaptiste Daroussin 
435d0ef721eSBaptiste Daroussin 	case EL_EDITMODE:
436d0ef721eSBaptiste Daroussin 		*va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
437d0ef721eSBaptiste Daroussin 		rv = 0;
438d0ef721eSBaptiste Daroussin 		break;
439d0ef721eSBaptiste Daroussin 
44091f76417SBaptiste Daroussin 	case EL_SAFEREAD:
44191f76417SBaptiste Daroussin 		*va_arg(ap, int *) = (el->el_flags & FIXIO);
44291f76417SBaptiste Daroussin 		rv = 0;
44391f76417SBaptiste Daroussin 		break;
44491f76417SBaptiste Daroussin 
445d0ef721eSBaptiste Daroussin 	case EL_TERMINAL:
446d0ef721eSBaptiste Daroussin 		terminal_get(el, va_arg(ap, const char **));
447d0ef721eSBaptiste Daroussin 		rv = 0;
448d0ef721eSBaptiste Daroussin 		break;
449d0ef721eSBaptiste Daroussin 
450d0ef721eSBaptiste Daroussin 	case EL_GETTC:
451d0ef721eSBaptiste Daroussin 	{
452d0ef721eSBaptiste Daroussin 		static char name[] = "gettc";
453d0ef721eSBaptiste Daroussin 		char *argv[3];
454d0ef721eSBaptiste Daroussin 		argv[0] = name;
455d0ef721eSBaptiste Daroussin 		argv[1] = va_arg(ap, char *);
456d0ef721eSBaptiste Daroussin 		argv[2] = va_arg(ap, void *);
457d0ef721eSBaptiste Daroussin 		rv = terminal_gettc(el, 3, argv);
458d0ef721eSBaptiste Daroussin 		break;
459d0ef721eSBaptiste Daroussin 	}
460d0ef721eSBaptiste Daroussin 
461d0ef721eSBaptiste Daroussin 	case EL_GETCFN:
462d0ef721eSBaptiste Daroussin 		*va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read);
463d0ef721eSBaptiste Daroussin 		rv = 0;
464d0ef721eSBaptiste Daroussin 		break;
465d0ef721eSBaptiste Daroussin 
466d0ef721eSBaptiste Daroussin 	case EL_CLIENTDATA:
467d0ef721eSBaptiste Daroussin 		*va_arg(ap, void **) = el->el_data;
468d0ef721eSBaptiste Daroussin 		rv = 0;
469d0ef721eSBaptiste Daroussin 		break;
470d0ef721eSBaptiste Daroussin 
471d0ef721eSBaptiste Daroussin 	case EL_UNBUFFERED:
472d0ef721eSBaptiste Daroussin 		*va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0;
473d0ef721eSBaptiste Daroussin 		rv = 0;
474d0ef721eSBaptiste Daroussin 		break;
475d0ef721eSBaptiste Daroussin 
476d0ef721eSBaptiste Daroussin 	case EL_GETFP:
477d0ef721eSBaptiste Daroussin 	{
478d0ef721eSBaptiste Daroussin 		int what;
479d0ef721eSBaptiste Daroussin 		FILE **fpp;
480d0ef721eSBaptiste Daroussin 
481d0ef721eSBaptiste Daroussin 		what = va_arg(ap, int);
482d0ef721eSBaptiste Daroussin 		fpp = va_arg(ap, FILE **);
483d0ef721eSBaptiste Daroussin 		rv = 0;
484d0ef721eSBaptiste Daroussin 		switch (what) {
485d0ef721eSBaptiste Daroussin 		case 0:
486d0ef721eSBaptiste Daroussin 			*fpp = el->el_infile;
487d0ef721eSBaptiste Daroussin 			break;
488d0ef721eSBaptiste Daroussin 		case 1:
489d0ef721eSBaptiste Daroussin 			*fpp = el->el_outfile;
490d0ef721eSBaptiste Daroussin 			break;
491d0ef721eSBaptiste Daroussin 		case 2:
492d0ef721eSBaptiste Daroussin 			*fpp = el->el_errfile;
493d0ef721eSBaptiste Daroussin 			break;
494d0ef721eSBaptiste Daroussin 		default:
495d0ef721eSBaptiste Daroussin 			rv = -1;
496d0ef721eSBaptiste Daroussin 			break;
497d0ef721eSBaptiste Daroussin 		}
498d0ef721eSBaptiste Daroussin 		break;
499d0ef721eSBaptiste Daroussin 	}
500d0ef721eSBaptiste Daroussin 	default:
501d0ef721eSBaptiste Daroussin 		rv = -1;
502d0ef721eSBaptiste Daroussin 		break;
503d0ef721eSBaptiste Daroussin 	}
504d0ef721eSBaptiste Daroussin 	va_end(ap);
505d0ef721eSBaptiste Daroussin 
506d0ef721eSBaptiste Daroussin 	return rv;
507d0ef721eSBaptiste Daroussin }
508d0ef721eSBaptiste Daroussin 
509d0ef721eSBaptiste Daroussin 
510d0ef721eSBaptiste Daroussin /* el_line():
511d0ef721eSBaptiste Daroussin  *	Return editing info
512d0ef721eSBaptiste Daroussin  */
513d0ef721eSBaptiste Daroussin const LineInfoW *
el_wline(EditLine * el)514d0ef721eSBaptiste Daroussin el_wline(EditLine *el)
515d0ef721eSBaptiste Daroussin {
516d0ef721eSBaptiste Daroussin 
517d0ef721eSBaptiste Daroussin 	return (const LineInfoW *)(void *)&el->el_line;
518d0ef721eSBaptiste Daroussin }
519d0ef721eSBaptiste Daroussin 
520d0ef721eSBaptiste Daroussin 
521d0ef721eSBaptiste Daroussin /* el_source():
522d0ef721eSBaptiste Daroussin  *	Source a file
523d0ef721eSBaptiste Daroussin  */
524d0ef721eSBaptiste Daroussin int
el_source(EditLine * el,const char * fname)525d0ef721eSBaptiste Daroussin el_source(EditLine *el, const char *fname)
526d0ef721eSBaptiste Daroussin {
527d0ef721eSBaptiste Daroussin 	FILE *fp;
528d0ef721eSBaptiste Daroussin 	size_t len;
529d0ef721eSBaptiste Daroussin 	ssize_t slen;
530d0ef721eSBaptiste Daroussin 	char *ptr;
531d0ef721eSBaptiste Daroussin 	char *path = NULL;
532d0ef721eSBaptiste Daroussin 	const wchar_t *dptr;
533d0ef721eSBaptiste Daroussin 	int error = 0;
534d0ef721eSBaptiste Daroussin 
535d0ef721eSBaptiste Daroussin 	fp = NULL;
536d0ef721eSBaptiste Daroussin 	if (fname == NULL) {
537d0ef721eSBaptiste Daroussin #ifdef HAVE_ISSETUGID
538d0ef721eSBaptiste Daroussin 		if (issetugid())
539d0ef721eSBaptiste Daroussin 			return -1;
540d0ef721eSBaptiste Daroussin 
541d0ef721eSBaptiste Daroussin 		if ((fname = getenv("EDITRC")) == NULL) {
542d0ef721eSBaptiste Daroussin 			static const char elpath[] = "/.editrc";
543d0ef721eSBaptiste Daroussin 			size_t plen = sizeof(elpath);
544d0ef721eSBaptiste Daroussin 
545d0ef721eSBaptiste Daroussin 			if ((ptr = getenv("HOME")) == NULL)
546d0ef721eSBaptiste Daroussin 				return -1;
547d0ef721eSBaptiste Daroussin 			plen += strlen(ptr);
548d0ef721eSBaptiste Daroussin 			if ((path = el_calloc(plen, sizeof(*path))) == NULL)
549d0ef721eSBaptiste Daroussin 				return -1;
550d0ef721eSBaptiste Daroussin 			(void)snprintf(path, plen, "%s%s", ptr,
551d0ef721eSBaptiste Daroussin 				elpath + (*ptr == '\0'));
552d0ef721eSBaptiste Daroussin 			fname = path;
553d0ef721eSBaptiste Daroussin 		}
554d0ef721eSBaptiste Daroussin #else
555d0ef721eSBaptiste Daroussin 		/*
556d0ef721eSBaptiste Daroussin 		 * If issetugid() is missing, always return an error, in order
557d0ef721eSBaptiste Daroussin 		 * to keep from inadvertently opening up the user to a security
558d0ef721eSBaptiste Daroussin 		 * hole.
559d0ef721eSBaptiste Daroussin 		 */
560d0ef721eSBaptiste Daroussin 		return -1;
561d0ef721eSBaptiste Daroussin #endif
562d0ef721eSBaptiste Daroussin 	}
563d0ef721eSBaptiste Daroussin 	if (fname[0] == '\0')
564d0ef721eSBaptiste Daroussin 		return -1;
565d0ef721eSBaptiste Daroussin 
566d0ef721eSBaptiste Daroussin 	if (fp == NULL)
567d0ef721eSBaptiste Daroussin 		fp = fopen(fname, "r");
568d0ef721eSBaptiste Daroussin 	if (fp == NULL) {
569d0ef721eSBaptiste Daroussin 		el_free(path);
570d0ef721eSBaptiste Daroussin 		return -1;
571d0ef721eSBaptiste Daroussin 	}
572d0ef721eSBaptiste Daroussin 
573d0ef721eSBaptiste Daroussin 	ptr = NULL;
574d0ef721eSBaptiste Daroussin 	len = 0;
575d0ef721eSBaptiste Daroussin 	while ((slen = getline(&ptr, &len, fp)) != -1) {
576d0ef721eSBaptiste Daroussin 		if (*ptr == '\n')
577d0ef721eSBaptiste Daroussin 			continue;	/* Empty line. */
578d0ef721eSBaptiste Daroussin 		if (slen > 0 && ptr[--slen] == '\n')
579d0ef721eSBaptiste Daroussin 			ptr[slen] = '\0';
580d0ef721eSBaptiste Daroussin 
581d0ef721eSBaptiste Daroussin 		dptr = ct_decode_string(ptr, &el->el_scratch);
582d0ef721eSBaptiste Daroussin 		if (!dptr)
583d0ef721eSBaptiste Daroussin 			continue;
584d0ef721eSBaptiste Daroussin 		/* loop until first non-space char or EOL */
585d0ef721eSBaptiste Daroussin 		while (*dptr != '\0' && iswspace(*dptr))
586d0ef721eSBaptiste Daroussin 			dptr++;
587d0ef721eSBaptiste Daroussin 		if (*dptr == '#')
588d0ef721eSBaptiste Daroussin 			continue;   /* ignore, this is a comment line */
589d0ef721eSBaptiste Daroussin 		if ((error = parse_line(el, dptr)) == -1)
590d0ef721eSBaptiste Daroussin 			break;
591d0ef721eSBaptiste Daroussin 	}
592d0ef721eSBaptiste Daroussin 	free(ptr);
593d0ef721eSBaptiste Daroussin 
594d0ef721eSBaptiste Daroussin 	el_free(path);
595d0ef721eSBaptiste Daroussin 	(void) fclose(fp);
596d0ef721eSBaptiste Daroussin 	return error;
597d0ef721eSBaptiste Daroussin }
598d0ef721eSBaptiste Daroussin 
599d0ef721eSBaptiste Daroussin 
600d0ef721eSBaptiste Daroussin /* el_resize():
601d0ef721eSBaptiste Daroussin  *	Called from program when terminal is resized
602d0ef721eSBaptiste Daroussin  */
603d0ef721eSBaptiste Daroussin void
el_resize(EditLine * el)604d0ef721eSBaptiste Daroussin el_resize(EditLine *el)
605d0ef721eSBaptiste Daroussin {
606d0ef721eSBaptiste Daroussin 	int lins, cols;
607d0ef721eSBaptiste Daroussin 	sigset_t oset, nset;
608d0ef721eSBaptiste Daroussin 
609d0ef721eSBaptiste Daroussin 	(void) sigemptyset(&nset);
610d0ef721eSBaptiste Daroussin 	(void) sigaddset(&nset, SIGWINCH);
611d0ef721eSBaptiste Daroussin 	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
612d0ef721eSBaptiste Daroussin 
613d0ef721eSBaptiste Daroussin 	/* get the correct window size */
614d0ef721eSBaptiste Daroussin 	if (terminal_get_size(el, &lins, &cols))
615d0ef721eSBaptiste Daroussin 		terminal_change_size(el, lins, cols);
616d0ef721eSBaptiste Daroussin 
617d0ef721eSBaptiste Daroussin 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
618d0ef721eSBaptiste Daroussin }
619d0ef721eSBaptiste Daroussin 
620d0ef721eSBaptiste Daroussin 
621d0ef721eSBaptiste Daroussin /* el_beep():
622d0ef721eSBaptiste Daroussin  *	Called from the program to beep
623d0ef721eSBaptiste Daroussin  */
624d0ef721eSBaptiste Daroussin void
el_beep(EditLine * el)625d0ef721eSBaptiste Daroussin el_beep(EditLine *el)
626d0ef721eSBaptiste Daroussin {
627d0ef721eSBaptiste Daroussin 
628d0ef721eSBaptiste Daroussin 	terminal_beep(el);
629d0ef721eSBaptiste Daroussin }
630d0ef721eSBaptiste Daroussin 
631d0ef721eSBaptiste Daroussin 
632d0ef721eSBaptiste Daroussin /* el_editmode()
633d0ef721eSBaptiste Daroussin  *	Set the state of EDIT_DISABLED from the `edit' command.
634d0ef721eSBaptiste Daroussin  */
635d0ef721eSBaptiste Daroussin libedit_private int
636d0ef721eSBaptiste Daroussin /*ARGSUSED*/
el_editmode(EditLine * el,int argc,const wchar_t ** argv)637d0ef721eSBaptiste Daroussin el_editmode(EditLine *el, int argc, const wchar_t **argv)
638d0ef721eSBaptiste Daroussin {
639d0ef721eSBaptiste Daroussin 	const wchar_t *how;
640d0ef721eSBaptiste Daroussin 
641d0ef721eSBaptiste Daroussin 	if (argv == NULL || argc != 2 || argv[1] == NULL)
642d0ef721eSBaptiste Daroussin 		return -1;
643d0ef721eSBaptiste Daroussin 
644d0ef721eSBaptiste Daroussin 	how = argv[1];
645d0ef721eSBaptiste Daroussin 	if (wcscmp(how, L"on") == 0) {
646d0ef721eSBaptiste Daroussin 		el->el_flags &= ~EDIT_DISABLED;
647d0ef721eSBaptiste Daroussin 		tty_rawmode(el);
648d0ef721eSBaptiste Daroussin 	} else if (wcscmp(how, L"off") == 0) {
649d0ef721eSBaptiste Daroussin 		tty_cookedmode(el);
650d0ef721eSBaptiste Daroussin 		el->el_flags |= EDIT_DISABLED;
651d0ef721eSBaptiste Daroussin 	}
652d0ef721eSBaptiste Daroussin 	else {
653d0ef721eSBaptiste Daroussin 		(void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n",
654d0ef721eSBaptiste Daroussin 		    how);
655d0ef721eSBaptiste Daroussin 		return -1;
656d0ef721eSBaptiste Daroussin 	}
657d0ef721eSBaptiste Daroussin 	return 0;
658d0ef721eSBaptiste Daroussin }
659