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