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