xref: /openbsd-src/lib/libedit/el.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: el.c,v 1.8 2001/04/13 20:35:19 millert Exp $	*/
2 /*	$NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $	*/
3 
4 /*-
5  * Copyright (c) 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Christos Zoulas of Cornell University.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  */
39 
40 #if !defined(lint) && !defined(SCCSID)
41 #if 0
42 static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";
43 #else
44 static char rcsid[] = "$OpenBSD: el.c,v 1.8 2001/04/13 20:35:19 millert Exp $";
45 #endif
46 #endif /* not lint && not SCCSID */
47 
48 /*
49  * el.c: EditLine interface functions
50  */
51 #include "sys.h"
52 
53 #include <sys/types.h>
54 #include <sys/param.h>
55 #include <string.h>
56 #include <stdlib.h>
57 #ifdef __STDC__
58 # include <stdarg.h>
59 #else
60 # include <varargs.h>
61 #endif
62 #include <unistd.h>
63 #include "el.h"
64 
65 /* el_init():
66  *	Initialize editline and set default parameters.
67  */
68 public EditLine *
69 el_init(prog, fin, fout)
70     const char *prog;
71     FILE *fin, *fout;
72 {
73     EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
74 #ifdef DEBUG
75     char *tty;
76 #endif
77 
78     if (el == NULL)
79 	return NULL;
80 
81     memset(el, 0, sizeof(EditLine));
82 
83     el->el_infd  = fileno(fin);
84     el->el_outfile = fout;
85     el->el_prog = strdup(prog);
86 
87 #ifdef DEBUG
88     if (issetugid() == 0 && (tty = getenv("DEBUGTTY")) != NULL) {
89 	el->el_errfile = fopen(tty, "w");
90 	if (el->el_errfile == NULL) {
91 		extern errno;
92 		(void)fprintf(stderr, "Cannot open %s (%s).\n",
93 			       tty, strerror(errno));
94 		return NULL;
95 	}
96     }
97     else
98 #endif
99 	el->el_errfile = stderr;
100 
101     /*
102      * Initialize all the modules. Order is important!!!
103      */
104     (void)term_init(el);
105     (void)tty_init(el);
106     (void)key_init(el);
107     (void)map_init(el);
108     (void)ch_init(el);
109     (void)search_init(el);
110     (void)hist_init(el);
111     (void)prompt_init(el);
112     (void)sig_init(el);
113     el->el_flags = 0;
114 
115     return el;
116 } /* end el_init */
117 
118 
119 /* el_end():
120  *	Clean up.
121  */
122 public void
123 el_end(el)
124     EditLine *el;
125 {
126     if (el == NULL)
127 	return;
128 
129     el_reset(el);
130 
131     term_end(el);
132     tty_end(el);
133     key_end(el);
134     map_end(el);
135     ch_end(el);
136     search_end(el);
137     hist_end(el);
138     prompt_end(el);
139     sig_end(el);
140 
141     el_free((ptr_t) el->el_prog);
142     el_free((ptr_t) el);
143 } /* end el_end */
144 
145 
146 /* el_reset():
147  *	Reset the tty and the parser
148  */
149 public void
150 el_reset(el)
151     EditLine *el;
152 {
153     tty_cookedmode(el);
154     ch_reset(el);	/* XXX: Do we want that? */
155 }
156 
157 
158 /* el_set():
159  *	set the editline parameters
160  */
161 public int
162 #ifdef __STDC__
163 el_set(EditLine *el, int op, ...)
164 #else
165 el_set(va_alist)
166     va_dcl
167 #endif
168 {
169     va_list va;
170     int rv;
171 #ifdef __STDC__
172     va_start(va, op);
173 #else
174     EditLine *el;
175     int op;
176 
177     va_start(va);
178     el = va_arg(va, EditLine *);
179     op = va_arg(va, int);
180 #endif
181 
182     switch (op) {
183     case EL_PROMPT:
184 	rv = prompt_set(el, va_arg(va, el_pfunc_t));
185 	break;
186 
187     case EL_TERMINAL:
188 	rv = term_set(el, va_arg(va, char *));
189 	break;
190 
191     case EL_EDITOR:
192 	rv = map_set_editor(el, va_arg(va, char *));
193 	break;
194 
195     case EL_SIGNAL:
196 	if (va_arg(va, int))
197 	    el->el_flags |= HANDLE_SIGNALS;
198 	else
199 	    el->el_flags &= ~HANDLE_SIGNALS;
200 	rv = 0;
201 	break;
202 
203     case EL_BIND:
204     case EL_TELLTC:
205     case EL_SETTC:
206     case EL_ECHOTC:
207     case EL_SETTY:
208 	{
209 	    char *argv[20];
210 	    int i;
211 	    for (i = 1; i < 20; i++)
212 		if ((argv[i] = va_arg(va, char *)) == NULL)
213 		     break;
214 
215 	    switch (op) {
216 	    case EL_BIND:
217 		argv[0] = "bind";
218 		rv = map_bind(el, i, argv);
219 		break;
220 
221 	    case EL_TELLTC:
222 		argv[0] = "telltc";
223 		rv = term_telltc(el, i, argv);
224 		break;
225 
226 	    case EL_SETTC:
227 		argv[0] = "settc";
228 		rv = term_settc(el, i, argv);
229 		break;
230 
231 	    case EL_ECHOTC:
232 		argv[0] = "echotc";
233 		rv = term_echotc(el, i, argv);
234 		break;
235 
236 	    case EL_SETTY:
237 		argv[0] = "setty";
238 		rv = tty_stty(el, i, argv);
239 		break;
240 
241 	    default:
242 		rv = -1;
243 		abort();
244 		break;
245 	    }
246 	}
247 	break;
248 
249     case EL_ADDFN:
250 	{
251 	    char 	*name = va_arg(va, char *);
252 	    char 	*help = va_arg(va, char *);
253 	    el_func_t    func = va_arg(va, el_func_t);
254 	    rv = map_addfunc(el, name, help, func);
255 	}
256 	break;
257 
258     case EL_HIST:
259 	{
260 	    hist_fun_t func = va_arg(va, hist_fun_t);
261 	    ptr_t      ptr = va_arg(va, char *);
262 	    rv = hist_set(el, func, ptr);
263 	}
264 	break;
265 
266     default:
267 	rv = -1;
268     }
269 
270     va_end(va);
271     return rv;
272 } /* end el_set */
273 
274 
275 /* el_line():
276  *	Return editing info
277  */
278 public const LineInfo *
279 el_line(el)
280     EditLine *el;
281 {
282     return (const LineInfo *) &el->el_line;
283 }
284 
285 static const char elpath[] = "/.editrc";
286 
287 /* el_source():
288  *	Source a file
289  */
290 public int
291 el_source(el, fname)
292     EditLine *el;
293     const char *fname;
294 {
295     FILE *fp;
296     size_t len;
297     char *ptr, path[MAXPATHLEN];
298 
299     if (fname == NULL) {
300         ptr = getenv("HOME");
301         if (issetugid() != 0 || ptr == NULL || *ptr == '\0')
302 	        return -1;
303         (void) snprintf(path, sizeof(path), "%s%s", ptr, elpath);
304         fname = path;
305     }
306 
307     if ((fp = fopen(fname, "r")) == NULL)
308 	return -1;
309 
310     while ((ptr = fgetln(fp, &len)) != NULL) {
311 	if (ptr[len - 1] == '\n')
312 		--len;
313 	ptr[len] = '\0';
314 	if (parse_line(el, ptr) == -1) {
315 	    (void)fclose(fp);
316 	    return -1;
317 	}
318     }
319 
320     (void)fclose(fp);
321     return 0;
322 }
323 
324 
325 /* el_resize():
326  *	Called from program when terminal is resized
327  */
328 public void
329 el_resize(el)
330     EditLine *el;
331 {
332     int lins, cols;
333     sigset_t oset, nset;
334     (void)sigemptyset(&nset);
335     (void)sigaddset(&nset, SIGWINCH);
336     (void)sigprocmask(SIG_BLOCK, &nset, &oset);
337 
338     /* get the correct window size */
339     if (term_get_size(el, &lins, &cols))
340 	term_change_size(el, lins, cols);
341 
342     (void)sigprocmask(SIG_SETMASK, &oset, NULL);
343 }
344