root/src/noitedit/el.c

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

dead assignments, refs #283

  • 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                         EL_ABORT((el->el_errfile, "Bad op %d\n", op));
271                         break;
272                 }
273                 break;
274         }
275
276         case EL_ADDFN:
277         {
278                 char *name = va_arg(va, char *);
279                 char *help = va_arg(va, char *);
280                 el_func_t func = va_arg(va, el_func_t);
281
282                 rv = map_addfunc(el, name, help, func);
283                 break;
284         }
285
286         case EL_HIST:
287         {
288                 hist_fun_t func = va_arg(va, hist_fun_t);
289                 ptr_t ptr = va_arg(va, char *);
290
291                 rv = hist_set(el, func, ptr);
292                 break;
293         }
294
295         case EL_EDITMODE:
296                 if (va_arg(va, int))
297                         el->el_flags &= ~EDIT_DISABLED;
298                 else
299                         el->el_flags |= EDIT_DISABLED;
300                 rv = 0;
301                 break;
302
303         default:
304                 rv = -1;
305         }
306
307         va_end(va);
308         return (rv);
309 }
310
311
312 /* el_get():
313  *      retrieve the editline parameters
314  */
315 public int
316 el_get(EditLine *el, int op, void *ret)
317 {
318         int rv;
319         union {
320                 void *vptr;
321                 const char *cptr;
322                 el_pfunc_t elpf;
323                 el_printffunc_t eprintff;
324                 el_putcfunc_t eputcf;
325                 el_flushfunc_t eflushf;
326         } vret;
327
328         vret.vptr = ret;
329         if (el == NULL || ret == NULL)
330                 return (-1);
331         switch (op) {
332         case EL_PROMPT:
333         case EL_RPROMPT:
334                 rv = prompt_get(el, &vret.elpf, op);
335                 break;
336
337         case EL_ERRPRINTFFN:
338                 *((el_printffunc_t *)ret) = el->el_err_printf;
339                 rv = 0;
340                 break;
341
342         case EL_STDPRINTFFN:
343                 *((el_printffunc_t *)ret) = el->el_std_printf;
344                 rv = 0;
345                 break;
346
347         case EL_STDPUTCFN:
348                 *((el_putcfunc_t *)ret) = el->el_std_putc;
349                 rv = 0;
350                 break;
351
352         case EL_STDFLUSHFN:
353                 *((el_flushfunc_t *)ret) = el->el_std_flush;
354                 rv = 0;
355                 break;
356
357         case EL_USERDATA:
358                 *((void **)ret) = el->el_userdata;
359                 rv = 0;
360                 break;
361
362         case EL_EDITOR:
363                 rv = map_get_editor(el, &vret.cptr);
364                 break;
365
366         case EL_SIGNAL:
367                 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
368                 rv = 0;
369                 break;
370
371         case EL_EDITMODE:
372                 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
373                 rv = 0;
374                 break;
375
376 #if 0                           /* XXX */
377         case EL_TERMINAL:
378                 rv = term_get(el, (const char *) &ret);
379                 break;
380
381         case EL_BIND:
382         case EL_TELLTC:
383         case EL_SETTC:
384         case EL_ECHOTC:
385         case EL_SETTY:
386         {
387                 char *argv[20];
388                 int i;
389
390                 for (i = 1; i < 20; i++)
391                         if ((argv[i] = va_arg(va, char *)) == NULL)
392                                 break;
393
394                 switch (op) {
395                 case EL_BIND:
396                         argv[0] = "bind";
397                         rv = map_bind(el, i, argv);
398                         break;
399
400                 case EL_TELLTC:
401                         argv[0] = "telltc";
402                         rv = term_telltc(el, i, argv);
403                         break;
404
405                 case EL_SETTC:
406                         argv[0] = "settc";
407                         rv = term_settc(el, i, argv);
408                         break;
409
410                 case EL_ECHOTC:
411                         argv[0] = "echotc";
412                         rv = term_echotc(el, i, argv);
413                         break;
414
415                 case EL_SETTY:
416                         argv[0] = "setty";
417                         rv = tty_stty(el, i, argv);
418                         break;
419
420                 default:
421                         rv = -1;
422                         EL_ABORT((el->errfile, "Bad op %d\n", op));
423                         break;
424                 }
425                 break;
426         }
427
428         case EL_ADDFN:
429         {
430                 char *name = va_arg(va, char *);
431                 char *help = va_arg(va, char *);
432                 el_func_t func = va_arg(va, el_func_t);
433
434                 rv = map_addfunc(el, name, help, func);
435                 break;
436         }
437
438         case EL_HIST:
439                 {
440                         hist_fun_t func = va_arg(va, hist_fun_t);
441                         ptr_t ptr = va_arg(va, char *);
442                         rv = hist_set(el, func, ptr);
443                 }
444                 break;
445 #endif /* XXX */
446
447         default:
448                 rv = -1;
449         }
450
451         return (rv);
452 }
453
454
455 /* el_line():
456  *      Return editing info
457  */
458 public const LineInfo *
459 el_line(EditLine *el)
460 {
461
462         return (const LineInfo *) (void *) &el->el_line;
463 }
464
465 static const char elpath[] = "/.editrc";
466
467 /* el_source():
468  *      Source a file
469  */
470 public int
471 el_source(EditLine *el, const char *fname)
472 {
473         FILE *fp;
474         size_t len;
475         char *ptr, path[MAXPATHLEN];
476
477         fp = NULL;
478         if (fname == NULL) {
479                 if (issetugid())
480                         return (-1);
481 #if _WIN32
482                 if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) {
483                         snprintf(path, sizeof(path), "%s%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH"), elpath);
484                         fname = path;
485                 }
486 #else
487                 if ((ptr = getenv("HOME")) == NULL)
488                         return (-1);
489                 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
490                         return (-1);
491                 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
492                         return (-1);
493                 fname = path;
494 #endif
495         }
496         if (fname == NULL)
497                 return -1;
498         if (fp == NULL)
499                 fp = fopen(fname, "r");
500         if (fp == NULL) {
501                 return (-1);
502         }
503
504         while ((ptr = fgetln(fp, &len)) != NULL) {
505                 if (len > 0 && ptr[len - 1] == '\n')
506                         --len;
507                 ptr[len] = '\0';
508                 if (parse_line(el, ptr) == -1) {
509                         (void) fclose(fp);
510                         return (-1);
511                 }
512         }
513
514         (void) fclose(fp);
515         return (0);
516 }
517
518
519 /* el_resize():
520  *      Called from program when terminal is resized
521  */
522 public void
523 el_resize(EditLine *el)
524 {
525         int lins, cols;
526 #if !_MSC_VER
527         sigset_t oset, nset;
528
529         (void) sigemptyset(&nset);
530         (void) sigaddset(&nset, SIGWINCH);
531         (void) sigprocmask(SIG_BLOCK, &nset, &oset);
532 #endif
533
534         /* get the correct window size */
535         if (term_get_size(el, &lins, &cols))
536                 term_change_size(el, lins, cols);
537
538 #if !_MSC_VER
539         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
540 #endif
541 }
542
543
544 /* el_beep():
545  *      Called from the program to beep
546  */
547 public void
548 el_beep(EditLine *el)
549 {
550
551         term_beep(el);
552 }
553
554
555 /* el_editmode()
556  *      Set the state of EDIT_DISABLED from the `edit' command.
557  */
558 protected int
559 /*ARGSUSED*/
560 el_editmode(EditLine *el, int argc, char **argv)
561 {
562         const char *how;
563
564         if (argv == NULL || argc != 2 || argv[1] == NULL)
565                 return (-1);
566
567         how = argv[1];
568         if (strcmp(how, "on") == 0)
569                 el->el_flags &= ~EDIT_DISABLED;
570         else if (strcmp(how, "off") == 0)
571                 el->el_flags |= EDIT_DISABLED;
572         else {
573                 (void) el->el_err_printf(el, "edit: Bad value `%s'.\n", how);
574                 return (-1);
575         }
576         return (0);
577 }
578
579 protected int
580 el_err_vprintf(EditLine *el, const char *fmt, va_list arg)
581 {
582         int len, mask;
583         char buffer[1024];
584         len = vsnprintf(buffer, sizeof(buffer), fmt, arg);
585         if(len > sizeof(buffer)) len = sizeof(buffer);
586         if(el->el_err_e)
587                 return el->
588                         el_err_e->
589                         opset->
590                         write(el->el_err_e->fd, buffer, len,
591                                 &mask, el->el_err_e);
592         return write(el->el_errfd, buffer, len);
593 }
594
595 protected int
596 el_err_printf(EditLine *el, const char *fmt, ...)
597 {
598         int len;
599         va_list arg;
600         va_start(arg, fmt);
601         len = el_err_vprintf(el, fmt, arg);
602         va_end(arg);
603         return len;
604 }
605
606 protected int
607 el_std_vprintf(EditLine *el, const char *fmt, va_list arg)
608 {
609         int len, mask;
610         char buffer[1024];
611         len = vsnprintf(buffer, sizeof(buffer), fmt, arg);
612         if(len > sizeof(buffer)) len = sizeof(buffer);
613         if(el->el_out_e)
614                 return el->
615                         el_out_e->
616                         opset->
617                         write(el->el_out_e->fd, buffer,
618                                 len, &mask, el->el_out_e);
619         return write(el->el_outfd, buffer, len);
620 }
621
622 protected int
623 el_std_printf(EditLine *el, const char *fmt, ...)
624 {
625         int len;
626         va_list arg;
627         va_start(arg, fmt);
628         len = el_std_vprintf(el, fmt, arg);
629         va_end(arg);
630         return len;
631 }
632
633 protected int
634 el_std_putc(int i, EditLine *el)
635 {
636         int mask;
637         unsigned char c = i & 0xff;
638         if(el->el_out_e)
639                 return el->
640                         el_out_e->
641                         opset->
642                         write(el->el_out_e->fd, &c,
643                                 1, &mask, el->el_out_e);
644         return write(el->el_outfd, &c, 1);
645 }
646 protected int
647 el_std_flush(EditLine *el)
648 {
649         return 0;
650 }
Note: See TracBrowser for help on using the browser.