root/src/noitedit/el.c

Revision c55a8e66237e1bd8d22b4497b6f0421472187764, 10.1 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

replace FILE * with fd for errors

  • 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 "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 "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 "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, FILE *fout, int errfd)
87 {
88
89         EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
90 #ifdef DEBUG
91         char *tty;
92 #endif
93
94         if (el == NULL)
95                 return (NULL);
96
97         memset(el, 0, sizeof(EditLine));
98
99         el->el_infd = infd;
100         el->el_outfile = fout;
101         el->el_errfd = errfd;
102         el->el_err_printf = el_err_printf;
103         el->el_prog = strdup(prog);
104
105         /*
106          * Initialize all the modules. Order is important!!!
107          */
108         el->el_flags = 0;
109
110         (void) term_init(el);
111         (void) key_init(el);
112         (void) map_init(el);
113         if (tty_init(el) == -1)
114                 el->el_flags |= NO_TTY;
115         (void) ch_init(el);
116         (void) search_init(el);
117         (void) hist_init(el);
118         (void) prompt_init(el);
119         (void) sig_init(el);
120
121         return (el);
122 }
123
124
125 /* el_end():
126  *      Clean up.
127  */
128 public void
129 el_end(EditLine *el)
130 {
131
132         if (el == NULL)
133                 return;
134
135         el_reset(el);
136
137         term_end(el);
138         key_end(el);
139         map_end(el);
140         tty_end(el);
141         ch_end(el);
142         search_end(el);
143         hist_end(el);
144         prompt_end(el);
145         sig_end(el);
146
147         el_free((ptr_t) el->el_prog);
148         el_free((ptr_t) el);
149 }
150
151
152 /* el_reset():
153  *      Reset the tty and the parser
154  */
155 public void
156 el_reset(EditLine *el)
157 {
158
159         tty_cookedmode(el);
160         ch_reset(el);           /* XXX: Do we want that? */
161 }
162
163
164 /* el_set():
165  *      set the editline parameters
166  */
167 public int
168 el_set(EditLine *el, int op, ...)
169 {
170         va_list va;
171         int rv;
172         va_start(va, op);
173
174         if (el == NULL)
175                 return (-1);
176         switch (op) {
177         case EL_PROMPT:
178         case EL_RPROMPT:
179                 rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
180                 break;
181
182         case EL_TERMINAL:
183                 rv = term_set(el, va_arg(va, char *));
184                 break;
185
186         case EL_EDITOR:
187                 rv = map_set_editor(el, va_arg(va, char *));
188                 break;
189
190         case EL_SIGNAL:
191                 if (va_arg(va, int))
192                         el->el_flags |= HANDLE_SIGNALS;
193                 else
194                         el->el_flags &= ~HANDLE_SIGNALS;
195                 rv = 0;
196                 break;
197
198         case EL_BIND:
199         case EL_TELLTC:
200         case EL_SETTC:
201         case EL_ECHOTC:
202         case EL_SETTY:
203         {
204                 char *argv[20];
205                 int i;
206
207                 for (i = 1; i < 20; i++)
208                         if ((argv[i] = va_arg(va, char *)) == NULL)
209                                 break;
210
211                 switch (op) {
212                 case EL_BIND:
213                         argv[0] = "bind";
214                         rv = map_bind(el, i, argv);
215                         break;
216
217                 case EL_TELLTC:
218                         argv[0] = "telltc";
219                         rv = term_telltc(el, i, argv);
220                         break;
221
222                 case EL_SETTC:
223                         argv[0] = "settc";
224                         rv = term_settc(el, i, argv);
225                         break;
226
227                 case EL_ECHOTC:
228                         argv[0] = "echotc";
229                         rv = term_echotc(el, i, argv);
230                         break;
231
232                 case EL_SETTY:
233                         argv[0] = "setty";
234                         rv = tty_stty(el, i, argv);
235                         break;
236
237                 default:
238                         rv = -1;
239                         EL_ABORT((el->el_errfile, "Bad op %d\n", op));
240                         break;
241                 }
242                 break;
243         }
244
245         case EL_ADDFN:
246         {
247                 char *name = va_arg(va, char *);
248                 char *help = va_arg(va, char *);
249                 el_func_t func = va_arg(va, el_func_t);
250
251                 rv = map_addfunc(el, name, help, func);
252                 break;
253         }
254
255         case EL_HIST:
256         {
257                 hist_fun_t func = va_arg(va, hist_fun_t);
258                 ptr_t ptr = va_arg(va, char *);
259
260                 rv = hist_set(el, func, ptr);
261                 break;
262         }
263
264         case EL_EDITMODE:
265                 if (va_arg(va, int))
266                         el->el_flags &= ~EDIT_DISABLED;
267                 else
268                         el->el_flags |= EDIT_DISABLED;
269                 rv = 0;
270                 break;
271
272         default:
273                 rv = -1;
274         }
275
276         va_end(va);
277         return (rv);
278 }
279
280
281 /* el_get():
282  *      retrieve the editline parameters
283  */
284 public int
285 el_get(EditLine *el, int op, void *ret)
286 {
287         int rv;
288         union {
289                 void *vptr;
290                 const char *cptr;
291                 el_pfunc_t elpf;
292         } vret;
293
294         vret.vptr = ret;
295         if (el == NULL || ret == NULL)
296                 return (-1);
297         switch (op) {
298         case EL_PROMPT:
299         case EL_RPROMPT:
300                 rv = prompt_get(el, &vret.elpf, op);
301                 break;
302
303         case EL_EDITOR:
304                 rv = map_get_editor(el, &vret.cptr);
305                 break;
306
307         case EL_SIGNAL:
308                 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
309                 rv = 0;
310                 break;
311
312         case EL_EDITMODE:
313                 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
314                 rv = 0;
315                 break;
316
317 #if 0                           /* XXX */
318         case EL_TERMINAL:
319                 rv = term_get(el, (const char *) &ret);
320                 break;
321
322         case EL_BIND:
323         case EL_TELLTC:
324         case EL_SETTC:
325         case EL_ECHOTC:
326         case EL_SETTY:
327         {
328                 char *argv[20];
329                 int i;
330
331                 for (i = 1; i < 20; i++)
332                         if ((argv[i] = va_arg(va, char *)) == NULL)
333                                 break;
334
335                 switch (op) {
336                 case EL_BIND:
337                         argv[0] = "bind";
338                         rv = map_bind(el, i, argv);
339                         break;
340
341                 case EL_TELLTC:
342                         argv[0] = "telltc";
343                         rv = term_telltc(el, i, argv);
344                         break;
345
346                 case EL_SETTC:
347                         argv[0] = "settc";
348                         rv = term_settc(el, i, argv);
349                         break;
350
351                 case EL_ECHOTC:
352                         argv[0] = "echotc";
353                         rv = term_echotc(el, i, argv);
354                         break;
355
356                 case EL_SETTY:
357                         argv[0] = "setty";
358                         rv = tty_stty(el, i, argv);
359                         break;
360
361                 default:
362                         rv = -1;
363                         EL_ABORT((el->errfile, "Bad op %d\n", op));
364                         break;
365                 }
366                 break;
367         }
368
369         case EL_ADDFN:
370         {
371                 char *name = va_arg(va, char *);
372                 char *help = va_arg(va, char *);
373                 el_func_t func = va_arg(va, el_func_t);
374
375                 rv = map_addfunc(el, name, help, func);
376                 break;
377         }
378
379         case EL_HIST:
380                 {
381                         hist_fun_t func = va_arg(va, hist_fun_t);
382                         ptr_t ptr = va_arg(va, char *);
383                         rv = hist_set(el, func, ptr);
384                 }
385                 break;
386 #endif /* XXX */
387
388         default:
389                 rv = -1;
390         }
391
392         return (rv);
393 }
394
395
396 /* el_line():
397  *      Return editing info
398  */
399 public const LineInfo *
400 el_line(EditLine *el)
401 {
402
403         return (const LineInfo *) (void *) &el->el_line;
404 }
405
406 static const char elpath[] = "/.editrc";
407
408 /* el_source():
409  *      Source a file
410  */
411 public int
412 el_source(EditLine *el, const char *fname)
413 {
414         FILE *fp;
415         size_t len;
416         char *ptr, path[MAXPATHLEN];
417
418         fp = NULL;
419         if (fname == NULL) {
420                 if (issetugid())
421                         return (-1);
422 #if _WIN32
423                 if (getenv("HOMEDRIVE") && getenv("HOMEPATH")) {
424                         snprintf(path, sizeof(path), "%s%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH"), elpath);
425                         fname = path;
426                 }
427 #else
428                 if ((ptr = getenv("HOME")) == NULL)
429                         return (-1);
430                 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
431                         return (-1);
432                 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
433                         return (-1);
434                 fname = path;
435 #endif
436         }
437         if (fname == NULL)
438                 return -1;
439         if (fp == NULL)
440                 fp = fopen(fname, "r");
441         if (fp == NULL) {
442                 return (-1);
443         }
444
445         while ((ptr = fgetln(fp, &len)) != NULL) {
446                 if (len > 0 && ptr[len - 1] == '\n')
447                         --len;
448                 ptr[len] = '\0';
449                 if (parse_line(el, ptr) == -1) {
450                         (void) fclose(fp);
451                         return (-1);
452                 }
453         }
454
455         (void) fclose(fp);
456         return (0);
457 }
458
459
460 /* el_resize():
461  *      Called from program when terminal is resized
462  */
463 public void
464 el_resize(EditLine *el)
465 {
466         int lins, cols;
467 #if !_MSC_VER
468         sigset_t oset, nset;
469
470         (void) sigemptyset(&nset);
471         (void) sigaddset(&nset, SIGWINCH);
472         (void) sigprocmask(SIG_BLOCK, &nset, &oset);
473 #endif
474
475         /* get the correct window size */
476         if (term_get_size(el, &lins, &cols))
477                 term_change_size(el, lins, cols);
478
479 #if !_MSC_VER
480         (void) sigprocmask(SIG_SETMASK, &oset, NULL);
481 #endif
482 }
483
484
485 /* el_beep():
486  *      Called from the program to beep
487  */
488 public void
489 el_beep(EditLine *el)
490 {
491
492         term_beep(el);
493 }
494
495
496 /* el_editmode()
497  *      Set the state of EDIT_DISABLED from the `edit' command.
498  */
499 protected int
500 /*ARGSUSED*/
501 el_editmode(EditLine *el, int argc, char **argv)
502 {
503         const char *how;
504
505         if (argv == NULL || argc != 2 || argv[1] == NULL)
506                 return (-1);
507
508         how = argv[1];
509         if (strcmp(how, "on") == 0)
510                 el->el_flags &= ~EDIT_DISABLED;
511         else if (strcmp(how, "off") == 0)
512                 el->el_flags |= EDIT_DISABLED;
513         else {
514                 (void) el->el_err_printf(el, "edit: Bad value `%s'.\n", how);
515                 return (-1);
516         }
517         return (0);
518 }
519
520 protected int
521 el_err_vprintf(EditLine *el, char *fmt, va_list arg)
522 {
523         int len;
524         char buffer[1024];
525         len = vsnprintf(buffer, sizeof(buffer), fmt, arg);
526         if(len > sizeof(buffer)) len = sizeof(buffer);
527         len = write(el->el_errfd, buffer, len);
528         return len;
529 }
530
531 protected int
532 el_err_printf(EditLine *el, char *fmt, ...)
533 {
534         int len;
535         va_list arg;
536         va_start(arg, fmt);
537         len = el_err_vprintf(el, fmt, arg);
538         va_end(arg);
539         return len;
540 }
Note: See TracBrowser for help on using the browser.