xref: /netbsd-src/lib/libedit/el.c (revision d0fed6c87ddc40a8bffa6f99e7433ddfc864dd83)
1 /*	$NetBSD: el.c,v 1.6 1997/04/24 18:54:16 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 #if !defined(lint) && !defined(SCCSID)
40 #if 0
41 static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";
42 #else
43 static char rcsid[] = "$NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $";
44 #endif
45 #endif /* not lint && not SCCSID */
46 
47 /*
48  * el.c: EditLine interface functions
49  */
50 #include "sys.h"
51 
52 #include <sys/types.h>
53 #include <sys/param.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #ifdef __STDC__
57 # include <stdarg.h>
58 #else
59 # include <varargs.h>
60 #endif
61 #include "el.h"
62 
63 /* el_init():
64  *	Initialize editline and set default parameters.
65  */
66 public EditLine *
67 el_init(prog, fin, fout)
68     const char *prog;
69     FILE *fin, *fout;
70 {
71     EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
72 #ifdef DEBUG
73     char *tty;
74 #endif
75 
76     if (el == NULL)
77 	return NULL;
78 
79     memset(el, 0, sizeof(EditLine));
80 
81     el->el_infd  = fileno(fin);
82     el->el_outfile = fout;
83     el->el_prog = strdup(prog);
84 
85 #ifdef DEBUG
86     if ((tty = getenv("DEBUGTTY")) != NULL) {
87 	el->el_errfile = fopen(tty, "w");
88 	if (el->el_errfile == NULL) {
89 		extern errno;
90 		(void) fprintf(stderr, "Cannot open %s (%s).\n",
91 			       tty, strerror(errno));
92 		return NULL;
93 	}
94     }
95     else
96 #endif
97 	el->el_errfile = stderr;
98 
99     /*
100      * Initialize all the modules. Order is important!!!
101      */
102     (void) term_init(el);
103     (void) tty_init(el);
104     (void) key_init(el);
105     (void) map_init(el);
106     (void) ch_init(el);
107     (void) search_init(el);
108     (void) hist_init(el);
109     (void) prompt_init(el);
110     (void) sig_init(el);
111     el->el_flags = 0;
112 
113     return el;
114 } /* end el_init */
115 
116 
117 /* el_end():
118  *	Clean up.
119  */
120 public void
121 el_end(el)
122     EditLine *el;
123 {
124     if (el == NULL)
125 	return;
126 
127     el_reset(el);
128 
129     term_end(el);
130     tty_end(el);
131     key_end(el);
132     map_end(el);
133     ch_end(el);
134     search_end(el);
135     hist_end(el);
136     prompt_end(el);
137     sig_end(el);
138 
139     el_free((ptr_t) el->el_prog);
140     el_free((ptr_t) el);
141 } /* end el_end */
142 
143 
144 /* el_reset():
145  *	Reset the tty and the parser
146  */
147 public void
148 el_reset(el)
149     EditLine *el;
150 {
151     tty_cookedmode(el);
152     ch_reset(el);	/* XXX: Do we want that? */
153 }
154 
155 
156 /* el_set():
157  *	set the editline parameters
158  */
159 public int
160 #ifdef __STDC__
161 el_set(EditLine *el, int op, ...)
162 #else
163 el_set(va_alist)
164     va_dcl
165 #endif
166 {
167     va_list va;
168     int rv;
169 #ifdef __STDC__
170     va_start(va, op);
171 #else
172     EditLine *el;
173     int op;
174 
175     va_start(va);
176     el = va_arg(va, EditLine *);
177     op = va_arg(va, int);
178 #endif
179 
180     switch (op) {
181     case EL_PROMPT:
182 	rv = prompt_set(el, va_arg(va, el_pfunc_t));
183 	break;
184 
185     case EL_TERMINAL:
186 	rv = term_set(el, va_arg(va, char *));
187 	break;
188 
189     case EL_EDITOR:
190 	rv = map_set_editor(el, va_arg(va, char *));
191 	break;
192 
193     case EL_SIGNAL:
194 	if (va_arg(va, int))
195 	    el->el_flags |= HANDLE_SIGNALS;
196 	else
197 	    el->el_flags &= ~HANDLE_SIGNALS;
198 	rv = 0;
199 	break;
200 
201     case EL_BIND:
202     case EL_TELLTC:
203     case EL_SETTC:
204     case EL_ECHOTC:
205     case EL_SETTY:
206 	{
207 	    char *argv[20];
208 	    int i;
209 	    for (i = 1; i < 20; i++)
210 		if ((argv[i] = va_arg(va, char *)) == NULL)
211 		     break;
212 
213 	    switch (op) {
214 	    case EL_BIND:
215 		argv[0] = "bind";
216 		rv = map_bind(el, i, argv);
217 		break;
218 
219 	    case EL_TELLTC:
220 		argv[0] = "telltc";
221 		rv = term_telltc(el, i, argv);
222 		break;
223 
224 	    case EL_SETTC:
225 		argv[0] = "settc";
226 		rv = term_settc(el, i, argv);
227 		break;
228 
229 	    case EL_ECHOTC:
230 		argv[0] = "echotc";
231 		rv = term_echotc(el, i, argv);
232 		break;
233 
234 	    case EL_SETTY:
235 		argv[0] = "setty";
236 		rv = tty_stty(el, i, argv);
237 		break;
238 
239 	    default:
240 		rv = -1;
241 		abort();
242 		break;
243 	    }
244 	}
245 	break;
246 
247     case EL_ADDFN:
248 	{
249 	    char 	*name = va_arg(va, char *);
250 	    char 	*help = va_arg(va, char *);
251 	    el_func_t    func = va_arg(va, el_func_t);
252 	    rv = map_addfunc(el, name, help, func);
253 	}
254 	break;
255 
256     case EL_HIST:
257 	{
258 	    hist_fun_t func = va_arg(va, hist_fun_t);
259 	    ptr_t      ptr = va_arg(va, char *);
260 	    rv = hist_set(el, func, ptr);
261 	}
262 	break;
263 
264     default:
265 	rv = -1;
266     }
267 
268     va_end(va);
269     return rv;
270 } /* end el_set */
271 
272 
273 /* el_line():
274  *	Return editing info
275  */
276 public const LineInfo *
277 el_line(el)
278     EditLine *el;
279 {
280     return (const LineInfo *) &el->el_line;
281 }
282 
283 static const char elpath[] = "/.editrc";
284 
285 /* el_source():
286  *	Source a file
287  */
288 public int
289 el_source(el, fname)
290     EditLine *el;
291     const char *fname;
292 {
293     FILE *fp;
294     size_t len;
295     char *ptr, path[MAXPATHLEN];
296 
297     if (fname == NULL) {
298 	fname = &elpath[1];
299 	if ((fp = fopen(fname, "r")) == NULL) {
300 	    if ((ptr = getenv("HOME")) == NULL)
301 		return -1;
302 	    (void)snprintf(path, sizeof(path), "%s%s", ptr, elpath);
303 	    fname = path;
304 	}
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