el.c revision 1.23 1 /* $NetBSD: el.c,v 1.23 2001/09/27 19:29:50 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #if !defined(lint) && !defined(SCCSID)
41 #if 0
42 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
43 #else
44 __RCSID("$NetBSD: el.c,v 1.23 2001/09/27 19:29:50 christos Exp $");
45 #endif
46 #endif /* not lint && not SCCSID */
47
48 /*
49 * el.c: EditLine interface functions
50 */
51 #include "sys.h"
52
53 #include <sys/types.h>
54 #include <sys/param.h>
55 #include <string.h>
56 #include <stdlib.h>
57 #include <stdarg.h>
58 #include "el.h"
59
60 /* el_init():
61 * Initialize editline and set default parameters.
62 */
63 public EditLine *
64 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
65 {
66
67 EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
68 #ifdef DEBUG
69 char *tty;
70 #endif
71
72 if (el == NULL)
73 return (NULL);
74
75 memset(el, 0, sizeof(EditLine));
76
77 el->el_infd = fileno(fin);
78 el->el_outfile = fout;
79 el->el_errfile = ferr;
80 el->el_prog = strdup(prog);
81
82 /*
83 * Initialize all the modules. Order is important!!!
84 */
85 el->el_flags = 0;
86
87 (void) term_init(el);
88 (void) key_init(el);
89 (void) map_init(el);
90 if (tty_init(el) == -1)
91 el->el_flags |= NO_TTY;
92 (void) ch_init(el);
93 (void) search_init(el);
94 (void) hist_init(el);
95 (void) prompt_init(el);
96 (void) sig_init(el);
97 (void) read_init(el);
98
99 return (el);
100 }
101
102
103 /* el_end():
104 * Clean up.
105 */
106 public void
107 el_end(EditLine *el)
108 {
109
110 if (el == NULL)
111 return;
112
113 el_reset(el);
114
115 term_end(el);
116 key_end(el);
117 map_end(el);
118 tty_end(el);
119 ch_end(el);
120 search_end(el);
121 hist_end(el);
122 prompt_end(el);
123 sig_end(el);
124
125 el_free((ptr_t) el->el_prog);
126 el_free((ptr_t) el);
127 }
128
129
130 /* el_reset():
131 * Reset the tty and the parser
132 */
133 public void
134 el_reset(EditLine *el)
135 {
136
137 tty_cookedmode(el);
138 ch_reset(el); /* XXX: Do we want that? */
139 }
140
141
142 /* el_set():
143 * set the editline parameters
144 */
145 public int
146 el_set(EditLine *el, int op, ...)
147 {
148 va_list va;
149 int rv;
150
151 if (el == NULL)
152 return (-1);
153 va_start(va, op);
154
155 switch (op) {
156 case EL_PROMPT:
157 case EL_RPROMPT:
158 rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
159 break;
160
161 case EL_TERMINAL:
162 rv = term_set(el, va_arg(va, char *));
163 break;
164
165 case EL_EDITOR:
166 rv = map_set_editor(el, va_arg(va, char *));
167 break;
168
169 case EL_SIGNAL:
170 if (va_arg(va, int))
171 el->el_flags |= HANDLE_SIGNALS;
172 else
173 el->el_flags &= ~HANDLE_SIGNALS;
174 rv = 0;
175 break;
176
177 case EL_BIND:
178 case EL_TELLTC:
179 case EL_SETTC:
180 case EL_ECHOTC:
181 case EL_SETTY:
182 {
183 char *argv[20];
184 int i;
185
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 EL_ABORT((el->el_errfile, "Bad op %d\n", op));
219 break;
220 }
221 break;
222 }
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
230 rv = map_addfunc(el, name, help, func);
231 break;
232 }
233
234 case EL_HIST:
235 {
236 hist_fun_t func = va_arg(va, hist_fun_t);
237 ptr_t ptr = va_arg(va, char *);
238
239 rv = hist_set(el, func, ptr);
240 break;
241 }
242
243 case EL_EDITMODE:
244 if (va_arg(va, int))
245 el->el_flags &= ~EDIT_DISABLED;
246 else
247 el->el_flags |= EDIT_DISABLED;
248 rv = 0;
249 break;
250
251 case EL_GETCFN:
252 {
253 el_rfunc_t rc = va_arg(va, el_rfunc_t);
254 rv = el_read_setfn(el, rc);
255 break;
256 }
257
258 default:
259 rv = -1;
260 }
261
262 va_end(va);
263 return (rv);
264 }
265
266
267 /* el_get():
268 * retrieve the editline parameters
269 */
270 public int
271 el_get(EditLine *el, int op, void *ret)
272 {
273 int rv;
274
275 if (el == NULL || ret == NULL)
276 return (-1);
277 switch (op) {
278 case EL_PROMPT:
279 case EL_RPROMPT:
280 rv = prompt_get(el, (el_pfunc_t *) & ret, op);
281 break;
282
283 case EL_EDITOR:
284 rv = map_get_editor(el, (const char **) &ret);
285 break;
286
287 case EL_SIGNAL:
288 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
289 rv = 0;
290 break;
291
292 case EL_EDITMODE:
293 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
294 rv = 0;
295 break;
296
297 #if 0 /* XXX */
298 case EL_TERMINAL:
299 rv = term_get(el, (const char *) &ret);
300 break;
301
302 case EL_BIND:
303 case EL_TELLTC:
304 case EL_SETTC:
305 case EL_ECHOTC:
306 case EL_SETTY:
307 {
308 char *argv[20];
309 int i;
310
311 for (i = 1; i < 20; i++)
312 if ((argv[i] = va_arg(va, char *)) == NULL)
313 break;
314
315 switch (op) {
316 case EL_BIND:
317 argv[0] = "bind";
318 rv = map_bind(el, i, argv);
319 break;
320
321 case EL_TELLTC:
322 argv[0] = "telltc";
323 rv = term_telltc(el, i, argv);
324 break;
325
326 case EL_SETTC:
327 argv[0] = "settc";
328 rv = term_settc(el, i, argv);
329 break;
330
331 case EL_ECHOTC:
332 argv[0] = "echotc";
333 rv = term_echotc(el, i, argv);
334 break;
335
336 case EL_SETTY:
337 argv[0] = "setty";
338 rv = tty_stty(el, i, argv);
339 break;
340
341 default:
342 rv = -1;
343 EL_ABORT((el->errfile, "Bad op %d\n", op));
344 break;
345 }
346 break;
347 }
348
349 case EL_ADDFN:
350 {
351 char *name = va_arg(va, char *);
352 char *help = va_arg(va, char *);
353 el_func_t func = va_arg(va, el_func_t);
354
355 rv = map_addfunc(el, name, help, func);
356 break;
357 }
358
359 case EL_HIST:
360 {
361 hist_fun_t func = va_arg(va, hist_fun_t);
362 ptr_t ptr = va_arg(va, char *);
363 rv = hist_set(el, func, ptr);
364 }
365 break;
366 #endif /* XXX */
367
368 case EL_GETCFN:
369 *((el_rfunc_t *)ret) = el_read_getfn(el);
370 rv = 0;
371 break;
372
373 default:
374 rv = -1;
375 }
376
377 return (rv);
378 }
379
380
381 /* el_line():
382 * Return editing info
383 */
384 public const LineInfo *
385 el_line(EditLine *el)
386 {
387
388 return (const LineInfo *) (void *) &el->el_line;
389 }
390
391 static const char elpath[] = "/.editrc";
392
393 /* el_source():
394 * Source a file
395 */
396 public int
397 el_source(EditLine *el, const char *fname)
398 {
399 FILE *fp;
400 size_t len;
401 char *ptr, path[MAXPATHLEN];
402
403 fp = NULL;
404 if (fname == NULL) {
405 if (issetugid())
406 return (-1);
407 if ((ptr = getenv("HOME")) == NULL)
408 return (-1);
409 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
410 return (-1);
411 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
412 return (-1);
413 fname = path;
414 }
415 if (fp == NULL)
416 fp = fopen(fname, "r");
417 if (fp == NULL)
418 return (-1);
419
420 while ((ptr = fgetln(fp, &len)) != NULL) {
421 if (len > 0 && ptr[len - 1] == '\n')
422 --len;
423 ptr[len] = '\0';
424 if (parse_line(el, ptr) == -1) {
425 (void) fclose(fp);
426 return (-1);
427 }
428 }
429
430 (void) fclose(fp);
431 return (0);
432 }
433
434
435 /* el_resize():
436 * Called from program when terminal is resized
437 */
438 public void
439 el_resize(EditLine *el)
440 {
441 int lins, cols;
442 sigset_t oset, nset;
443
444 (void) sigemptyset(&nset);
445 (void) sigaddset(&nset, SIGWINCH);
446 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
447
448 /* get the correct window size */
449 if (term_get_size(el, &lins, &cols))
450 term_change_size(el, lins, cols);
451
452 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
453 }
454
455
456 /* el_beep():
457 * Called from the program to beep
458 */
459 public void
460 el_beep(EditLine *el)
461 {
462
463 term_beep(el);
464 }
465
466
467 /* el_editmode()
468 * Set the state of EDIT_DISABLED from the `edit' command.
469 */
470 protected int
471 /*ARGSUSED*/
472 el_editmode(EditLine *el, int argc, char **argv)
473 {
474 const char *how;
475
476 if (argv == NULL || argc != 2 || argv[1] == NULL)
477 return (-1);
478
479 how = argv[1];
480 if (strcmp(how, "on") == 0)
481 el->el_flags &= ~EDIT_DISABLED;
482 else if (strcmp(how, "off") == 0)
483 el->el_flags |= EDIT_DISABLED;
484 else {
485 (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
486 return (-1);
487 }
488 return (0);
489 }
490