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