source: heimdal/trunk/lib/libedit/src/el.c

Last change on this file was 1, checked in by Paul Smedley, 10 years ago

Initial commit of Heimdal 1.5.3

File size: 11.4 KB
Line 
1/* $NetBSD: el.c,v 1.61 2011/01/27 23:11:40 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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include "config.h"
36#if !defined(lint) && !defined(SCCSID)
37#if 0
38static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
39#else
40__RCSID("$NetBSD: el.c,v 1.61 2011/01/27 23:11:40 christos Exp $");
41#endif
42#endif /* not lint && not SCCSID */
43
44#ifndef MAXPATHLEN
45#define MAXPATHLEN 4096
46#endif
47
48/*
49 * el.c: EditLine interface functions
50 */
51#include <sys/types.h>
52#include <sys/param.h>
53#include <string.h>
54#include <stdlib.h>
55#include <stdarg.h>
56#include <ctype.h>
57#include <locale.h>
58#include <langinfo.h>
59#include "el.h"
60
61/* el_init():
62 * Initialize editline and set default parameters.
63 */
64public EditLine *
65el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
66{
67 EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
68
69 if (el == NULL)
70 return (NULL);
71
72 memset(el, 0, sizeof(EditLine));
73
74 el->el_infile = fin;
75 el->el_outfile = fout;
76 el->el_errfile = ferr;
77
78 el->el_infd = fileno(fin);
79 el->el_outfd = fileno(fout);
80 el->el_errfd = fileno(ferr);
81
82 el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
83 if (el->el_prog == NULL) {
84 el_free(el);
85 return NULL;
86 }
87
88 /*
89 * Initialize all the modules. Order is important!!!
90 */
91 el->el_flags = 0;
92#ifdef WIDECHAR
93 if (setlocale(LC_CTYPE, NULL) != NULL){
94 if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
95 el->el_flags |= CHARSET_IS_UTF8;
96 }
97#endif
98
99 if (term_init(el) == -1) {
100 el_free(el->el_prog);
101 el_free(el);
102 return NULL;
103 }
104 (void) key_init(el);
105 (void) map_init(el);
106 if (tty_init(el) == -1)
107 el->el_flags |= NO_TTY;
108 (void) ch_init(el);
109 (void) search_init(el);
110 (void) hist_init(el);
111 (void) prompt_init(el);
112 (void) sig_init(el);
113 (void) read_init(el);
114
115 return (el);
116}
117
118
119/* el_end():
120 * Clean up.
121 */
122public void
123el_end(EditLine *el)
124{
125
126 if (el == NULL)
127 return;
128
129 el_reset(el);
130
131 term_end(el);
132 key_end(el);
133 map_end(el);
134 tty_end(el);
135 ch_end(el);
136 search_end(el);
137 hist_end(el);
138 prompt_end(el);
139 sig_end(el);
140
141 el_free((ptr_t) el->el_prog);
142 el_free((ptr_t) el);
143#ifdef WIDECHAR
144 el_free((ptr_t) el->el_scratch.cbuff);
145 el_free((ptr_t) el->el_scratch.wbuff);
146 el_free((ptr_t) el->el_lgcyconv.cbuff);
147 el_free((ptr_t) el->el_lgcyconv.wbuff);
148#endif
149}
150
151
152/* el_reset():
153 * Reset the tty and the parser
154 */
155public void
156el_reset(EditLine *el)
157{
158
159 tty_cookedmode(el);
160 ch_reset(el, 0); /* XXX: Do we want that? */
161}
162
163
164/* el_set():
165 * set the editline parameters
166 */
167public int
168FUN(el,set)(EditLine *el, int op, ...)
169{
170 va_list ap;
171 int rv = 0;
172
173 if (el == NULL)
174 return (-1);
175 va_start(ap, op);
176
177 switch (op) {
178 case EL_PROMPT:
179 case EL_RPROMPT: {
180 el_pfunc_t p = va_arg(ap, el_pfunc_t);
181
182 rv = prompt_set(el, p, 0, op, 1);
183 break;
184 }
185
186 case EL_RESIZE: {
187 el_zfunc_t p = va_arg(ap, el_zfunc_t);
188 void *arg = va_arg(ap, void *);
189 rv = ch_resizefun(el, p, arg);
190 break;
191 }
192
193 case EL_PROMPT_ESC:
194 case EL_RPROMPT_ESC: {
195 el_pfunc_t p = va_arg(ap, el_pfunc_t);
196 int c = va_arg(ap, int);
197
198 rv = prompt_set(el, p, c, op, 1);
199 break;
200 }
201
202 case EL_TERMINAL:
203 rv = term_set(el, va_arg(ap, char *));
204 break;
205
206 case EL_EDITOR:
207 rv = map_set_editor(el, va_arg(ap, Char *));
208 break;
209
210 case EL_SIGNAL:
211 if (va_arg(ap, int))
212 el->el_flags |= HANDLE_SIGNALS;
213 else
214 el->el_flags &= ~HANDLE_SIGNALS;
215 break;
216
217 case EL_BIND:
218 case EL_TELLTC:
219 case EL_SETTC:
220 case EL_ECHOTC:
221 case EL_SETTY:
222 {
223 const Char *argv[20];
224 int i;
225
226 for (i = 1; i < 20; i++)
227 if ((argv[i] = va_arg(ap, Char *)) == NULL)
228 break;
229
230 switch (op) {
231 case EL_BIND:
232 argv[0] = STR("bind");
233 rv = map_bind(el, i, argv);
234 break;
235
236 case EL_TELLTC:
237 argv[0] = STR("telltc");
238 rv = term_telltc(el, i, argv);
239 break;
240
241 case EL_SETTC:
242 argv[0] = STR("settc");
243 rv = term_settc(el, i, argv);
244 break;
245
246 case EL_ECHOTC:
247 argv[0] = STR("echotc");
248 rv = term_echotc(el, i, argv);
249 break;
250
251 case EL_SETTY:
252 argv[0] = STR("setty");
253 rv = tty_stty(el, i, argv);
254 break;
255
256 default:
257 rv = -1;
258 EL_ABORT((el->el_errfile, "Bad op %d\n", op));
259 break;
260 }
261 break;
262 }
263
264 case EL_ADDFN:
265 {
266 Char *name = va_arg(ap, Char *);
267 Char *help = va_arg(ap, Char *);
268 el_func_t func = va_arg(ap, el_func_t);
269
270 rv = map_addfunc(el, name, help, func);
271 break;
272 }
273
274 case EL_HIST:
275 {
276 hist_fun_t func = va_arg(ap, hist_fun_t);
277 ptr_t ptr = va_arg(ap, ptr_t);
278
279 rv = hist_set(el, func, ptr);
280 if (!(el->el_flags & CHARSET_IS_UTF8))
281 el->el_flags &= ~NARROW_HISTORY;
282 break;
283 }
284
285 case EL_EDITMODE:
286 if (va_arg(ap, int))
287 el->el_flags &= ~EDIT_DISABLED;
288 else
289 el->el_flags |= EDIT_DISABLED;
290 rv = 0;
291 break;
292
293 case EL_GETCFN:
294 {
295 el_rfunc_t rc = va_arg(ap, el_rfunc_t);
296 rv = el_read_setfn(el, rc);
297 el->el_flags &= ~NARROW_READ;
298 break;
299 }
300
301 case EL_CLIENTDATA:
302 el->el_data = va_arg(ap, void *);
303 break;
304
305 case EL_UNBUFFERED:
306 rv = va_arg(ap, int);
307 if (rv && !(el->el_flags & UNBUFFERED)) {
308 el->el_flags |= UNBUFFERED;
309 read_prepare(el);
310 } else if (!rv && (el->el_flags & UNBUFFERED)) {
311 el->el_flags &= ~UNBUFFERED;
312 read_finish(el);
313 }
314 rv = 0;
315 break;
316
317 case EL_PREP_TERM:
318 rv = va_arg(ap, int);
319 if (rv)
320 (void) tty_rawmode(el);
321 else
322 (void) tty_cookedmode(el);
323 rv = 0;
324 break;
325
326 case EL_SETFP:
327 {
328 FILE *fp;
329 int what;
330
331 what = va_arg(ap, int);
332 fp = va_arg(ap, FILE *);
333
334 rv = 0;
335 switch (what) {
336 case 0:
337 el->el_infile = fp;
338 el->el_infd = fileno(fp);
339 break;
340 case 1:
341 el->el_outfile = fp;
342 el->el_outfd = fileno(fp);
343 break;
344 case 2:
345 el->el_errfile = fp;
346 el->el_errfd = fileno(fp);
347 break;
348 default:
349 rv = -1;
350 break;
351 }
352 break;
353 }
354
355 case EL_REFRESH:
356 re_clear_display(el);
357 re_refresh(el);
358 term__flush(el);
359 break;
360
361 default:
362 rv = -1;
363 break;
364 }
365
366 va_end(ap);
367 return (rv);
368}
369
370
371/* el_get():
372 * retrieve the editline parameters
373 */
374public int
375FUN(el,get)(EditLine *el, int op, ...)
376{
377 va_list ap;
378 int rv;
379
380 if (el == NULL)
381 return -1;
382
383 va_start(ap, op);
384
385 switch (op) {
386 case EL_PROMPT:
387 case EL_RPROMPT: {
388 el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
389 rv = prompt_get(el, p, 0, op);
390 break;
391 }
392 case EL_PROMPT_ESC:
393 case EL_RPROMPT_ESC: {
394 el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
395 Char *c = va_arg(ap, Char *);
396
397 rv = prompt_get(el, p, c, op);
398 break;
399 }
400
401 case EL_EDITOR:
402 rv = map_get_editor(el, va_arg(ap, const Char **));
403 break;
404
405 case EL_SIGNAL:
406 *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
407 rv = 0;
408 break;
409
410 case EL_EDITMODE:
411 *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
412 rv = 0;
413 break;
414
415 case EL_TERMINAL:
416 term_get(el, va_arg(ap, const char **));
417 rv = 0;
418 break;
419
420 case EL_GETTC:
421 {
422 static char name[] = "gettc";
423 char *argv[20];
424 int i;
425
426 for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++)
427 if ((argv[i] = va_arg(ap, char *)) == NULL)
428 break;
429
430 switch (op) {
431 case EL_GETTC:
432 argv[0] = name;
433 rv = term_gettc(el, i, argv);
434 break;
435
436 default:
437 rv = -1;
438 EL_ABORT((el->el_errfile, "Bad op %d\n", op));
439 break;
440 }
441 break;
442 }
443
444 case EL_GETCFN:
445 *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
446 rv = 0;
447 break;
448
449 case EL_CLIENTDATA:
450 *va_arg(ap, void **) = el->el_data;
451 rv = 0;
452 break;
453
454 case EL_UNBUFFERED:
455 *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
456 rv = 0;
457 break;
458
459 case EL_GETFP:
460 {
461 int what;
462 FILE **fpp;
463
464 what = va_arg(ap, int);
465 fpp = va_arg(ap, FILE **);
466 rv = 0;
467 switch (what) {
468 case 0:
469 *fpp = el->el_infile;
470 break;
471 case 1:
472 *fpp = el->el_outfile;
473 break;
474 case 2:
475 *fpp = el->el_errfile;
476 break;
477 default:
478 rv = -1;
479 break;
480 }
481 break;
482 }
483 default:
484 rv = -1;
485 break;
486 }
487 va_end(ap);
488
489 return (rv);
490}
491
492
493/* el_line():
494 * Return editing info
495 */
496public const TYPE(LineInfo) *
497FUN(el,line)(EditLine *el)
498{
499
500 return (const TYPE(LineInfo) *) (void *) &el->el_line;
501}
502
503
504/* el_source():
505 * Source a file
506 */
507public int
508el_source(EditLine *el, const char *fname)
509{
510 FILE *fp;
511 size_t len;
512 char *ptr;
513 char path[MAXPATHLEN];
514 const Char *dptr;
515
516 fp = NULL;
517 if (fname == NULL) {
518 static const char elpath[] = "/.editrc";
519
520#ifdef HAVE_ISSETUGID
521 if (issetugid())
522 return (-1);
523#endif
524 if ((ptr = getenv("HOME")) == NULL)
525 return (-1);
526 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
527 return (-1);
528 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
529 return (-1);
530 fname = path;
531 }
532 if (fp == NULL)
533 fp = fopen(fname, "r");
534 if (fp == NULL)
535 return (-1);
536
537 while ((ptr = fgetln(fp, &len)) != NULL) {
538 dptr = ct_decode_string(ptr, &el->el_scratch);
539 if (!dptr)
540 continue;
541 if (len > 0 && dptr[len - 1] == '\n')
542 --len;
543
544 /* loop until first non-space char or EOL */
545 while (*dptr != '\0' && Isspace(*dptr))
546 dptr++;
547 if (*dptr == '#')
548 continue; /* ignore, this is a comment line */
549 if (parse_line(el, dptr) == -1) {
550 (void) fclose(fp);
551 return (-1);
552 }
553 }
554
555 (void) fclose(fp);
556 return (0);
557}
558
559
560/* el_resize():
561 * Called from program when terminal is resized
562 */
563public void
564el_resize(EditLine *el)
565{
566 int lins, cols;
567 sigset_t oset, nset;
568
569 (void) sigemptyset(&nset);
570 (void) sigaddset(&nset, SIGWINCH);
571 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
572
573 /* get the correct window size */
574 if (term_get_size(el, &lins, &cols))
575 term_change_size(el, lins, cols);
576
577 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
578}
579
580
581/* el_beep():
582 * Called from the program to beep
583 */
584public void
585el_beep(EditLine *el)
586{
587
588 term_beep(el);
589}
590
591
592/* el_editmode()
593 * Set the state of EDIT_DISABLED from the `edit' command.
594 */
595protected int
596/*ARGSUSED*/
597el_editmode(EditLine *el, int argc, const Char **argv)
598{
599 const Char *how;
600
601 if (argv == NULL || argc != 2 || argv[1] == NULL)
602 return (-1);
603
604 how = argv[1];
605 if (Strcmp(how, STR("on")) == 0) {
606 el->el_flags &= ~EDIT_DISABLED;
607 tty_rawmode(el);
608 } else if (Strcmp(how, STR("off")) == 0) {
609 tty_cookedmode(el);
610 el->el_flags |= EDIT_DISABLED;
611 }
612 else {
613 (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n",
614 how);
615 return (-1);
616 }
617 return (0);
618}
Note: See TracBrowser for help on using the repository browser.