Annotation of src/lib/libedit/el.c, Revision 1.47.2.1
1.47.2.1! jym 1: /* $NetBSD: el.c,v 1.52 2009/05/11 18:33:30 christos Exp $ */
1.2 lukem 2:
1.1 cgd 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.
1.32 agc 18: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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:
1.29 christos 35: #include "config.h"
1.1 cgd 36: #if !defined(lint) && !defined(SCCSID)
1.2 lukem 37: #if 0
1.1 cgd 38: static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
1.2 lukem 39: #else
1.47.2.1! jym 40: __RCSID("$NetBSD: el.c,v 1.52 2009/05/11 18:33:30 christos Exp $");
1.2 lukem 41: #endif
1.1 cgd 42: #endif /* not lint && not SCCSID */
43:
44: /*
45: * el.c: EditLine interface functions
46: */
47: #include <sys/types.h>
48: #include <sys/param.h>
49: #include <string.h>
50: #include <stdlib.h>
1.19 lukem 51: #include <stdarg.h>
1.1 cgd 52: #include "el.h"
53:
54: /* el_init():
55: * Initialize editline and set default parameters.
56: */
57: public EditLine *
1.19 lukem 58: el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
1.1 cgd 59: {
1.18 chuck 60:
1.19 lukem 61: EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
1.1 cgd 62:
1.19 lukem 63: if (el == NULL)
64: return (NULL);
1.1 cgd 65:
1.19 lukem 66: memset(el, 0, sizeof(EditLine));
1.1 cgd 67:
1.44 christos 68: el->el_infile = fin;
1.19 lukem 69: el->el_outfile = fout;
70: el->el_errfile = ferr;
1.44 christos 71:
72: el->el_infd = fileno(fin);
73:
1.36 christos 74: if ((el->el_prog = el_strdup(prog)) == NULL) {
75: el_free(el);
76: return NULL;
77: }
1.19 lukem 78:
79: /*
80: * Initialize all the modules. Order is important!!!
81: */
82: el->el_flags = 0;
83:
1.25 christos 84: if (term_init(el) == -1) {
1.36 christos 85: el_free(el->el_prog);
1.25 christos 86: el_free(el);
87: return NULL;
88: }
1.19 lukem 89: (void) key_init(el);
90: (void) map_init(el);
91: if (tty_init(el) == -1)
92: el->el_flags |= NO_TTY;
93: (void) ch_init(el);
94: (void) search_init(el);
95: (void) hist_init(el);
96: (void) prompt_init(el);
97: (void) sig_init(el);
1.23 christos 98: (void) read_init(el);
1.1 cgd 99:
1.19 lukem 100: return (el);
101: }
1.1 cgd 102:
103:
104: /* el_end():
105: * Clean up.
106: */
107: public void
1.19 lukem 108: el_end(EditLine *el)
1.1 cgd 109: {
110:
1.19 lukem 111: if (el == NULL)
112: return;
1.1 cgd 113:
1.19 lukem 114: el_reset(el);
115:
116: term_end(el);
117: key_end(el);
118: map_end(el);
119: tty_end(el);
120: ch_end(el);
121: search_end(el);
122: hist_end(el);
123: prompt_end(el);
124: sig_end(el);
125:
126: el_free((ptr_t) el->el_prog);
127: el_free((ptr_t) el);
128: }
1.1 cgd 129:
130:
131: /* el_reset():
132: * Reset the tty and the parser
133: */
134: public void
1.19 lukem 135: el_reset(EditLine *el)
1.1 cgd 136: {
1.19 lukem 137:
138: tty_cookedmode(el);
1.40 christos 139: ch_reset(el, 0); /* XXX: Do we want that? */
1.1 cgd 140: }
141:
142:
143: /* el_set():
144: * set the editline parameters
145: */
146: public int
147: el_set(EditLine *el, int op, ...)
148: {
1.44 christos 149: va_list ap;
1.27 christos 150: int rv = 0;
1.1 cgd 151:
1.19 lukem 152: if (el == NULL)
153: return (-1);
1.44 christos 154: va_start(ap, op);
1.22 wiz 155:
1.19 lukem 156: switch (op) {
157: case EL_PROMPT:
1.47.2.1! jym 158: case EL_RPROMPT: {
! 159: el_pfunc_t p = va_arg(ap, el_pfunc_t);
! 160:
! 161: rv = prompt_set(el, p, 0, op);
! 162: break;
! 163: }
! 164:
! 165: case EL_PROMPT_ESC:
! 166: case EL_RPROMPT_ESC: {
! 167: el_pfunc_t p = va_arg(ap, el_pfunc_t);
! 168: char c = va_arg(ap, int);
! 169:
! 170: rv = prompt_set(el, p, c, op);
1.19 lukem 171: break;
1.47.2.1! jym 172: }
1.13 simonb 173:
1.19 lukem 174: case EL_TERMINAL:
1.44 christos 175: rv = term_set(el, va_arg(ap, char *));
1.19 lukem 176: break;
1.1 cgd 177:
1.19 lukem 178: case EL_EDITOR:
1.44 christos 179: rv = map_set_editor(el, va_arg(ap, char *));
1.1 cgd 180: break;
181:
1.19 lukem 182: case EL_SIGNAL:
1.44 christos 183: if (va_arg(ap, int))
1.19 lukem 184: el->el_flags |= HANDLE_SIGNALS;
185: else
186: el->el_flags &= ~HANDLE_SIGNALS;
1.1 cgd 187: break;
188:
1.19 lukem 189: case EL_BIND:
190: case EL_TELLTC:
191: case EL_SETTC:
1.42 christos 192: case EL_GETTC:
1.19 lukem 193: case EL_ECHOTC:
194: case EL_SETTY:
195: {
1.29 christos 196: const char *argv[20];
1.19 lukem 197: int i;
198:
199: for (i = 1; i < 20; i++)
1.44 christos 200: if ((argv[i] = va_arg(ap, char *)) == NULL)
1.19 lukem 201: break;
202:
203: switch (op) {
204: case EL_BIND:
205: argv[0] = "bind";
206: rv = map_bind(el, i, argv);
207: break;
208:
209: case EL_TELLTC:
210: argv[0] = "telltc";
211: rv = term_telltc(el, i, argv);
212: break;
213:
214: case EL_SETTC:
215: argv[0] = "settc";
216: rv = term_settc(el, i, argv);
217: break;
218:
219: case EL_ECHOTC:
220: argv[0] = "echotc";
221: rv = term_echotc(el, i, argv);
222: break;
223:
224: case EL_SETTY:
225: argv[0] = "setty";
226: rv = tty_stty(el, i, argv);
227: break;
228:
229: default:
230: rv = -1;
1.20 christos 231: EL_ABORT((el->el_errfile, "Bad op %d\n", op));
1.19 lukem 232: break;
233: }
1.1 cgd 234: break;
1.19 lukem 235: }
236:
237: case EL_ADDFN:
238: {
1.44 christos 239: char *name = va_arg(ap, char *);
240: char *help = va_arg(ap, char *);
241: el_func_t func = va_arg(ap, el_func_t);
1.1 cgd 242:
1.19 lukem 243: rv = map_addfunc(el, name, help, func);
1.1 cgd 244: break;
1.19 lukem 245: }
246:
247: case EL_HIST:
248: {
1.44 christos 249: hist_fun_t func = va_arg(ap, hist_fun_t);
250: ptr_t ptr = va_arg(ap, char *);
1.1 cgd 251:
1.19 lukem 252: rv = hist_set(el, func, ptr);
1.1 cgd 253: break;
1.19 lukem 254: }
1.1 cgd 255:
1.19 lukem 256: case EL_EDITMODE:
1.44 christos 257: if (va_arg(ap, int))
1.19 lukem 258: el->el_flags &= ~EDIT_DISABLED;
259: else
260: el->el_flags |= EDIT_DISABLED;
261: rv = 0;
1.1 cgd 262: break;
1.13 simonb 263:
1.23 christos 264: case EL_GETCFN:
265: {
1.44 christos 266: el_rfunc_t rc = va_arg(ap, el_rfunc_t);
1.23 christos 267: rv = el_read_setfn(el, rc);
268: break;
269: }
270:
1.24 christos 271: case EL_CLIENTDATA:
1.44 christos 272: el->el_data = va_arg(ap, void *);
1.24 christos 273: break;
274:
1.34 christos 275: case EL_UNBUFFERED:
1.44 christos 276: rv = va_arg(ap, int);
1.34 christos 277: if (rv && !(el->el_flags & UNBUFFERED)) {
278: el->el_flags |= UNBUFFERED;
279: read_prepare(el);
280: } else if (!rv && (el->el_flags & UNBUFFERED)) {
281: el->el_flags &= ~UNBUFFERED;
282: read_finish(el);
283: }
1.35 christos 284: rv = 0;
285: break;
286:
287: case EL_PREP_TERM:
1.44 christos 288: rv = va_arg(ap, int);
1.35 christos 289: if (rv)
1.38 christos 290: (void) tty_rawmode(el);
1.35 christos 291: else
1.38 christos 292: (void) tty_cookedmode(el);
1.34 christos 293: rv = 0;
294: break;
295:
1.44 christos 296: case EL_SETFP:
297: {
298: FILE *fp;
299: int what;
300:
301: what = va_arg(ap, int);
302: fp = va_arg(ap, FILE *);
303:
304: rv = 0;
305: switch (what) {
306: case 0:
307: el->el_infile = fp;
308: el->el_infd = fileno(fp);
309: break;
310: case 1:
311: el->el_outfile = fp;
312: break;
313: case 2:
314: el->el_errfile = fp;
315: break;
316: default:
317: rv = -1;
318: break;
319: }
320: break;
321: }
322:
1.45 christos 323: case EL_REFRESH:
324: re_clear_display(el);
325: re_refresh(el);
1.46 christos 326: term__flush(el);
1.45 christos 327: break;
328:
1.19 lukem 329: default:
330: rv = -1;
1.27 christos 331: break;
1.1 cgd 332: }
333:
1.44 christos 334: va_end(ap);
1.19 lukem 335: return (rv);
336: }
1.1 cgd 337:
338:
1.10 lukem 339: /* el_get():
340: * retrieve the editline parameters
341: */
342: public int
1.42 christos 343: el_get(EditLine *el, int op, ...)
1.10 lukem 344: {
1.42 christos 345: va_list ap;
1.19 lukem 346: int rv;
1.10 lukem 347:
1.42 christos 348: if (el == NULL)
349: return -1;
350:
351: va_start(ap, op);
352:
1.19 lukem 353: switch (op) {
354: case EL_PROMPT:
1.47.2.1! jym 355: case EL_RPROMPT: {
! 356: el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
! 357: char *c = va_arg(ap, char *);
! 358:
! 359: rv = prompt_get(el, p, c, op);
1.19 lukem 360: break;
1.47.2.1! jym 361: }
1.10 lukem 362:
1.19 lukem 363: case EL_EDITOR:
1.42 christos 364: rv = map_get_editor(el, va_arg(ap, const char **));
1.10 lukem 365: break;
366:
1.19 lukem 367: case EL_SIGNAL:
1.42 christos 368: *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
1.19 lukem 369: rv = 0;
1.10 lukem 370: break;
371:
1.19 lukem 372: case EL_EDITMODE:
1.42 christos 373: *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
1.19 lukem 374: rv = 0;
1.10 lukem 375: break;
376:
1.19 lukem 377: case EL_TERMINAL:
1.42 christos 378: term_get(el, va_arg(ap, const char **));
1.33 christos 379: rv = 0;
1.10 lukem 380: break;
381:
1.42 christos 382: case EL_GETTC:
1.19 lukem 383: {
1.42 christos 384: static char name[] = "gettc";
385: char *argv[20];
1.19 lukem 386: int i;
1.10 lukem 387:
1.47 lukem 388: for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++)
1.42 christos 389: if ((argv[i] = va_arg(ap, char *)) == NULL)
1.19 lukem 390: break;
391:
392: switch (op) {
1.42 christos 393: case EL_GETTC:
394: argv[0] = name;
395: rv = term_gettc(el, i, argv);
1.19 lukem 396: break;
397:
398: default:
399: rv = -1;
1.43 freza 400: EL_ABORT((el->el_errfile, "Bad op %d\n", op));
1.19 lukem 401: break;
402: }
1.10 lukem 403: break;
404: }
1.13 simonb 405:
1.42 christos 406: #if 0 /* XXX */
1.19 lukem 407: case EL_ADDFN:
1.10 lukem 408: {
1.44 christos 409: char *name = va_arg(ap, char *);
410: char *help = va_arg(ap, char *);
411: el_func_t func = va_arg(ap, el_func_t);
1.19 lukem 412:
413: rv = map_addfunc(el, name, help, func);
414: break;
1.10 lukem 415: }
416:
1.19 lukem 417: case EL_HIST:
418: {
1.44 christos 419: hist_fun_t func = va_arg(ap, hist_fun_t);
420: ptr_t ptr = va_arg(ap, char *);
1.19 lukem 421: rv = hist_set(el, func, ptr);
422: }
423: break;
424: #endif /* XXX */
1.23 christos 425:
426: case EL_GETCFN:
1.42 christos 427: *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
1.24 christos 428: rv = 0;
429: break;
430:
431: case EL_CLIENTDATA:
1.42 christos 432: *va_arg(ap, void **) = el->el_data;
1.34 christos 433: rv = 0;
434: break;
435:
436: case EL_UNBUFFERED:
1.42 christos 437: *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
1.23 christos 438: rv = 0;
439: break;
1.19 lukem 440:
1.44 christos 441: case EL_GETFP:
442: {
443: int what;
444: FILE **fpp;
445:
446: what = va_arg(ap, int);
447: fpp = va_arg(ap, FILE **);
448: rv = 0;
449: switch (what) {
450: case 0:
451: *fpp = el->el_infile;
452: break;
453: case 1:
454: *fpp = el->el_outfile;
455: break;
456: case 2:
457: *fpp = el->el_errfile;
458: break;
459: default:
460: rv = -1;
461: break;
462: }
463: break;
464: }
1.19 lukem 465: default:
466: rv = -1;
1.44 christos 467: break;
1.19 lukem 468: }
1.42 christos 469: va_end(ap);
1.10 lukem 470:
1.19 lukem 471: return (rv);
472: }
1.10 lukem 473:
474:
1.1 cgd 475: /* el_line():
476: * Return editing info
477: */
478: public const LineInfo *
1.19 lukem 479: el_line(EditLine *el)
1.1 cgd 480: {
1.19 lukem 481:
482: return (const LineInfo *) (void *) &el->el_line;
1.1 cgd 483: }
484:
485:
486: /* el_source():
487: * Source a file
488: */
489: public int
1.19 lukem 490: el_source(EditLine *el, const char *fname)
1.1 cgd 491: {
1.19 lukem 492: FILE *fp;
493: size_t len;
1.27 christos 494: char *ptr;
1.19 lukem 495:
496: fp = NULL;
497: if (fname == NULL) {
1.29 christos 498: #ifdef HAVE_ISSETUGID
1.27 christos 499: static const char elpath[] = "/.editrc";
500: char path[MAXPATHLEN];
501:
1.19 lukem 502: if (issetugid())
503: return (-1);
504: if ((ptr = getenv("HOME")) == NULL)
505: return (-1);
506: if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
507: return (-1);
508: if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
509: return (-1);
510: fname = path;
1.27 christos 511: #else
512: /*
513: * If issetugid() is missing, always return an error, in order
514: * to keep from inadvertently opening up the user to a security
515: * hole.
516: */
517: return (-1);
518: #endif
1.19 lukem 519: }
520: if (fp == NULL)
521: fp = fopen(fname, "r");
522: if (fp == NULL)
523: return (-1);
524:
525: while ((ptr = fgetln(fp, &len)) != NULL) {
526: if (len > 0 && ptr[len - 1] == '\n')
527: --len;
528: ptr[len] = '\0';
529: if (parse_line(el, ptr) == -1) {
530: (void) fclose(fp);
531: return (-1);
532: }
1.1 cgd 533: }
534:
1.19 lukem 535: (void) fclose(fp);
536: return (0);
1.1 cgd 537: }
538:
539:
540: /* el_resize():
541: * Called from program when terminal is resized
542: */
543: public void
1.19 lukem 544: el_resize(EditLine *el)
1.1 cgd 545: {
1.19 lukem 546: int lins, cols;
547: sigset_t oset, nset;
548:
549: (void) sigemptyset(&nset);
550: (void) sigaddset(&nset, SIGWINCH);
551: (void) sigprocmask(SIG_BLOCK, &nset, &oset);
552:
553: /* get the correct window size */
554: if (term_get_size(el, &lins, &cols))
555: term_change_size(el, lins, cols);
1.1 cgd 556:
1.19 lukem 557: (void) sigprocmask(SIG_SETMASK, &oset, NULL);
1.9 christos 558: }
1.14 lukem 559:
1.9 christos 560:
561: /* el_beep():
562: * Called from the program to beep
563: */
564: public void
1.19 lukem 565: el_beep(EditLine *el)
1.9 christos 566: {
1.19 lukem 567:
568: term_beep(el);
1.1 cgd 569: }
1.10 lukem 570:
571:
572: /* el_editmode()
573: * Set the state of EDIT_DISABLED from the `edit' command.
574: */
575: protected int
576: /*ARGSUSED*/
1.29 christos 577: el_editmode(EditLine *el, int argc, const char **argv)
1.10 lukem 578: {
1.19 lukem 579: const char *how;
1.10 lukem 580:
1.19 lukem 581: if (argv == NULL || argc != 2 || argv[1] == NULL)
582: return (-1);
1.10 lukem 583:
1.19 lukem 584: how = argv[1];
1.39 christos 585: if (strcmp(how, "on") == 0) {
1.19 lukem 586: el->el_flags &= ~EDIT_DISABLED;
1.39 christos 587: tty_rawmode(el);
588: } else if (strcmp(how, "off") == 0) {
589: tty_cookedmode(el);
1.19 lukem 590: el->el_flags |= EDIT_DISABLED;
1.39 christos 591: }
1.19 lukem 592: else {
593: (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
594: return (-1);
595: }
596: return (0);
597: }
CVSweb <webmaster@jp.NetBSD.org>