root/src/noitedit/el.c

Revision e06b23eaa47ce975bd25ec9124c72ab282f7ae97, 12.2 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 7 years ago)

Get ssl working. libedit was writing directly instead of using the opset. Change API and fixup libedit to support events.

  • Property mode set to 100644
Line 
1 /*      $NetBSD: el.c,v 1.21 2001/01/05 22:45:30 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 "noitedit/compat.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.21 2001/01/05 22:45:30 christos Exp $");
45 #endif
46 #endif /* not lint && not SCCSID */
47
48 /*
49  * el.c: EditLine interface functions
50  */
51 #include "noitedit/sys.h"
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #include <sys/types.h>
57 #if !_MSC_VER
58 #include <sys/param.h>
59 #endif
60 #include <string.h>
61 #include <stdlib.h>
62 #include <stdarg.h>
63 #include <pthread.h>
64 #include "noitedit/el.h"
65
66 pthread_key_t tputs_hack;
67 public void
68 el_multi_init() {
69   pthread_key_create(&tputs_hack, NULL);
70 }
71
72 public void
73 el_multi_set_el(EditLine *el) {
74   pthread_setspecific(tputs_hack, el);
75 }
76
77 public EditLine *
78 el_multi_get_el() {
79   return (EditLine *)pthread_getspecific(tputs_hack);
80 }
81
82 /* el_init():
83  *      Initialize editline and set default parameters.
84  */
85 public EditLine *
86 el_init(const char *prog, int infd, eventer_t in_e,
87         int outfd, eventer_t out_e, int errfd, eventer_t err_e)
88 {
89
90         EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
91 #ifdef DEBUG
92         char *tty;
93 #endif
94
95         if (el == NULL)
96                 return (NULL);
97
98         memset(el, 0, sizeof(EditLine));
99
100         el->el_infd = infd;
101         el->el_in_e = in_e;
102         el->el_outfd = outfd;
103         el->el_out_e = out_e;
104         el->el_errfd = errfd;
105         el->el_err_e = err_e;
106         el->el_err_printf = el_err_printf;
107         el->el_std_printf = el_std_printf;
108         el->el_std_putc = el_std_putc;
109         el->el_std_flush = el_std_flush;
110         el->el_prog = strdup(prog);
111
112         /*
113          * Initialize all the modules. Order is important!!!
114          */
115         el->el_flags = 0;
116
117         (void) term_init(el);
118         (void) key_init(el);
119         (void) map_init(el);
120         if (tty_init(el) == -1)
121                 el->el_flags |= NO_TTY;
122         (void) ch_init(el);
123         (void) search_init(el);
124         (void) hist_init(el);
125         (void) prompt_init(el);
126         (void) sig_init(el);
127
128         return (el);
129 }
130
131
132 /* el_end():
133  *      Clean up.
134  */
135 public void
136 el_end(EditLine *el)
137 {
138
139         if (el == NULL)
140                 return;
141
142         el_reset(el);
143
144         term_end(el);
145         key_end(el);
146         map_end(el);
147         tty_end(el);
148         ch_end(el);
149         search_end(el);
150         hist_end(el);
151         prompt_end(el);
152         sig_end(el);
153
154         el_free((ptr_t) el->el_prog);
155         el_free((ptr_t) el);
156 }
157
158
159 /* el_reset():
160  *      Reset the tty and the parser
161  */
162 public void
163 el_reset(EditLine *el)
164 {
165
166         tty_cookedmode(el);
167         ch_reset(el);           /* XXX: Do we want that? */
168 }
169
170
171 /* el_set():
172  *      set the editline parameters
173  */
174 public int
175 el_set(EditLine *el, int op, ...)
176 {
177         va_list va;
178         int rv;
179         va_start(va, op);
180
181         if (el == NULL)
182                 return (-1);
183         switch (op) {
184         case EL_PROMPT:
185         case EL_RPROMPT:
186                 rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
187                 break;
188
189         case EL_ERRPRINTFFN:
190                 el->el_err_printf = va_arg(va, el_printffunc_t);
191                 rv = 0;
192                 break;
193
194         case EL_STDPRINTFFN:
195                 el->el_std_printf = va_arg(va, el_printffunc_t);
196                 rv = 0;
197                 break;
198
199         case EL_STDPUTCFN:
200                 el->el_std_putc = va_arg(va, el_putcfunc_t);
201                 rv = 0;
202                 break;
203
204         case EL_STDFLUSHFN:
205                 el->el_std_flush = va_arg(va, el_flushfunc_t);
206                 rv = 0;
207                 break;
208
209         case EL_USERDATA:
210                 el->el_userdata = va_arg(va, void *);
211                 rv = 0;
212                 break;
213
214         case EL_TERMINAL:
215                 rv = term_set(el, va_arg(va, char *));
216                 break;
217
218         case EL_EDITOR:
219                 rv = map_set_editor(el, va_arg(va, char *));
220                 break;
221
222         case EL_SIGNAL:
223                 if (va_arg(va, int))
224                         el->el_flags |= HANDLE_SIGNALS;
225                 else
226                         el->el_flags &= ~HANDLE_SIGNALS;
227                 rv = 0;
228                 break;
229
230         case EL_BIND:
231         case EL_TELLTC:
232         case EL_SETTC:
233         case EL_ECHOTC:
234         case EL_SETTY:
235         {
236                 char *argv[20];
237                 int i;
238
239                 for (i = 1; i < 20; i++)
240                         if ((argv[i] = va_arg(va, char *)) == NULL)
241                                 break;
242
243                 switch (op) {
244                 case EL_BIND:
245                         argv[0] = "bind";
246                         rv = map_bind(el, i, argv);
247                         break;
248
249                 case EL_TELLTC:
250                         argv[0] = "telltc";
251                         rv = term_telltc(el, i, argv);
252                         break;
253
254                 case EL_SETTC:
255                         argv[0] = "settc";
256                         rv = term_settc(el, i, argv);
257                         break;
258
259                 case EL_ECHOTC:
260                         argv[0] = "echotc";
261                         rv = term_echotc(el, i, argv);
262                         break;
263
264                 case EL_SETTY:
265                         argv[0] = "setty";
266                         rv = tty_stty(el, i, argv);
267                         break;
268
269                 default:
270                         rv = -1;
271                         EL_ABORT((el->el_errfile, "Bad op %d\n", op));
272                         break;
273                 }
274                 break;
275         }
276
277         case EL_ADDFN:
278         {
279                 char *name = va_arg(va, char *);
280                 char *help = va_arg(va, char *);
281                 el_func_t func = va_arg(va, el_func_t);
282
283                 rv = map_addfunc(el, name, help, func);
284                 break;
285         }
286
287         case EL_HIST:
288         {
289                 hist_fun_t func = va_arg(va, hist_fun_t);
290                 ptr_t ptr = va_arg(va, char *);
291
292                 rv = hist_set(el, func, ptr);
293                 break;
294         }
295
296         case EL_EDITMODE:
297                 if (va_arg(va, int))
298                         el->el_flags &= ~EDIT_DISABLED;
299                 else
300                         el->el_flags |= EDIT_DISABLED;
301                 rv = 0;
302                 break;
303
304         default:
305                 rv = -1;
306         }
307
308         va_end(va);
309         return (rv);
310 }
311
312
313 /* el_get():
314  *      retrieve the editline parameters
315  */
316 public int
317 el_get(EditLine *el, int op, void *ret)
318 {
319         int rv;
320         union {
321                 void *vptr;
322                 const char *cptr;
323                 el_pfunc_t elpf;
324                 el_printffunc_t eprintff;
325                 el_putcfunc_t eputcf;
326                 el_flushfunc_t eflushf;
327         } vret;
328
329         vret.vptr = ret;
330         if (el == NULL || ret == NULL)
331                 return (-1);
332         switch (op) {
333         case EL_PROMPT:
334         case EL_RPROMPT:
335                 rv = prompt_get(el, &vret.elpf, op);
336                 break;
337
338         case EL_ERRPRINTFFN:
339                 *((el_printffunc_t *)ret) = el->el_err_printf;
340                 rv = 0;
341                 break;
342
343         case EL_STDPRINTFFN:
344                 *((el_printffunc_t *)ret) = el->el_std_printf;
345                 rv = 0;
346                 break;
347
348         case EL_STDPUTCFN:
349                 *((el_putcfunc_t *)ret) = el->el_std_putc;
350                 rv = 0;
351                 break;
352
353         case EL_STDFLUSHFN:
354                 *((el_flushfunc_t *)ret) = el->el_std_flush;
355                 rv = 0;
356                 break;
357
358         case EL_USERDATA:
359                 *((void **)ret) = el->el_userdata;
360                 rv = 0;
361                 break;
362
363         case EL_EDITOR:
364                 rv = map_get_editor(el, &vret.cptr);
365                 break;
366
367         case EL_SIGNAL:
368                 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
369                 rv = 0;
370                 break;
371
372         case EL_EDITMODE:
373                 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
374                 rv = 0;
375                 break;
376
377 #if 0                           /* XXX */
378         case EL_TERMINAL:
379                 rv = term_get(el, (const char *) &ret);
380                 break;
381
382         case EL_BIND:
383         case EL_TELLTC:
384         case EL_SETTC:
385         case EL_ECHOTC:
386         case EL_SETTY:
387         {
388                 char *argv[20];
389                 int i;
390
391                 for (i = 1; i < 20; i++)
392                         if ((argv[i] = va_arg(va, char *)) == NULL)
393                                 break;
394
395                 switch (op) {
396                 case EL_BIND:
397                         argv[0] = "bind";
398                         rv = map_bind(el, i, argv);
399                         break;
400
401                 case EL_TELLTC:
402                         argv[0] = "telltc";
403                         rv = term_telltc(el, i, argv);
404                         break;
405
406                 case EL_SETTC:
407                         argv[0] = "settc";
408                         rv = term_settc(el, i, argv);
409                         break;
410
411                 case EL_ECHOTC:
412                         argv[0] = "echotc";
413                         rv = term_echotc(el, i, argv);
414                         break;
415
416                 case EL_SETTY:
417                         argv[0] = "setty";
418                         rv = tty_stty(el, i, argv);
419                         break;
420
421                 default:
422                         rv = -1;
423                         EL_ABORT((el->errfile, "Bad op %d\n", op));
424                         break;
425                 }
426                 break;
427         }
428
429         case EL_ADDFN:
430         {
431                 char *name = va_arg(va, char *);
432                 char *help = va_arg(va, char *);
433                 el_func_t func = va_arg(va, el_func_t);
434
435                 rv = map_addfunc(el, name, help, func);
436                 break;
437         }
438
439         case EL_HIST:
440                 {
441                         hist_fun_t func = va_arg(va, hist_fun_t);
442                         ptr_t ptr = va_arg(va, char *);
443                         rv = hist_set(el, func, ptr);
444                 }
445                 break;
446 #endif /* XXX */
447
448         default:
449                 rv = -1;
450         }
451
452         return (rv);
453 }
454
455
456 /* el_line():
457  *      Return editing info
458  */
459 public const LineInfo *
460 el_line(EditLine *el)
461 {
462
463         return (const LineInfo *) (void *) &el->el_line;
464 }
465
466 static const char elpath[] = "/.editrc";
467
468 /* el_source():
469  *      Source a file
470  */
471 public int
472 el_source(EditLine *el, const char *fname)
473 {
474         FILE *fp;
475         size_t len;
476         char *ptr, path[MAXPATHLEN];
477
478         fp = NULL;
479         if (fname == NULL) {
480                 if (issetugid())
481                         return (-1);
482 #if _WIN32
483                 if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) {
484                         snprintf(path, sizeof(path), "%s%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH"), elpath);
485                         fname = path;
486                 }
487 #else
488                 if ((ptr = getenv("HOME")) == NULL)
489                         return (-1);
490                 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
491                         return (-1);
492                 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
493                         return (-1);
494                 fname = path;
495 #endif
496         }
497         if (fname == NULL)
498                 return -1;
499         if (fp == NULL)
500                 fp = fopen(fname, "r");
501         if (fp == NULL) {
502                 return (-1);
503         }
504
505         while ((ptr = fgetln(fp, &len)) != NULL) {
506                 if (len > 0 && ptr[len - 1] == '\n')
507                         --len;
508                 ptr[len] = '\0';
509                 if (parse_line(el, ptr) == -1) {
510                         (void) fclose(fp);
511                         return (-1);
512                 }
513         }
514
515         (void) fclose(fp);
516         return (0);
517 }
518
519
520 /* el_resize():
521  *      Called from program when terminal is resized
522  */
523 public void
524 el_resize(EditLine *el)
525 {
526         int lins, cols;
527 #if !_MSC_VER
528         sigset_t oset, nset;
529
530         (void) sigemptyset(&nset);
531         (void) sigaddset(&nset, SIGWINCH);
532         (void) sigprocmask(SIG_BLOCK, &nset, &oset);
533 #endif
534
535         /* get the correct window size */
536         if (term_get_size(el, &lins, &cols))
537                 term_change_size(el, lins, cols);
538
539 #if !_MSC_VER
540         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
541 #endif
542 }
543
544
545 /* el_beep():
546  *      Called from the program to beep
547  */
548 public void
549 el_beep(EditLine *el)
550 {
551
552         term_beep(el);
553 }
554
555
556 /* el_editmode()
557  *      Set the state of EDIT_DISABLED from the `edit' command.
558  */
559 protected int
560 /*ARGSUSED*/
561 el_editmode(EditLine *el, int argc, char **argv)
562 {
563         const char *how;
564
565         if (argv == NULL || argc != 2 || argv[1] == NULL)
566                 return (-1);
567
568         how = argv[1];
569         if (strcmp(how, "on") == 0)
570                 el->el_flags &= ~EDIT_DISABLED;
571         else if (strcmp(how, "off") == 0)
572                 el->el_flags |= EDIT_DISABLED;
573         else {
574                 (void) el->el_err_printf(el, "edit: Bad value `%s'.\n", how);
575                 return (-1);
576         }
577         return (0);
578 }
579
580 protected int
581 el_err_vprintf(EditLine *el, const char *fmt, va_list arg)
582 {
583         int len, mask;
584         char buffer[1024];
585         len = vsnprintf(buffer, sizeof(buffer), fmt, arg);
586         if(len > sizeof(buffer)) len = sizeof(buffer);
587         if(el->el_err_e)
588                 return el->
589                         el_err_e->
590                         opset->
591                         write(el->el_err_e->fd, buffer, len,
592                                 &mask, el->el_err_e);
593         return write(el->el_errfd, buffer, len);
594 }
595
596 protected int
597 el_err_printf(EditLine *el, const char *fmt, ...)
598 {
599         int len;
600         va_list arg;
601         va_start(arg, fmt);
602         len = el_err_vprintf(el, fmt, arg);
603         va_end(arg);
604         return len;
605 }
606
607 protected int
608 el_std_vprintf(EditLine *el, const char *fmt, va_list arg)
609 {
610         int len, mask;
611         char buffer[1024];
612         len = vsnprintf(buffer, sizeof(buffer), fmt, arg);
613         if(len > sizeof(buffer)) len = sizeof(buffer);
614         if(el->el_out_e)
615                 return el->
616                         el_out_e->
617                         opset->
618                         write(el->el_out_e->fd, buffer,
619                                 len, &mask, el->el_out_e);
620         return write(el->el_outfd, buffer, len);
621 }
622
623 protected int
624 el_std_printf(EditLine *el, const char *fmt, ...)
625 {
626         int len;
627         va_list arg;
628         va_start(arg, fmt);
629         len = el_std_vprintf(el, fmt, arg);
630         va_end(arg);
631         return len;
632 }
633
634 protected int
635 el_std_putc(int i, EditLine *el)
636 {
637         int mask;
638         unsigned char c = i & 0xff;
639         if(el->el_out_e)
640                 return el->
641                         el_out_e->
642                         opset->
643                         write(el->el_out_e->fd, &c,
644                                 1, &mask, el->el_out_e);
645         return write(el->el_outfd, &c, 1);
646 }
647 protected int
648 el_std_flush(EditLine *el)
649 {
650         return 0;
651 }
Note: See TracBrowser for help on using the browser.