xref: /dragonfly/contrib/libedit/src/el.c (revision ae19eda8)
1ae19eda8Szrj /*	$NetBSD: el.c,v 1.97 2018/11/18 17:09:39 christos Exp $	*/
232fe07f8SJohn Marino 
332fe07f8SJohn Marino /*-
432fe07f8SJohn Marino  * Copyright (c) 1992, 1993
532fe07f8SJohn Marino  *	The Regents of the University of California.  All rights reserved.
632fe07f8SJohn Marino  *
732fe07f8SJohn Marino  * This code is derived from software contributed to Berkeley by
832fe07f8SJohn Marino  * Christos Zoulas of Cornell University.
932fe07f8SJohn Marino  *
1032fe07f8SJohn Marino  * Redistribution and use in source and binary forms, with or without
1132fe07f8SJohn Marino  * modification, are permitted provided that the following conditions
1232fe07f8SJohn Marino  * are met:
1332fe07f8SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1432fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1532fe07f8SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1632fe07f8SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1732fe07f8SJohn Marino  *    documentation and/or other materials provided with the distribution.
1832fe07f8SJohn Marino  * 3. Neither the name of the University nor the names of its contributors
1932fe07f8SJohn Marino  *    may be used to endorse or promote products derived from this software
2032fe07f8SJohn Marino  *    without specific prior written permission.
2132fe07f8SJohn Marino  *
2232fe07f8SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2332fe07f8SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2432fe07f8SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2532fe07f8SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2632fe07f8SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2732fe07f8SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2832fe07f8SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2932fe07f8SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3032fe07f8SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3132fe07f8SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3232fe07f8SJohn Marino  * SUCH DAMAGE.
3332fe07f8SJohn Marino  */
3432fe07f8SJohn Marino 
3532fe07f8SJohn Marino #include "config.h"
3632fe07f8SJohn Marino #if !defined(lint) && !defined(SCCSID)
3732fe07f8SJohn Marino #if 0
3832fe07f8SJohn Marino static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";
3932fe07f8SJohn Marino #else
40ae19eda8Szrj __RCSID("$NetBSD: el.c,v 1.97 2018/11/18 17:09:39 christos Exp $");
4132fe07f8SJohn Marino #endif
4232fe07f8SJohn Marino #endif /* not lint && not SCCSID */
4332fe07f8SJohn Marino 
4432fe07f8SJohn Marino #ifndef MAXPATHLEN
4532fe07f8SJohn Marino #define MAXPATHLEN 4096
4632fe07f8SJohn Marino #endif
4732fe07f8SJohn Marino 
4832fe07f8SJohn Marino /*
4932fe07f8SJohn Marino  * el.c: EditLine interface functions
5032fe07f8SJohn Marino  */
5132fe07f8SJohn Marino #include <sys/types.h>
5232fe07f8SJohn Marino #include <sys/param.h>
5332fe07f8SJohn Marino #include <ctype.h>
5432fe07f8SJohn Marino #include <langinfo.h>
5512db70c8Szrj #include <locale.h>
5612db70c8Szrj #include <stdarg.h>
5712db70c8Szrj #include <stdlib.h>
5812db70c8Szrj #include <string.h>
5912db70c8Szrj 
6032fe07f8SJohn Marino #include "el.h"
6112db70c8Szrj #include "parse.h"
6212db70c8Szrj #include "read.h"
6332fe07f8SJohn Marino 
6484b940c1SJohn Marino #ifndef HAVE_SECURE_GETENV
6584b940c1SJohn Marino #	ifdef HAVE___SECURE_GETENV
6684b940c1SJohn Marino #		define secure_getenv __secure_getenv
6784b940c1SJohn Marino #		define HAVE_SECURE_GETENV 1
6884b940c1SJohn Marino #	else
6984b940c1SJohn Marino #		ifdef HAVE_ISSETUGID
7084b940c1SJohn Marino #			include <unistd.h>
7184b940c1SJohn Marino #		else
7284b940c1SJohn Marino #			undef issetugid
7384b940c1SJohn Marino #			define issetugid() 1
7484b940c1SJohn Marino #		endif
7584b940c1SJohn Marino #	endif
7684b940c1SJohn Marino #endif
7784b940c1SJohn Marino 
7884b940c1SJohn Marino #ifndef HAVE_SECURE_GETENV
7984b940c1SJohn Marino char *secure_getenv(char const *name)
8084b940c1SJohn Marino {
8184b940c1SJohn Marino 	if (issetugid())
8284b940c1SJohn Marino 		return 0;
8384b940c1SJohn Marino 	return getenv(name);
8484b940c1SJohn Marino }
8584b940c1SJohn Marino #endif
8684b940c1SJohn Marino 
8732fe07f8SJohn Marino /* el_init():
8832fe07f8SJohn Marino  *	Initialize editline and set default parameters.
8932fe07f8SJohn Marino  */
9012db70c8Szrj EditLine *
9132fe07f8SJohn Marino el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
9232fe07f8SJohn Marino {
9384b940c1SJohn Marino     return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout),
9484b940c1SJohn Marino 	fileno(ferr));
9584b940c1SJohn Marino }
9684b940c1SJohn Marino 
97ae19eda8Szrj libedit_private EditLine *
98ae19eda8Szrj el_init_internal(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
99ae19eda8Szrj     int fdin, int fdout, int fderr, int flags)
10084b940c1SJohn Marino {
10132fe07f8SJohn Marino 	EditLine *el = el_malloc(sizeof(*el));
10232fe07f8SJohn Marino 
10332fe07f8SJohn Marino 	if (el == NULL)
10432fe07f8SJohn Marino 		return NULL;
10532fe07f8SJohn Marino 
10632fe07f8SJohn Marino 	memset(el, 0, sizeof(EditLine));
10732fe07f8SJohn Marino 
10832fe07f8SJohn Marino 	el->el_infile = fin;
10932fe07f8SJohn Marino 	el->el_outfile = fout;
11032fe07f8SJohn Marino 	el->el_errfile = ferr;
11132fe07f8SJohn Marino 
11284b940c1SJohn Marino 	el->el_infd = fdin;
11384b940c1SJohn Marino 	el->el_outfd = fdout;
11484b940c1SJohn Marino 	el->el_errfd = fderr;
11532fe07f8SJohn Marino 
11612db70c8Szrj 	el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch));
11732fe07f8SJohn Marino 	if (el->el_prog == NULL) {
11832fe07f8SJohn Marino 		el_free(el);
11932fe07f8SJohn Marino 		return NULL;
12032fe07f8SJohn Marino 	}
12132fe07f8SJohn Marino 
12232fe07f8SJohn Marino 	/*
12332fe07f8SJohn Marino          * Initialize all the modules. Order is important!!!
12432fe07f8SJohn Marino          */
125ae19eda8Szrj 	el->el_flags = flags;
12632fe07f8SJohn Marino 
12732fe07f8SJohn Marino 	if (terminal_init(el) == -1) {
12832fe07f8SJohn Marino 		el_free(el->el_prog);
12932fe07f8SJohn Marino 		el_free(el);
13032fe07f8SJohn Marino 		return NULL;
13132fe07f8SJohn Marino 	}
13232fe07f8SJohn Marino 	(void) keymacro_init(el);
13332fe07f8SJohn Marino 	(void) map_init(el);
13432fe07f8SJohn Marino 	if (tty_init(el) == -1)
13532fe07f8SJohn Marino 		el->el_flags |= NO_TTY;
13632fe07f8SJohn Marino 	(void) ch_init(el);
13732fe07f8SJohn Marino 	(void) search_init(el);
13832fe07f8SJohn Marino 	(void) hist_init(el);
13932fe07f8SJohn Marino 	(void) prompt_init(el);
14032fe07f8SJohn Marino 	(void) sig_init(el);
141ae19eda8Szrj 	(void) literal_init(el);
14212db70c8Szrj 	if (read_init(el) == -1) {
14312db70c8Szrj 		el_end(el);
14412db70c8Szrj 		return NULL;
14512db70c8Szrj 	}
14632fe07f8SJohn Marino 	return el;
14732fe07f8SJohn Marino }
14832fe07f8SJohn Marino 
149ae19eda8Szrj EditLine *
150ae19eda8Szrj el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
151ae19eda8Szrj     int fdin, int fdout, int fderr)
152ae19eda8Szrj {
153ae19eda8Szrj 	return el_init_internal(prog, fin, fout, ferr, fdin, fdout, fderr, 0);
154ae19eda8Szrj }
15532fe07f8SJohn Marino 
15632fe07f8SJohn Marino /* el_end():
15732fe07f8SJohn Marino  *	Clean up.
15832fe07f8SJohn Marino  */
15912db70c8Szrj void
16032fe07f8SJohn Marino el_end(EditLine *el)
16132fe07f8SJohn Marino {
16232fe07f8SJohn Marino 
16332fe07f8SJohn Marino 	if (el == NULL)
16432fe07f8SJohn Marino 		return;
16532fe07f8SJohn Marino 
16632fe07f8SJohn Marino 	el_reset(el);
16732fe07f8SJohn Marino 
16832fe07f8SJohn Marino 	terminal_end(el);
16932fe07f8SJohn Marino 	keymacro_end(el);
17032fe07f8SJohn Marino 	map_end(el);
17112db70c8Szrj 	if (!(el->el_flags & NO_TTY))
172ae19eda8Szrj 		tty_end(el, TCSAFLUSH);
17332fe07f8SJohn Marino 	ch_end(el);
17412db70c8Szrj 	read_end(el->el_read);
17532fe07f8SJohn Marino 	search_end(el);
17632fe07f8SJohn Marino 	hist_end(el);
17732fe07f8SJohn Marino 	prompt_end(el);
17832fe07f8SJohn Marino 	sig_end(el);
179ae19eda8Szrj 	literal_end(el);
18032fe07f8SJohn Marino 
18132fe07f8SJohn Marino 	el_free(el->el_prog);
18212db70c8Szrj 	el_free(el->el_visual.cbuff);
18312db70c8Szrj 	el_free(el->el_visual.wbuff);
18432fe07f8SJohn Marino 	el_free(el->el_scratch.cbuff);
18532fe07f8SJohn Marino 	el_free(el->el_scratch.wbuff);
18632fe07f8SJohn Marino 	el_free(el->el_lgcyconv.cbuff);
18732fe07f8SJohn Marino 	el_free(el->el_lgcyconv.wbuff);
18832fe07f8SJohn Marino 	el_free(el);
18932fe07f8SJohn Marino }
19032fe07f8SJohn Marino 
19132fe07f8SJohn Marino 
19232fe07f8SJohn Marino /* el_reset():
19332fe07f8SJohn Marino  *	Reset the tty and the parser
19432fe07f8SJohn Marino  */
19512db70c8Szrj void
19632fe07f8SJohn Marino el_reset(EditLine *el)
19732fe07f8SJohn Marino {
19832fe07f8SJohn Marino 
19932fe07f8SJohn Marino 	tty_cookedmode(el);
20012db70c8Szrj 	ch_reset(el);		/* XXX: Do we want that? */
20132fe07f8SJohn Marino }
20232fe07f8SJohn Marino 
20332fe07f8SJohn Marino 
20432fe07f8SJohn Marino /* el_set():
20532fe07f8SJohn Marino  *	set the editline parameters
20632fe07f8SJohn Marino  */
20712db70c8Szrj int
20812db70c8Szrj el_wset(EditLine *el, int op, ...)
20932fe07f8SJohn Marino {
21032fe07f8SJohn Marino 	va_list ap;
21132fe07f8SJohn Marino 	int rv = 0;
21232fe07f8SJohn Marino 
21332fe07f8SJohn Marino 	if (el == NULL)
21432fe07f8SJohn Marino 		return -1;
21532fe07f8SJohn Marino 	va_start(ap, op);
21632fe07f8SJohn Marino 
21732fe07f8SJohn Marino 	switch (op) {
21832fe07f8SJohn Marino 	case EL_PROMPT:
21932fe07f8SJohn Marino 	case EL_RPROMPT: {
22032fe07f8SJohn Marino 		el_pfunc_t p = va_arg(ap, el_pfunc_t);
22132fe07f8SJohn Marino 
22232fe07f8SJohn Marino 		rv = prompt_set(el, p, 0, op, 1);
22332fe07f8SJohn Marino 		break;
22432fe07f8SJohn Marino 	}
22532fe07f8SJohn Marino 
22632fe07f8SJohn Marino 	case EL_RESIZE: {
22732fe07f8SJohn Marino 		el_zfunc_t p = va_arg(ap, el_zfunc_t);
22832fe07f8SJohn Marino 		void *arg = va_arg(ap, void *);
22932fe07f8SJohn Marino 		rv = ch_resizefun(el, p, arg);
23032fe07f8SJohn Marino 		break;
23132fe07f8SJohn Marino 	}
23232fe07f8SJohn Marino 
23384b940c1SJohn Marino 	case EL_ALIAS_TEXT: {
23484b940c1SJohn Marino 		el_afunc_t p = va_arg(ap, el_afunc_t);
23584b940c1SJohn Marino 		void *arg = va_arg(ap, void *);
23684b940c1SJohn Marino 		rv = ch_aliasfun(el, p, arg);
23784b940c1SJohn Marino 		break;
23884b940c1SJohn Marino 	}
23984b940c1SJohn Marino 
24032fe07f8SJohn Marino 	case EL_PROMPT_ESC:
24132fe07f8SJohn Marino 	case EL_RPROMPT_ESC: {
24232fe07f8SJohn Marino 		el_pfunc_t p = va_arg(ap, el_pfunc_t);
24332fe07f8SJohn Marino 		int c = va_arg(ap, int);
24432fe07f8SJohn Marino 
24512db70c8Szrj 		rv = prompt_set(el, p, (wchar_t)c, op, 1);
24632fe07f8SJohn Marino 		break;
24732fe07f8SJohn Marino 	}
24832fe07f8SJohn Marino 
24932fe07f8SJohn Marino 	case EL_TERMINAL:
25032fe07f8SJohn Marino 		rv = terminal_set(el, va_arg(ap, char *));
25132fe07f8SJohn Marino 		break;
25232fe07f8SJohn Marino 
25332fe07f8SJohn Marino 	case EL_EDITOR:
25412db70c8Szrj 		rv = map_set_editor(el, va_arg(ap, wchar_t *));
25532fe07f8SJohn Marino 		break;
25632fe07f8SJohn Marino 
25732fe07f8SJohn Marino 	case EL_SIGNAL:
25832fe07f8SJohn Marino 		if (va_arg(ap, int))
25932fe07f8SJohn Marino 			el->el_flags |= HANDLE_SIGNALS;
26032fe07f8SJohn Marino 		else
26132fe07f8SJohn Marino 			el->el_flags &= ~HANDLE_SIGNALS;
26232fe07f8SJohn Marino 		break;
26332fe07f8SJohn Marino 
26432fe07f8SJohn Marino 	case EL_BIND:
26532fe07f8SJohn Marino 	case EL_TELLTC:
26632fe07f8SJohn Marino 	case EL_SETTC:
26732fe07f8SJohn Marino 	case EL_ECHOTC:
26832fe07f8SJohn Marino 	case EL_SETTY:
26932fe07f8SJohn Marino 	{
27012db70c8Szrj 		const wchar_t *argv[20];
27132fe07f8SJohn Marino 		int i;
27232fe07f8SJohn Marino 
27332fe07f8SJohn Marino 		for (i = 1; i < (int)__arraycount(argv); i++)
27412db70c8Szrj 			if ((argv[i] = va_arg(ap, wchar_t *)) == NULL)
27532fe07f8SJohn Marino 				break;
27632fe07f8SJohn Marino 
27732fe07f8SJohn Marino 		switch (op) {
27832fe07f8SJohn Marino 		case EL_BIND:
27912db70c8Szrj 			argv[0] = L"bind";
28032fe07f8SJohn Marino 			rv = map_bind(el, i, argv);
28132fe07f8SJohn Marino 			break;
28232fe07f8SJohn Marino 
28332fe07f8SJohn Marino 		case EL_TELLTC:
28412db70c8Szrj 			argv[0] = L"telltc";
28532fe07f8SJohn Marino 			rv = terminal_telltc(el, i, argv);
28632fe07f8SJohn Marino 			break;
28732fe07f8SJohn Marino 
28832fe07f8SJohn Marino 		case EL_SETTC:
28912db70c8Szrj 			argv[0] = L"settc";
29032fe07f8SJohn Marino 			rv = terminal_settc(el, i, argv);
29132fe07f8SJohn Marino 			break;
29232fe07f8SJohn Marino 
29332fe07f8SJohn Marino 		case EL_ECHOTC:
29412db70c8Szrj 			argv[0] = L"echotc";
29532fe07f8SJohn Marino 			rv = terminal_echotc(el, i, argv);
29632fe07f8SJohn Marino 			break;
29732fe07f8SJohn Marino 
29832fe07f8SJohn Marino 		case EL_SETTY:
29912db70c8Szrj 			argv[0] = L"setty";
30032fe07f8SJohn Marino 			rv = tty_stty(el, i, argv);
30132fe07f8SJohn Marino 			break;
30232fe07f8SJohn Marino 
30332fe07f8SJohn Marino 		default:
30432fe07f8SJohn Marino 			rv = -1;
30532fe07f8SJohn Marino 			EL_ABORT((el->el_errfile, "Bad op %d\n", op));
30632fe07f8SJohn Marino 			break;
30732fe07f8SJohn Marino 		}
30832fe07f8SJohn Marino 		break;
30932fe07f8SJohn Marino 	}
31032fe07f8SJohn Marino 
31132fe07f8SJohn Marino 	case EL_ADDFN:
31232fe07f8SJohn Marino 	{
31312db70c8Szrj 		wchar_t *name = va_arg(ap, wchar_t *);
31412db70c8Szrj 		wchar_t *help = va_arg(ap, wchar_t *);
31532fe07f8SJohn Marino 		el_func_t func = va_arg(ap, el_func_t);
31632fe07f8SJohn Marino 
31732fe07f8SJohn Marino 		rv = map_addfunc(el, name, help, func);
31832fe07f8SJohn Marino 		break;
31932fe07f8SJohn Marino 	}
32032fe07f8SJohn Marino 
32132fe07f8SJohn Marino 	case EL_HIST:
32232fe07f8SJohn Marino 	{
32332fe07f8SJohn Marino 		hist_fun_t func = va_arg(ap, hist_fun_t);
32432fe07f8SJohn Marino 		void *ptr = va_arg(ap, void *);
32532fe07f8SJohn Marino 
32632fe07f8SJohn Marino 		rv = hist_set(el, func, ptr);
327ae19eda8Szrj 		if (MB_CUR_MAX == 1)
32832fe07f8SJohn Marino 			el->el_flags &= ~NARROW_HISTORY;
32932fe07f8SJohn Marino 		break;
33032fe07f8SJohn Marino 	}
33132fe07f8SJohn Marino 
33232fe07f8SJohn Marino 	case EL_EDITMODE:
33332fe07f8SJohn Marino 		if (va_arg(ap, int))
33432fe07f8SJohn Marino 			el->el_flags &= ~EDIT_DISABLED;
33532fe07f8SJohn Marino 		else
33632fe07f8SJohn Marino 			el->el_flags |= EDIT_DISABLED;
33732fe07f8SJohn Marino 		rv = 0;
33832fe07f8SJohn Marino 		break;
33932fe07f8SJohn Marino 
34032fe07f8SJohn Marino 	case EL_GETCFN:
34132fe07f8SJohn Marino 	{
34232fe07f8SJohn Marino 		el_rfunc_t rc = va_arg(ap, el_rfunc_t);
34312db70c8Szrj 		rv = el_read_setfn(el->el_read, rc);
34432fe07f8SJohn Marino 		break;
34532fe07f8SJohn Marino 	}
34632fe07f8SJohn Marino 
34732fe07f8SJohn Marino 	case EL_CLIENTDATA:
34832fe07f8SJohn Marino 		el->el_data = va_arg(ap, void *);
34932fe07f8SJohn Marino 		break;
35032fe07f8SJohn Marino 
35132fe07f8SJohn Marino 	case EL_UNBUFFERED:
35232fe07f8SJohn Marino 		rv = va_arg(ap, int);
35332fe07f8SJohn Marino 		if (rv && !(el->el_flags & UNBUFFERED)) {
35432fe07f8SJohn Marino 			el->el_flags |= UNBUFFERED;
35532fe07f8SJohn Marino 			read_prepare(el);
35632fe07f8SJohn Marino 		} else if (!rv && (el->el_flags & UNBUFFERED)) {
35732fe07f8SJohn Marino 			el->el_flags &= ~UNBUFFERED;
35832fe07f8SJohn Marino 			read_finish(el);
35932fe07f8SJohn Marino 		}
36032fe07f8SJohn Marino 		rv = 0;
36132fe07f8SJohn Marino 		break;
36232fe07f8SJohn Marino 
36332fe07f8SJohn Marino 	case EL_PREP_TERM:
36432fe07f8SJohn Marino 		rv = va_arg(ap, int);
36532fe07f8SJohn Marino 		if (rv)
36632fe07f8SJohn Marino 			(void) tty_rawmode(el);
36732fe07f8SJohn Marino 		else
36832fe07f8SJohn Marino 			(void) tty_cookedmode(el);
36932fe07f8SJohn Marino 		rv = 0;
37032fe07f8SJohn Marino 		break;
37132fe07f8SJohn Marino 
37232fe07f8SJohn Marino 	case EL_SETFP:
37332fe07f8SJohn Marino 	{
37432fe07f8SJohn Marino 		FILE *fp;
37532fe07f8SJohn Marino 		int what;
37632fe07f8SJohn Marino 
37732fe07f8SJohn Marino 		what = va_arg(ap, int);
37832fe07f8SJohn Marino 		fp = va_arg(ap, FILE *);
37932fe07f8SJohn Marino 
38032fe07f8SJohn Marino 		rv = 0;
38132fe07f8SJohn Marino 		switch (what) {
38232fe07f8SJohn Marino 		case 0:
38332fe07f8SJohn Marino 			el->el_infile = fp;
38432fe07f8SJohn Marino 			el->el_infd = fileno(fp);
38532fe07f8SJohn Marino 			break;
38632fe07f8SJohn Marino 		case 1:
38732fe07f8SJohn Marino 			el->el_outfile = fp;
38832fe07f8SJohn Marino 			el->el_outfd = fileno(fp);
38932fe07f8SJohn Marino 			break;
39032fe07f8SJohn Marino 		case 2:
39132fe07f8SJohn Marino 			el->el_errfile = fp;
39232fe07f8SJohn Marino 			el->el_errfd = fileno(fp);
39332fe07f8SJohn Marino 			break;
39432fe07f8SJohn Marino 		default:
39532fe07f8SJohn Marino 			rv = -1;
39632fe07f8SJohn Marino 			break;
39732fe07f8SJohn Marino 		}
39832fe07f8SJohn Marino 		break;
39932fe07f8SJohn Marino 	}
40032fe07f8SJohn Marino 
40132fe07f8SJohn Marino 	case EL_REFRESH:
40232fe07f8SJohn Marino 		re_clear_display(el);
40332fe07f8SJohn Marino 		re_refresh(el);
40432fe07f8SJohn Marino 		terminal__flush(el);
40532fe07f8SJohn Marino 		break;
40632fe07f8SJohn Marino 
40732fe07f8SJohn Marino 	default:
40832fe07f8SJohn Marino 		rv = -1;
40932fe07f8SJohn Marino 		break;
41032fe07f8SJohn Marino 	}
41132fe07f8SJohn Marino 
41232fe07f8SJohn Marino 	va_end(ap);
41332fe07f8SJohn Marino 	return rv;
41432fe07f8SJohn Marino }
41532fe07f8SJohn Marino 
41632fe07f8SJohn Marino 
41732fe07f8SJohn Marino /* el_get():
41832fe07f8SJohn Marino  *	retrieve the editline parameters
41932fe07f8SJohn Marino  */
42012db70c8Szrj int
42112db70c8Szrj el_wget(EditLine *el, int op, ...)
42232fe07f8SJohn Marino {
42332fe07f8SJohn Marino 	va_list ap;
42432fe07f8SJohn Marino 	int rv;
42532fe07f8SJohn Marino 
42632fe07f8SJohn Marino 	if (el == NULL)
42732fe07f8SJohn Marino 		return -1;
42832fe07f8SJohn Marino 
42932fe07f8SJohn Marino 	va_start(ap, op);
43032fe07f8SJohn Marino 
43132fe07f8SJohn Marino 	switch (op) {
43232fe07f8SJohn Marino 	case EL_PROMPT:
43332fe07f8SJohn Marino 	case EL_RPROMPT: {
43432fe07f8SJohn Marino 		el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
43532fe07f8SJohn Marino 		rv = prompt_get(el, p, 0, op);
43632fe07f8SJohn Marino 		break;
43732fe07f8SJohn Marino 	}
43832fe07f8SJohn Marino 	case EL_PROMPT_ESC:
43932fe07f8SJohn Marino 	case EL_RPROMPT_ESC: {
44032fe07f8SJohn Marino 		el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
44112db70c8Szrj 		wchar_t *c = va_arg(ap, wchar_t *);
44232fe07f8SJohn Marino 
44332fe07f8SJohn Marino 		rv = prompt_get(el, p, c, op);
44432fe07f8SJohn Marino 		break;
44532fe07f8SJohn Marino 	}
44632fe07f8SJohn Marino 
44732fe07f8SJohn Marino 	case EL_EDITOR:
44812db70c8Szrj 		rv = map_get_editor(el, va_arg(ap, const wchar_t **));
44932fe07f8SJohn Marino 		break;
45032fe07f8SJohn Marino 
45132fe07f8SJohn Marino 	case EL_SIGNAL:
45232fe07f8SJohn Marino 		*va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
45332fe07f8SJohn Marino 		rv = 0;
45432fe07f8SJohn Marino 		break;
45532fe07f8SJohn Marino 
45632fe07f8SJohn Marino 	case EL_EDITMODE:
45732fe07f8SJohn Marino 		*va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
45832fe07f8SJohn Marino 		rv = 0;
45932fe07f8SJohn Marino 		break;
46032fe07f8SJohn Marino 
46132fe07f8SJohn Marino 	case EL_TERMINAL:
46232fe07f8SJohn Marino 		terminal_get(el, va_arg(ap, const char **));
46332fe07f8SJohn Marino 		rv = 0;
46432fe07f8SJohn Marino 		break;
46532fe07f8SJohn Marino 
46632fe07f8SJohn Marino 	case EL_GETTC:
46732fe07f8SJohn Marino 	{
46832fe07f8SJohn Marino 		static char name[] = "gettc";
46932fe07f8SJohn Marino 		char *argv[20];
47032fe07f8SJohn Marino 		int i;
47132fe07f8SJohn Marino 
47232fe07f8SJohn Marino 		for (i = 1; i < (int)__arraycount(argv); i++)
47332fe07f8SJohn Marino 			if ((argv[i] = va_arg(ap, char *)) == NULL)
47432fe07f8SJohn Marino 				break;
47532fe07f8SJohn Marino 
47632fe07f8SJohn Marino 		argv[0] = name;
47732fe07f8SJohn Marino 		rv = terminal_gettc(el, i, argv);
47832fe07f8SJohn Marino 		break;
47932fe07f8SJohn Marino 	}
48032fe07f8SJohn Marino 
48132fe07f8SJohn Marino 	case EL_GETCFN:
48212db70c8Szrj 		*va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read);
48332fe07f8SJohn Marino 		rv = 0;
48432fe07f8SJohn Marino 		break;
48532fe07f8SJohn Marino 
48632fe07f8SJohn Marino 	case EL_CLIENTDATA:
48732fe07f8SJohn Marino 		*va_arg(ap, void **) = el->el_data;
48832fe07f8SJohn Marino 		rv = 0;
48932fe07f8SJohn Marino 		break;
49032fe07f8SJohn Marino 
49132fe07f8SJohn Marino 	case EL_UNBUFFERED:
492c8e4d2bfSJohn Marino 		*va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0;
49332fe07f8SJohn Marino 		rv = 0;
49432fe07f8SJohn Marino 		break;
49532fe07f8SJohn Marino 
49632fe07f8SJohn Marino 	case EL_GETFP:
49732fe07f8SJohn Marino 	{
49832fe07f8SJohn Marino 		int what;
49932fe07f8SJohn Marino 		FILE **fpp;
50032fe07f8SJohn Marino 
50132fe07f8SJohn Marino 		what = va_arg(ap, int);
50232fe07f8SJohn Marino 		fpp = va_arg(ap, FILE **);
50332fe07f8SJohn Marino 		rv = 0;
50432fe07f8SJohn Marino 		switch (what) {
50532fe07f8SJohn Marino 		case 0:
50632fe07f8SJohn Marino 			*fpp = el->el_infile;
50732fe07f8SJohn Marino 			break;
50832fe07f8SJohn Marino 		case 1:
50932fe07f8SJohn Marino 			*fpp = el->el_outfile;
51032fe07f8SJohn Marino 			break;
51132fe07f8SJohn Marino 		case 2:
51232fe07f8SJohn Marino 			*fpp = el->el_errfile;
51332fe07f8SJohn Marino 			break;
51432fe07f8SJohn Marino 		default:
51532fe07f8SJohn Marino 			rv = -1;
51632fe07f8SJohn Marino 			break;
51732fe07f8SJohn Marino 		}
51832fe07f8SJohn Marino 		break;
51932fe07f8SJohn Marino 	}
52032fe07f8SJohn Marino 	default:
52132fe07f8SJohn Marino 		rv = -1;
52232fe07f8SJohn Marino 		break;
52332fe07f8SJohn Marino 	}
52432fe07f8SJohn Marino 	va_end(ap);
52532fe07f8SJohn Marino 
52632fe07f8SJohn Marino 	return rv;
52732fe07f8SJohn Marino }
52832fe07f8SJohn Marino 
52932fe07f8SJohn Marino 
53032fe07f8SJohn Marino /* el_line():
53132fe07f8SJohn Marino  *	Return editing info
53232fe07f8SJohn Marino  */
53312db70c8Szrj const LineInfoW *
53412db70c8Szrj el_wline(EditLine *el)
53532fe07f8SJohn Marino {
53632fe07f8SJohn Marino 
53712db70c8Szrj 	return (const LineInfoW *)(void *)&el->el_line;
53832fe07f8SJohn Marino }
53932fe07f8SJohn Marino 
54032fe07f8SJohn Marino 
54132fe07f8SJohn Marino /* el_source():
54232fe07f8SJohn Marino  *	Source a file
54332fe07f8SJohn Marino  */
54412db70c8Szrj int
54532fe07f8SJohn Marino el_source(EditLine *el, const char *fname)
54632fe07f8SJohn Marino {
54732fe07f8SJohn Marino 	FILE *fp;
54832fe07f8SJohn Marino 	size_t len;
54912db70c8Szrj 	ssize_t slen;
55032fe07f8SJohn Marino 	char *ptr;
55132fe07f8SJohn Marino 	char *path = NULL;
55212db70c8Szrj 	const wchar_t *dptr;
55332fe07f8SJohn Marino 	int error = 0;
55432fe07f8SJohn Marino 
55532fe07f8SJohn Marino 	fp = NULL;
55632fe07f8SJohn Marino 	if (fname == NULL) {
557ae19eda8Szrj #ifdef HAVE_ISSETUGID
558ae19eda8Szrj 		if (issetugid())
559ae19eda8Szrj 			return -1;
560ae19eda8Szrj 
561ae19eda8Szrj 		if ((fname = getenv("EDITRC")) == NULL) {
56232fe07f8SJohn Marino 			static const char elpath[] = "/.editrc";
56332fe07f8SJohn Marino 			size_t plen = sizeof(elpath);
56432fe07f8SJohn Marino 
565ae19eda8Szrj 			if ((ptr = getenv("HOME")) == NULL)
56632fe07f8SJohn Marino 				return -1;
56732fe07f8SJohn Marino 			plen += strlen(ptr);
56832fe07f8SJohn Marino 			if ((path = el_malloc(plen * sizeof(*path))) == NULL)
56932fe07f8SJohn Marino 				return -1;
570ae19eda8Szrj 			(void)snprintf(path, plen, "%s%s", ptr,
571ae19eda8Szrj 				elpath + (*ptr == '\0'));
57232fe07f8SJohn Marino 			fname = path;
57332fe07f8SJohn Marino 		}
574ae19eda8Szrj #else
575ae19eda8Szrj 		/*
576ae19eda8Szrj 		 * If issetugid() is missing, always return an error, in order
577ae19eda8Szrj 		 * to keep from inadvertently opening up the user to a security
578ae19eda8Szrj 		 * hole.
579ae19eda8Szrj 		 */
580ae19eda8Szrj 		return -1;
581ae19eda8Szrj #endif
582ae19eda8Szrj 	}
583ae19eda8Szrj 	if (fname[0] == '\0')
584ae19eda8Szrj 		return -1;
585ae19eda8Szrj 
58632fe07f8SJohn Marino 	if (fp == NULL)
58732fe07f8SJohn Marino 		fp = fopen(fname, "r");
58832fe07f8SJohn Marino 	if (fp == NULL) {
58932fe07f8SJohn Marino 		el_free(path);
59032fe07f8SJohn Marino 		return -1;
59132fe07f8SJohn Marino 	}
59232fe07f8SJohn Marino 
59312db70c8Szrj 	ptr = NULL;
59412db70c8Szrj 	len = 0;
59512db70c8Szrj 	while ((slen = getline(&ptr, &len, fp)) != -1) {
59632fe07f8SJohn Marino 		if (*ptr == '\n')
59732fe07f8SJohn Marino 			continue;	/* Empty line. */
59812db70c8Szrj 		if (slen > 0 && ptr[--slen] == '\n')
59912db70c8Szrj 			ptr[slen] = '\0';
60012db70c8Szrj 
60132fe07f8SJohn Marino 		dptr = ct_decode_string(ptr, &el->el_scratch);
60232fe07f8SJohn Marino 		if (!dptr)
60332fe07f8SJohn Marino 			continue;
60432fe07f8SJohn Marino 		/* loop until first non-space char or EOL */
60512db70c8Szrj 		while (*dptr != '\0' && iswspace(*dptr))
60632fe07f8SJohn Marino 			dptr++;
60732fe07f8SJohn Marino 		if (*dptr == '#')
60832fe07f8SJohn Marino 			continue;   /* ignore, this is a comment line */
60932fe07f8SJohn Marino 		if ((error = parse_line(el, dptr)) == -1)
61032fe07f8SJohn Marino 			break;
61132fe07f8SJohn Marino 	}
61212db70c8Szrj 	free(ptr);
61332fe07f8SJohn Marino 
61432fe07f8SJohn Marino 	el_free(path);
61532fe07f8SJohn Marino 	(void) fclose(fp);
61632fe07f8SJohn Marino 	return error;
61732fe07f8SJohn Marino }
61832fe07f8SJohn Marino 
61932fe07f8SJohn Marino 
62032fe07f8SJohn Marino /* el_resize():
62132fe07f8SJohn Marino  *	Called from program when terminal is resized
62232fe07f8SJohn Marino  */
62312db70c8Szrj void
62432fe07f8SJohn Marino el_resize(EditLine *el)
62532fe07f8SJohn Marino {
62632fe07f8SJohn Marino 	int lins, cols;
62732fe07f8SJohn Marino 	sigset_t oset, nset;
62832fe07f8SJohn Marino 
62932fe07f8SJohn Marino 	(void) sigemptyset(&nset);
63032fe07f8SJohn Marino 	(void) sigaddset(&nset, SIGWINCH);
63132fe07f8SJohn Marino 	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
63232fe07f8SJohn Marino 
63332fe07f8SJohn Marino 	/* get the correct window size */
63432fe07f8SJohn Marino 	if (terminal_get_size(el, &lins, &cols))
63532fe07f8SJohn Marino 		terminal_change_size(el, lins, cols);
63632fe07f8SJohn Marino 
63732fe07f8SJohn Marino 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
63832fe07f8SJohn Marino }
63932fe07f8SJohn Marino 
64032fe07f8SJohn Marino 
64132fe07f8SJohn Marino /* el_beep():
64232fe07f8SJohn Marino  *	Called from the program to beep
64332fe07f8SJohn Marino  */
64412db70c8Szrj void
64532fe07f8SJohn Marino el_beep(EditLine *el)
64632fe07f8SJohn Marino {
64732fe07f8SJohn Marino 
64832fe07f8SJohn Marino 	terminal_beep(el);
64932fe07f8SJohn Marino }
65032fe07f8SJohn Marino 
65132fe07f8SJohn Marino 
65232fe07f8SJohn Marino /* el_editmode()
65332fe07f8SJohn Marino  *	Set the state of EDIT_DISABLED from the `edit' command.
65432fe07f8SJohn Marino  */
65512db70c8Szrj libedit_private int
65632fe07f8SJohn Marino /*ARGSUSED*/
65712db70c8Szrj el_editmode(EditLine *el, int argc, const wchar_t **argv)
65832fe07f8SJohn Marino {
65912db70c8Szrj 	const wchar_t *how;
66032fe07f8SJohn Marino 
66132fe07f8SJohn Marino 	if (argv == NULL || argc != 2 || argv[1] == NULL)
66232fe07f8SJohn Marino 		return -1;
66332fe07f8SJohn Marino 
66432fe07f8SJohn Marino 	how = argv[1];
66512db70c8Szrj 	if (wcscmp(how, L"on") == 0) {
66632fe07f8SJohn Marino 		el->el_flags &= ~EDIT_DISABLED;
66732fe07f8SJohn Marino 		tty_rawmode(el);
66812db70c8Szrj 	} else if (wcscmp(how, L"off") == 0) {
66932fe07f8SJohn Marino 		tty_cookedmode(el);
67032fe07f8SJohn Marino 		el->el_flags |= EDIT_DISABLED;
67132fe07f8SJohn Marino 	}
67232fe07f8SJohn Marino 	else {
67312db70c8Szrj 		(void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n",
67432fe07f8SJohn Marino 		    how);
67532fe07f8SJohn Marino 		return -1;
67632fe07f8SJohn Marino 	}
67732fe07f8SJohn Marino 	return 0;
67832fe07f8SJohn Marino }
679