el.c revision 1.13 1 /* $NetBSD: el.c,v 1.13 1999/07/02 15:21:23 simonb 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.13 1999/07/02 15:21:23 simonb 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 #ifdef __STDC__
58 # include <stdarg.h>
59 #else
60 # include <varargs.h>
61 #endif
62 #include "el.h"
63
64 /* el_init():
65 * Initialize editline and set default parameters.
66 */
67 public EditLine *
68 el_init(prog, fin, fout, ferr)
69 const char *prog;
70 FILE *fin, *fout, *ferr;
71 {
72 EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
73 #ifdef DEBUG
74 char *tty;
75 #endif
76
77 if (el == NULL)
78 return NULL;
79
80 memset(el, 0, sizeof(EditLine));
81
82 el->el_infd = fileno(fin);
83 el->el_outfile = fout;
84 el->el_errfile = ferr;
85 el->el_prog = strdup(prog);
86
87 /*
88 * Initialize all the modules. Order is important!!!
89 */
90 el->el_flags = 0;
91 (void) term_init(el);
92 (void) key_init(el);
93 (void) map_init(el);
94 if (tty_init(el) == -1)
95 el->el_flags |= NO_TTY;
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
102 return el;
103 } /* end el_init */
104
105
106 /* el_end():
107 * Clean up.
108 */
109 public void
110 el_end(el)
111 EditLine *el;
112 {
113 if (el == NULL)
114 return;
115
116 el_reset(el);
117
118 term_end(el);
119 key_end(el);
120 map_end(el);
121 tty_end(el);
122 ch_end(el);
123 search_end(el);
124 hist_end(el);
125 prompt_end(el);
126 sig_end(el);
127
128 el_free((ptr_t) el->el_prog);
129 el_free((ptr_t) el);
130 } /* end el_end */
131
132
133 /* el_reset():
134 * Reset the tty and the parser
135 */
136 public void
137 el_reset(el)
138 EditLine *el;
139 {
140 tty_cookedmode(el);
141 ch_reset(el); /* XXX: Do we want that? */
142 }
143
144
145 /* el_set():
146 * set the editline parameters
147 */
148 public int
149 #ifdef __STDC__
150 el_set(EditLine *el, int op, ...)
151 #else
152 el_set(va_alist)
153 va_dcl
154 #endif
155 {
156 va_list va;
157 int rv;
158 #ifdef __STDC__
159 va_start(va, op);
160 #else
161 EditLine *el;
162 int op;
163
164 va_start(va);
165 el = va_arg(va, EditLine *);
166 op = va_arg(va, int);
167 #endif
168
169 if (el == NULL)
170 return -1;
171 switch (op) {
172 case EL_PROMPT:
173 rv = prompt_set(el, va_arg(va, el_pfunc_t));
174 break;
175
176 case EL_TERMINAL:
177 rv = term_set(el, va_arg(va, char *));
178 break;
179
180 case EL_EDITOR:
181 rv = map_set_editor(el, va_arg(va, char *));
182 break;
183
184 case EL_SIGNAL:
185 if (va_arg(va, int))
186 el->el_flags |= HANDLE_SIGNALS;
187 else
188 el->el_flags &= ~HANDLE_SIGNALS;
189 rv = 0;
190 break;
191
192 case EL_BIND:
193 case EL_TELLTC:
194 case EL_SETTC:
195 case EL_ECHOTC:
196 case EL_SETTY:
197 {
198 char *argv[20];
199 int i;
200 for (i = 1; i < 20; i++)
201 if ((argv[i] = va_arg(va, char *)) == NULL)
202 break;
203
204 switch (op) {
205 case EL_BIND:
206 argv[0] = "bind";
207 rv = map_bind(el, i, argv);
208 break;
209
210 case EL_TELLTC:
211 argv[0] = "telltc";
212 rv = term_telltc(el, i, argv);
213 break;
214
215 case EL_SETTC:
216 argv[0] = "settc";
217 rv = term_settc(el, i, argv);
218 break;
219
220 case EL_ECHOTC:
221 argv[0] = "echotc";
222 rv = term_echotc(el, i, argv);
223 break;
224
225 case EL_SETTY:
226 argv[0] = "setty";
227 rv = tty_stty(el, i, argv);
228 break;
229
230 default:
231 rv = -1;
232 abort();
233 break;
234 }
235 }
236 break;
237
238 case EL_ADDFN:
239 {
240 char *name = va_arg(va, char *);
241 char *help = va_arg(va, char *);
242 el_func_t func = va_arg(va, el_func_t);
243 rv = map_addfunc(el, name, help, func);
244 }
245 break;
246
247 case EL_HIST:
248 {
249 hist_fun_t func = va_arg(va, hist_fun_t);
250 ptr_t ptr = va_arg(va, char *);
251 rv = hist_set(el, func, ptr);
252 }
253 break;
254
255 case EL_EDITMODE:
256 if (va_arg(va, int))
257 el->el_flags &= ~EDIT_DISABLED;
258 else
259 el->el_flags |= EDIT_DISABLED;
260 rv = 0;
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_get():
273 * retrieve the editline parameters
274 */
275 public int
276 el_get(el, op, ret)
277 EditLine *el;
278 int op;
279 void *ret;
280 {
281 int rv;
282
283 if (el == NULL || ret == NULL)
284 return -1;
285 switch (op) {
286 case EL_PROMPT:
287 rv = prompt_get(el, (el_pfunc_t *)&ret);
288 break;
289
290 case EL_EDITOR:
291 rv = map_get_editor(el, (const char **)&ret);
292 break;
293
294 case EL_SIGNAL:
295 *((int *)ret) = (el->el_flags & HANDLE_SIGNALS);
296 rv = 0;
297 break;
298
299 case EL_EDITMODE:
300 *((int *)ret) = (!(el->el_flags & EDIT_DISABLED));
301 rv = 0;
302 break;
303
304 #if 0 /*XXX*/
305 case EL_TERMINAL:
306 rv = term_get(el, (const char *)&ret);
307 break;
308
309 case EL_BIND:
310 case EL_TELLTC:
311 case EL_SETTC:
312 case EL_ECHOTC:
313 case EL_SETTY:
314 {
315 char *argv[20];
316 int i;
317 for (i = 1; i < 20; i++)
318 if ((argv[i] = va_arg(va, char *)) == NULL)
319 break;
320
321 switch (op) {
322 case EL_BIND:
323 argv[0] = "bind";
324 rv = map_bind(el, i, argv);
325 break;
326
327 case EL_TELLTC:
328 argv[0] = "telltc";
329 rv = term_telltc(el, i, argv);
330 break;
331
332 case EL_SETTC:
333 argv[0] = "settc";
334 rv = term_settc(el, i, argv);
335 break;
336
337 case EL_ECHOTC:
338 argv[0] = "echotc";
339 rv = term_echotc(el, i, argv);
340 break;
341
342 case EL_SETTY:
343 argv[0] = "setty";
344 rv = tty_stty(el, i, argv);
345 break;
346
347 default:
348 rv = -1;
349 abort();
350 break;
351 }
352 }
353 break;
354
355 case EL_ADDFN:
356 {
357 char *name = va_arg(va, char *);
358 char *help = va_arg(va, char *);
359 el_func_t func = va_arg(va, el_func_t);
360 rv = map_addfunc(el, name, help, func);
361 }
362 break;
363
364 case EL_HIST:
365 {
366 hist_fun_t func = va_arg(va, hist_fun_t);
367 ptr_t ptr = va_arg(va, char *);
368 rv = hist_set(el, func, ptr);
369 }
370 break;
371 #endif /*XXX*/
372
373 default:
374 rv = -1;
375 }
376
377 return rv;
378 } /* end el_get */
379
380
381 /* el_line():
382 * Return editing info
383 */
384 public const LineInfo *
385 el_line(el)
386 EditLine *el;
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(el, fname)
398 EditLine *el;
399 const char *fname;
400 {
401 FILE *fp;
402 size_t len;
403 char *ptr, path[MAXPATHLEN];
404
405 if (fname == NULL) {
406 fname = &elpath[1];
407 if ((fp = fopen(fname, "r")) == NULL) {
408 if ((ptr = getenv("HOME")) == NULL)
409 return -1;
410 (void)snprintf(path, sizeof(path), "%s%s", ptr, elpath);
411 fname = path;
412 }
413 }
414
415 if ((fp = fopen(fname, "r")) == NULL)
416 return -1;
417
418 while ((ptr = fgetln(fp, &len)) != NULL) {
419 if (ptr[len - 1] == '\n')
420 --len;
421 ptr[len] = '\0';
422 if (parse_line(el, ptr) == -1) {
423 (void) fclose(fp);
424 return -1;
425 }
426 }
427
428 (void) fclose(fp);
429 return 0;
430 }
431
432
433 /* el_resize():
434 * Called from program when terminal is resized
435 */
436 public void
437 el_resize(el)
438 EditLine *el;
439 {
440 int lins, cols;
441 sigset_t oset, nset;
442 (void) sigemptyset(&nset);
443 (void) sigaddset(&nset, SIGWINCH);
444 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
445
446 /* get the correct window size */
447 if (term_get_size(el, &lins, &cols))
448 term_change_size(el, lins, cols);
449
450 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
451 }
452
453 /* el_beep():
454 * Called from the program to beep
455 */
456 public void
457 el_beep(el)
458 EditLine *el;
459 {
460 term_beep(el);
461 }
462
463
464 /* el_editmode()
465 * Set the state of EDIT_DISABLED from the `edit' command.
466 */
467 protected int
468 /*ARGSUSED*/
469 el_editmode(el, argc, argv)
470 EditLine *el;
471 int argc;
472 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 } /* end el_editmode */
490