File: | src/lib/libedit/el.c |
Warning: | line 247, column 4 Value stored to 'rv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: el.c,v 1.38 2023/03/08 04:43:05 guenther Exp $ */ |
2 | /* $NetBSD: el.c,v 1.61 2011/01/27 23:11:40 christos Exp $ */ |
3 | |
4 | /*- |
5 | * Copyright (c) 1992, 1993 |
6 | * The Regents of the University of California. All rights reserved. |
7 | * |
8 | * This code is derived from software contributed to Berkeley by |
9 | * Christos Zoulas of Cornell University. |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. |
19 | * 3. Neither the name of the University nor the names of its contributors |
20 | * may be used to endorse or promote products derived from this software |
21 | * without specific prior written permission. |
22 | * |
23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
33 | * SUCH DAMAGE. |
34 | */ |
35 | |
36 | #include "config.h" |
37 | |
38 | /* |
39 | * el.c: EditLine interface functions |
40 | */ |
41 | #include <sys/types.h> |
42 | #include <ctype.h> |
43 | #include <langinfo.h> |
44 | #include <limits.h> |
45 | #include <locale.h> |
46 | #include <stdarg.h> |
47 | #include <stdlib.h> |
48 | #include <string.h> |
49 | |
50 | #include "el.h" |
51 | #include "parse.h" |
52 | #include "read.h" |
53 | |
54 | /* el_init(): |
55 | * Initialize editline and set default parameters. |
56 | */ |
57 | EditLine * |
58 | el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) |
59 | { |
60 | EditLine *el = (EditLine *) calloc(1, sizeof(EditLine)); |
61 | |
62 | if (el == NULL((void *)0)) |
63 | return NULL((void *)0); |
64 | |
65 | el->el_infile = fin; |
66 | el->el_outfile = fout; |
67 | el->el_errfile = ferr; |
68 | |
69 | el->el_infd = fileno(fin)(!__isthreaded ? ((fin)->_file) : (fileno)(fin)); |
70 | el->el_outfd = fileno(fout)(!__isthreaded ? ((fout)->_file) : (fileno)(fout)); |
71 | el->el_errfd = fileno(ferr)(!__isthreaded ? ((ferr)->_file) : (fileno)(ferr)); |
72 | |
73 | el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch)); |
74 | if (el->el_prog == NULL((void *)0)) { |
75 | free(el); |
76 | return NULL((void *)0); |
77 | } |
78 | |
79 | /* |
80 | * Initialize all the modules. Order is important!!! |
81 | */ |
82 | el->el_flags = 0; |
83 | if (setlocale(LC_CTYPE2, NULL((void *)0)) != NULL((void *)0)){ |
84 | if (strcmp(nl_langinfo(CODESET51), "UTF-8") == 0) |
85 | el->el_flags |= CHARSET_IS_UTF80x10; |
86 | } |
87 | |
88 | if (terminal_init(el) == -1) { |
89 | free(el->el_prog); |
90 | free(el); |
91 | return NULL((void *)0); |
92 | } |
93 | (void) keymacro_init(el); |
94 | (void) map_init(el); |
95 | if (tty_init(el) == -1) |
96 | el->el_flags |= NO_TTY0x02; |
97 | (void) ch_init(el); |
98 | (void) search_init(el); |
99 | (void) hist_init(el); |
100 | (void) prompt_init(el); |
101 | (void) sig_init(el); |
102 | if (read_init(el) == -1) { |
103 | el_end(el); |
104 | return NULL((void *)0); |
105 | } |
106 | return el; |
107 | } |
108 | |
109 | |
110 | /* el_end(): |
111 | * Clean up. |
112 | */ |
113 | void |
114 | el_end(EditLine *el) |
115 | { |
116 | |
117 | if (el == NULL((void *)0)) |
118 | return; |
119 | |
120 | el_reset(el); |
121 | |
122 | terminal_end(el); |
123 | keymacro_end(el); |
124 | map_end(el); |
125 | tty_end(el); |
126 | ch_end(el); |
127 | read_end(el->el_read); |
128 | search_end(el); |
129 | hist_end(el); |
130 | prompt_end(el); |
131 | sig_end(el); |
132 | |
133 | free(el->el_prog); |
134 | free(el->el_scratch.cbuff); |
135 | free(el->el_scratch.wbuff); |
136 | free(el->el_lgcyconv.cbuff); |
137 | free(el->el_lgcyconv.wbuff); |
138 | free(el); |
139 | } |
140 | |
141 | |
142 | /* el_reset(): |
143 | * Reset the tty and the parser |
144 | */ |
145 | void |
146 | el_reset(EditLine *el) |
147 | { |
148 | |
149 | tty_cookedmode(el); |
150 | ch_reset(el); /* XXX: Do we want that? */ |
151 | } |
152 | |
153 | |
154 | /* el_set(): |
155 | * set the editline parameters |
156 | */ |
157 | int |
158 | el_wset(EditLine *el, int op, ...) |
159 | { |
160 | va_list ap; |
161 | int rv = 0; |
162 | |
163 | if (el == NULL((void *)0)) |
164 | return -1; |
165 | va_start(ap, op)__builtin_va_start((ap), op); |
166 | |
167 | switch (op) { |
168 | case EL_PROMPT0: |
169 | case EL_RPROMPT12: { |
170 | el_pfunc_t p = va_arg(ap, el_pfunc_t)__builtin_va_arg((ap), el_pfunc_t); |
171 | |
172 | rv = prompt_set(el, p, 0, op, 1); |
173 | break; |
174 | } |
175 | |
176 | case EL_RESIZE23: { |
177 | el_zfunc_t p = va_arg(ap, el_zfunc_t)__builtin_va_arg((ap), el_zfunc_t); |
178 | void *arg = va_arg(ap, void *)__builtin_va_arg((ap), void *); |
179 | rv = ch_resizefun(el, p, arg); |
180 | break; |
181 | } |
182 | |
183 | case EL_PROMPT_ESC21: |
184 | case EL_RPROMPT_ESC22: { |
185 | el_pfunc_t p = va_arg(ap, el_pfunc_t)__builtin_va_arg((ap), el_pfunc_t); |
186 | int c = va_arg(ap, int)__builtin_va_arg((ap), int); |
187 | |
188 | rv = prompt_set(el, p, c, op, 1); |
189 | break; |
190 | } |
191 | |
192 | case EL_TERMINAL1: |
193 | rv = terminal_set(el, va_arg(ap, char *)__builtin_va_arg((ap), char *)); |
194 | break; |
195 | |
196 | case EL_EDITOR2: |
197 | rv = map_set_editor(el, va_arg(ap, wchar_t *)__builtin_va_arg((ap), wchar_t *)); |
198 | break; |
199 | |
200 | case EL_SIGNAL3: |
201 | if (va_arg(ap, int)__builtin_va_arg((ap), int)) |
202 | el->el_flags |= HANDLE_SIGNALS0x01; |
203 | else |
204 | el->el_flags &= ~HANDLE_SIGNALS0x01; |
205 | break; |
206 | |
207 | case EL_BIND4: |
208 | case EL_TELLTC5: |
209 | case EL_SETTC6: |
210 | case EL_ECHOTC7: |
211 | case EL_SETTY8: |
212 | { |
213 | const wchar_t *argv[20]; |
214 | int i; |
215 | |
216 | for (i = 1; i < 20; i++) |
217 | if ((argv[i] = va_arg(ap, wchar_t *)__builtin_va_arg((ap), wchar_t *)) == NULL((void *)0)) |
218 | break; |
219 | |
220 | switch (op) { |
221 | case EL_BIND4: |
222 | argv[0] = L"bind"; |
223 | rv = map_bind(el, i, argv); |
224 | break; |
225 | |
226 | case EL_TELLTC5: |
227 | argv[0] = L"telltc"; |
228 | rv = terminal_telltc(el, i, argv); |
229 | break; |
230 | |
231 | case EL_SETTC6: |
232 | argv[0] = L"settc"; |
233 | rv = terminal_settc(el, i, argv); |
234 | break; |
235 | |
236 | case EL_ECHOTC7: |
237 | argv[0] = L"echotc"; |
238 | rv = terminal_echotc(el, i, argv); |
239 | break; |
240 | |
241 | case EL_SETTY8: |
242 | argv[0] = L"setty"; |
243 | rv = tty_stty(el, i, argv); |
244 | break; |
245 | |
246 | default: |
247 | rv = -1; |
Value stored to 'rv' is never read | |
248 | EL_ABORT((el->el_errfile, "Bad op %d\n", op))abort(); |
249 | break; |
250 | } |
251 | break; |
252 | } |
253 | |
254 | case EL_ADDFN9: |
255 | { |
256 | wchar_t *name = va_arg(ap, wchar_t *)__builtin_va_arg((ap), wchar_t *); |
257 | wchar_t *help = va_arg(ap, wchar_t *)__builtin_va_arg((ap), wchar_t *); |
258 | el_func_t func = va_arg(ap, el_func_t)__builtin_va_arg((ap), el_func_t); |
259 | |
260 | rv = map_addfunc(el, name, help, func); |
261 | break; |
262 | } |
263 | |
264 | case EL_HIST10: |
265 | { |
266 | hist_fun_t func = va_arg(ap, hist_fun_t)__builtin_va_arg((ap), hist_fun_t); |
267 | void *ptr = va_arg(ap, void *)__builtin_va_arg((ap), void *); |
268 | |
269 | rv = hist_set(el, func, ptr); |
270 | if (!(el->el_flags & CHARSET_IS_UTF80x10)) |
271 | el->el_flags &= ~NARROW_HISTORY0x40; |
272 | break; |
273 | } |
274 | |
275 | case EL_EDITMODE11: |
276 | if (va_arg(ap, int)__builtin_va_arg((ap), int)) |
277 | el->el_flags &= ~EDIT_DISABLED0x04; |
278 | else |
279 | el->el_flags |= EDIT_DISABLED0x04; |
280 | rv = 0; |
281 | break; |
282 | |
283 | case EL_GETCFN13: |
284 | { |
285 | el_rfunc_t rc = va_arg(ap, el_rfunc_t)__builtin_va_arg((ap), el_rfunc_t); |
286 | rv = el_read_setfn(el->el_read, rc); |
287 | break; |
288 | } |
289 | |
290 | case EL_CLIENTDATA14: |
291 | el->el_data = va_arg(ap, void *)__builtin_va_arg((ap), void *); |
292 | break; |
293 | |
294 | case EL_UNBUFFERED15: |
295 | rv = va_arg(ap, int)__builtin_va_arg((ap), int); |
296 | if (rv && !(el->el_flags & UNBUFFERED0x08)) { |
297 | el->el_flags |= UNBUFFERED0x08; |
298 | read_prepare(el); |
299 | } else if (!rv && (el->el_flags & UNBUFFERED0x08)) { |
300 | el->el_flags &= ~UNBUFFERED0x08; |
301 | read_finish(el); |
302 | } |
303 | rv = 0; |
304 | break; |
305 | |
306 | case EL_PREP_TERM16: |
307 | rv = va_arg(ap, int)__builtin_va_arg((ap), int); |
308 | if (rv) |
309 | (void) tty_rawmode(el); |
310 | else |
311 | (void) tty_cookedmode(el); |
312 | rv = 0; |
313 | break; |
314 | |
315 | case EL_SETFP19: |
316 | { |
317 | FILE *fp; |
318 | int what; |
319 | |
320 | what = va_arg(ap, int)__builtin_va_arg((ap), int); |
321 | fp = va_arg(ap, FILE *)__builtin_va_arg((ap), FILE *); |
322 | |
323 | rv = 0; |
324 | switch (what) { |
325 | case 0: |
326 | el->el_infile = fp; |
327 | el->el_infd = fileno(fp)(!__isthreaded ? ((fp)->_file) : (fileno)(fp)); |
328 | break; |
329 | case 1: |
330 | el->el_outfile = fp; |
331 | el->el_outfd = fileno(fp)(!__isthreaded ? ((fp)->_file) : (fileno)(fp)); |
332 | break; |
333 | case 2: |
334 | el->el_errfile = fp; |
335 | el->el_errfd = fileno(fp)(!__isthreaded ? ((fp)->_file) : (fileno)(fp)); |
336 | break; |
337 | default: |
338 | rv = -1; |
339 | break; |
340 | } |
341 | break; |
342 | } |
343 | |
344 | case EL_REFRESH20: |
345 | re_clear_display(el); |
346 | re_refresh(el); |
347 | terminal__flush(el); |
348 | break; |
349 | |
350 | default: |
351 | rv = -1; |
352 | break; |
353 | } |
354 | |
355 | va_end(ap)__builtin_va_end((ap)); |
356 | return rv; |
357 | } |
358 | |
359 | |
360 | /* el_get(): |
361 | * retrieve the editline parameters |
362 | */ |
363 | int |
364 | el_wget(EditLine *el, int op, ...) |
365 | { |
366 | va_list ap; |
367 | int rv; |
368 | |
369 | if (el == NULL((void *)0)) |
370 | return -1; |
371 | |
372 | va_start(ap, op)__builtin_va_start((ap), op); |
373 | |
374 | switch (op) { |
375 | case EL_PROMPT0: |
376 | case EL_RPROMPT12: { |
377 | el_pfunc_t *p = va_arg(ap, el_pfunc_t *)__builtin_va_arg((ap), el_pfunc_t *); |
378 | rv = prompt_get(el, p, 0, op); |
379 | break; |
380 | } |
381 | case EL_PROMPT_ESC21: |
382 | case EL_RPROMPT_ESC22: { |
383 | el_pfunc_t *p = va_arg(ap, el_pfunc_t *)__builtin_va_arg((ap), el_pfunc_t *); |
384 | wchar_t *c = va_arg(ap, wchar_t *)__builtin_va_arg((ap), wchar_t *); |
385 | |
386 | rv = prompt_get(el, p, c, op); |
387 | break; |
388 | } |
389 | |
390 | case EL_EDITOR2: |
391 | rv = map_get_editor(el, va_arg(ap, const wchar_t **)__builtin_va_arg((ap), const wchar_t **)); |
392 | break; |
393 | |
394 | case EL_SIGNAL3: |
395 | *va_arg(ap, int *)__builtin_va_arg((ap), int *) = (el->el_flags & HANDLE_SIGNALS0x01); |
396 | rv = 0; |
397 | break; |
398 | |
399 | case EL_EDITMODE11: |
400 | *va_arg(ap, int *)__builtin_va_arg((ap), int *) = !(el->el_flags & EDIT_DISABLED0x04); |
401 | rv = 0; |
402 | break; |
403 | |
404 | case EL_TERMINAL1: |
405 | terminal_get(el, va_arg(ap, const char **)__builtin_va_arg((ap), const char **)); |
406 | rv = 0; |
407 | break; |
408 | |
409 | case EL_GETTC17: |
410 | { |
411 | static char name[] = "gettc"; |
412 | char *argv[20]; |
413 | int i; |
414 | |
415 | for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++) |
416 | if ((argv[i] = va_arg(ap, char *)__builtin_va_arg((ap), char *)) == NULL((void *)0)) |
417 | break; |
418 | |
419 | switch (op) { |
420 | case EL_GETTC17: |
421 | argv[0] = name; |
422 | rv = terminal_gettc(el, i, argv); |
423 | break; |
424 | |
425 | default: |
426 | rv = -1; |
427 | EL_ABORT((el->el_errfile, "Bad op %d\n", op))abort(); |
428 | break; |
429 | } |
430 | break; |
431 | } |
432 | |
433 | case EL_GETCFN13: |
434 | *va_arg(ap, el_rfunc_t *)__builtin_va_arg((ap), el_rfunc_t *) = el_read_getfn(el->el_read); |
435 | rv = 0; |
436 | break; |
437 | |
438 | case EL_CLIENTDATA14: |
439 | *va_arg(ap, void **)__builtin_va_arg((ap), void **) = el->el_data; |
440 | rv = 0; |
441 | break; |
442 | |
443 | case EL_UNBUFFERED15: |
444 | *va_arg(ap, int *)__builtin_va_arg((ap), int *) = (!(el->el_flags & UNBUFFERED0x08)); |
445 | rv = 0; |
446 | break; |
447 | |
448 | case EL_GETFP18: |
449 | { |
450 | int what; |
451 | FILE **fpp; |
452 | |
453 | what = va_arg(ap, int)__builtin_va_arg((ap), int); |
454 | fpp = va_arg(ap, FILE **)__builtin_va_arg((ap), FILE **); |
455 | rv = 0; |
456 | switch (what) { |
457 | case 0: |
458 | *fpp = el->el_infile; |
459 | break; |
460 | case 1: |
461 | *fpp = el->el_outfile; |
462 | break; |
463 | case 2: |
464 | *fpp = el->el_errfile; |
465 | break; |
466 | default: |
467 | rv = -1; |
468 | break; |
469 | } |
470 | break; |
471 | } |
472 | default: |
473 | rv = -1; |
474 | break; |
475 | } |
476 | va_end(ap)__builtin_va_end((ap)); |
477 | |
478 | return rv; |
479 | } |
480 | |
481 | |
482 | /* el_line(): |
483 | * Return editing info |
484 | */ |
485 | const LineInfoW * |
486 | el_wline(EditLine *el) |
487 | { |
488 | |
489 | return (const LineInfoW *)(void *)&el->el_line; |
490 | } |
491 | |
492 | |
493 | /* el_source(): |
494 | * Source a file |
495 | */ |
496 | int |
497 | el_source(EditLine *el, const char *fname) |
498 | { |
499 | FILE *fp; |
500 | size_t len; |
501 | ssize_t slen; |
502 | char *ptr; |
503 | #ifdef HAVE_ISSETUGID1 |
504 | char path[PATH_MAX1024]; |
505 | #endif |
506 | const wchar_t *dptr; |
507 | |
508 | fp = NULL((void *)0); |
509 | if (fname == NULL((void *)0)) { |
510 | #ifdef HAVE_ISSETUGID1 |
511 | static const char elpath[] = "/.editrc"; |
512 | |
513 | if (issetugid()) |
514 | return -1; |
515 | if ((ptr = getenv("HOME")) == NULL((void *)0)) |
516 | return -1; |
517 | if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) |
518 | return -1; |
519 | if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) |
520 | return -1; |
521 | fname = path; |
522 | #else |
523 | /* |
524 | * If issetugid() is missing, always return an error, in order |
525 | * to keep from inadvertently opening up the user to a security |
526 | * hole. |
527 | */ |
528 | return -1; |
529 | #endif |
530 | } |
531 | if (fp == NULL((void *)0)) |
532 | fp = fopen(fname, "r"); |
533 | if (fp == NULL((void *)0)) |
534 | return -1; |
535 | |
536 | ptr = NULL((void *)0); |
537 | len = 0; |
538 | while ((slen = getline(&ptr, &len, fp)) != -1) { |
539 | if (*ptr == '\n') |
540 | continue; /* Empty line. */ |
541 | if (slen > 0 && ptr[--slen] == '\n') |
542 | ptr[slen] = '\0'; |
543 | |
544 | dptr = ct_decode_string(ptr, &el->el_scratch); |
545 | if (!dptr) |
546 | continue; |
547 | /* loop until first non-space char or EOL */ |
548 | while (*dptr != '\0' && iswspace(*dptr)) |
549 | dptr++; |
550 | if (*dptr == '#') |
551 | continue; /* ignore, this is a comment line */ |
552 | if (parse_line(el, dptr) == -1) { |
553 | free(ptr); |
554 | (void) fclose(fp); |
555 | return -1; |
556 | } |
557 | } |
558 | free(ptr); |
559 | (void) fclose(fp); |
560 | return 0; |
561 | } |
562 | |
563 | |
564 | /* el_resize(): |
565 | * Called from program when terminal is resized |
566 | */ |
567 | void |
568 | el_resize(EditLine *el) |
569 | { |
570 | int lins, cols; |
571 | sigset_t oset, nset; |
572 | |
573 | (void) sigemptyset(&nset); |
574 | (void) sigaddset(&nset, SIGWINCH28); |
575 | (void) sigprocmask(SIG_BLOCK1, &nset, &oset); |
576 | |
577 | /* get the correct window size */ |
578 | if (terminal_get_size(el, &lins, &cols)) |
579 | terminal_change_size(el, lins, cols); |
580 | |
581 | (void) sigprocmask(SIG_SETMASK3, &oset, NULL((void *)0)); |
582 | } |
583 | |
584 | |
585 | /* el_beep(): |
586 | * Called from the program to beep |
587 | */ |
588 | void |
589 | el_beep(EditLine *el) |
590 | { |
591 | |
592 | terminal_beep(el); |
593 | } |
594 | |
595 | |
596 | /* el_editmode() |
597 | * Set the state of EDIT_DISABLED from the `edit' command. |
598 | */ |
599 | protected__attribute__((__visibility__("hidden"))) int |
600 | el_editmode(EditLine *el, int argc, const wchar_t **argv) |
601 | { |
602 | const wchar_t *how; |
603 | |
604 | if (argv == NULL((void *)0) || argc != 2 || argv[1] == NULL((void *)0)) |
605 | return -1; |
606 | |
607 | how = argv[1]; |
608 | if (wcscmp(how, L"on") == 0) { |
609 | el->el_flags &= ~EDIT_DISABLED0x04; |
610 | tty_rawmode(el); |
611 | } else if (wcscmp(how, L"off") == 0) { |
612 | tty_cookedmode(el); |
613 | el->el_flags |= EDIT_DISABLED0x04; |
614 | } |
615 | else { |
616 | (void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n", |
617 | how); |
618 | return -1; |
619 | } |
620 | return 0; |
621 | } |