Initial import from FreeBSD RELENG_4:
[games.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
37 #if !defined(lint) && !defined(SCCSID)
38 #if 0
39 static char sccsid[] = "@(#)el.c        8.2 (Berkeley) 1/3/94";
40 #endif
41 static const char rcsid[] =
42   "$FreeBSD: src/lib/libedit/el.c,v 1.6.2.1 2000/05/22 06:07:00 imp Exp $";
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  */
65 public EditLine *
66 el_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  */
119 public void
120 el_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  */
146 public void
147 el_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  */
158 public int
159 #if __STDC__
160 el_set(EditLine *el, int op, ...)
161 #else
162 el_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  */
275 public const LineInfo *
276 el_line(el)
277     EditLine *el;
278 {
279     return (const LineInfo *) &el->el_line;
280 }
281
282 static const char elpath[] = "/.editrc";
283
284 /* el_source():
285  *      Source a file
286  */
287 public int
288 el_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  */
325 public void
326 el_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
342 public void
343 el_data_set (el, data)
344     EditLine *el;
345     void *data;
346 {
347     el->data = data;
348
349     return;
350 }
351
352 public void *
353 el_data_get (el)
354     EditLine *el;
355 {
356     if (el->data)
357         return (el->data);
358     return (NULL);
359 }