xref: /netbsd-src/lib/libedit/el.c (revision c41a4eebefede43f6950f838a387dc18c6a431bf)
1 /*	$NetBSD: el.c,v 1.8 1997/12/20 19:15:50 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell University.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 #if !defined(lint) && !defined(SCCSID)
41 #if 0
42 static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";
43 #else
44 __RCSID("$NetBSD: el.c,v 1.8 1997/12/20 19:15:50 christos 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 "el.h"
63 
64 /* el_init():
65  *	Initialize editline and set default parameters.
66  */
67 public EditLine *
68 el_init(prog, fin, fout)
69     const char *prog;
70     FILE *fin, *fout;
71 {
72     EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
73 #ifdef DEBUG
74     char *tty;
75 #endif
76 
77     if (el == NULL)
78 	return NULL;
79 
80     memset(el, 0, sizeof(EditLine));
81 
82     el->el_infd  = fileno(fin);
83     el->el_outfile = fout;
84     el->el_prog = strdup(prog);
85 
86 #ifdef DEBUG
87     if ((tty = getenv("DEBUGTTY")) != NULL) {
88 	el->el_errfile = fopen(tty, "w");
89 	if (el->el_errfile == NULL) {
90 		extern errno;
91 		(void) fprintf(stderr, "Cannot open %s (%s).\n",
92 			       tty, strerror(errno));
93 		return NULL;
94 	}
95     }
96     else
97 #endif
98 	el->el_errfile = stderr;
99 
100     /*
101      * Initialize all the modules. Order is important!!!
102      */
103     el->el_flags = 0;
104     (void) term_init(el);
105     if (tty_init(el) == -1)
106 	el->el_flags |= NO_TTY;
107     (void) key_init(el);
108     (void) map_init(el);
109     (void) ch_init(el);
110     (void) search_init(el);
111     (void) hist_init(el);
112     (void) prompt_init(el);
113     (void) sig_init(el);
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 	fname = &elpath[1];
301 	if ((fp = fopen(fname, "r")) == NULL) {
302 	    if ((ptr = getenv("HOME")) == NULL)
303 		return -1;
304 	    (void)snprintf(path, sizeof(path), "%s%s", ptr, elpath);
305 	    fname = path;
306 	}
307     }
308 
309     if ((fp = fopen(fname, "r")) == NULL)
310 	return -1;
311 
312     while ((ptr = fgetln(fp, &len)) != NULL) {
313 	if (ptr[len - 1] == '\n')
314 	    --len;
315 	ptr[len] = '\0';
316 	if (parse_line(el, ptr) == -1) {
317 	    (void) fclose(fp);
318 	    return -1;
319 	}
320     }
321 
322     (void) fclose(fp);
323     return 0;
324 }
325 
326 
327 /* el_resize():
328  *	Called from program when terminal is resized
329  */
330 public void
331 el_resize(el)
332     EditLine *el;
333 {
334     int lins, cols;
335     sigset_t oset, nset;
336     (void) sigemptyset(&nset);
337     (void) sigaddset(&nset, SIGWINCH);
338     (void) sigprocmask(SIG_BLOCK, &nset, &oset);
339 
340     /* get the correct window size */
341     if (term_get_size(el, &lins, &cols))
342 	term_change_size(el, lins, cols);
343 
344     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
345 }
346