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