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