Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libedit/readline.c
39475 views
1
/* $NetBSD: readline.c,v 1.182 2024/03/26 18:02:04 christos Exp $ */
2
3
/*-
4
* Copyright (c) 1997 The NetBSD Foundation, Inc.
5
* All rights reserved.
6
*
7
* This code is derived from software contributed to The NetBSD Foundation
8
* by Jaromir Dolecek.
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
*
19
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
* POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32
#include "config.h"
33
#if !defined(lint) && !defined(SCCSID)
34
__RCSID("$NetBSD: readline.c,v 1.182 2024/03/26 18:02:04 christos Exp $");
35
#endif /* not lint && not SCCSID */
36
37
#include <sys/types.h>
38
#include <sys/stat.h>
39
#include <ctype.h>
40
#include <dirent.h>
41
#include <errno.h>
42
#include <fcntl.h>
43
#include <limits.h>
44
#include <pwd.h>
45
#include <setjmp.h>
46
#include <stdarg.h>
47
#include <stdint.h>
48
#include <stdio.h>
49
#include <stdlib.h>
50
#include <string.h>
51
#include <unistd.h>
52
#include <vis.h>
53
54
#define completion_matches xxx_completion_matches
55
#include "readline/readline.h"
56
#undef completion_matches
57
#include "el.h"
58
#include "fcns.h"
59
#include "filecomplete.h"
60
61
void rl_prep_terminal(int);
62
void rl_deprep_terminal(void);
63
64
/* for rl_complete() */
65
#define TAB '\r'
66
67
/* see comment at the #ifdef for sense of this */
68
/* #define GDB_411_HACK */
69
70
/* readline compatibility stuff - look at readline sources/documentation */
71
/* to see what these variables mean */
72
const char *rl_library_version = "EditLine wrapper";
73
int rl_readline_version = RL_READLINE_VERSION;
74
static char empty[] = { '\0' };
75
static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
76
static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
77
'>', '<', '=', ';', '|', '&', '{', '(', '\0' };
78
const char *rl_readline_name = empty;
79
FILE *rl_instream = NULL;
80
FILE *rl_outstream = NULL;
81
int rl_point = 0;
82
int rl_end = 0;
83
char *rl_line_buffer = NULL;
84
rl_vcpfunc_t *rl_linefunc = NULL;
85
int rl_done = 0;
86
rl_hook_func_t *rl_event_hook = NULL;
87
KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
88
emacs_meta_keymap,
89
emacs_ctlx_keymap;
90
/*
91
* The following is not implemented; we always catch signals in the
92
* libedit fashion: set handlers on entry to el_gets() and clear them
93
* on the way out. This simplistic approach works for most cases; if
94
* it does not work for your application, please let us know.
95
*/
96
int rl_catch_signals = 1;
97
int rl_catch_sigwinch = 1;
98
99
int history_base = 1; /* probably never subject to change */
100
int history_length = 0;
101
int history_offset = 0;
102
int max_input_history = 0;
103
char history_expansion_char = '!';
104
char history_subst_char = '^';
105
char *history_no_expand_chars = expand_chars;
106
rl_linebuf_func_t *history_inhibit_expansion_function = NULL;
107
char *history_arg_extract(int start, int end, const char *str);
108
109
int rl_inhibit_completion = 0;
110
int rl_attempted_completion_over = 0;
111
const char *rl_basic_word_break_characters = break_chars;
112
char *rl_completer_word_break_characters = NULL;
113
const char *rl_completer_quote_characters = NULL;
114
const char *rl_basic_quote_characters = "\"'";
115
rl_compentry_func_t *rl_completion_entry_function = NULL;
116
char *(*rl_completion_word_break_hook)(void) = NULL;
117
rl_completion_func_t *rl_attempted_completion_function = NULL;
118
rl_hook_func_t *rl_pre_input_hook = NULL;
119
rl_hook_func_t *rl_startup1_hook = NULL;
120
int (*rl_getc_function)(FILE *) = NULL;
121
char *rl_terminal_name = NULL;
122
int rl_already_prompted = 0;
123
int rl_filename_completion_desired = 0;
124
int rl_ignore_completion_duplicates = 0;
125
int readline_echoing_p = 1;
126
int _rl_print_completions_horizontally = 0;
127
rl_voidfunc_t *rl_redisplay_function = NULL;
128
rl_hook_func_t *rl_startup_hook = NULL;
129
rl_compdisp_func_t *rl_completion_display_matches_hook = NULL;
130
rl_vintfunc_t *rl_prep_term_function = (rl_vintfunc_t *)rl_prep_terminal;
131
rl_voidfunc_t *rl_deprep_term_function = (rl_voidfunc_t *)rl_deprep_terminal;
132
KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
133
unsigned long rl_readline_state = RL_STATE_NONE;
134
int _rl_complete_mark_directories;
135
rl_icppfunc_t *rl_directory_completion_hook;
136
int rl_completion_suppress_append;
137
int rl_sort_completion_matches;
138
int _rl_completion_prefix_display_length;
139
int _rl_echoing_p;
140
int history_max_entries;
141
char *rl_display_prompt;
142
int rl_erase_empty_line;
143
144
/*
145
* The current prompt string.
146
*/
147
char *rl_prompt = NULL;
148
char *rl_prompt_saved = NULL;
149
/*
150
* This is set to character indicating type of completion being done by
151
* rl_complete_internal(); this is available for application completion
152
* functions.
153
*/
154
int rl_completion_type = 0;
155
156
/*
157
* If more than this number of items results from query for possible
158
* completions, we ask user if they are sure to really display the list.
159
*/
160
int rl_completion_query_items = 100;
161
162
/*
163
* List of characters which are word break characters, but should be left
164
* in the parsed text when it is passed to the completion function.
165
* Shell uses this to help determine what kind of completing to do.
166
*/
167
const char *rl_special_prefixes = NULL;
168
169
/*
170
* This is the character appended to the completed words if at the end of
171
* the line. Default is ' ' (a space).
172
*/
173
int rl_completion_append_character = ' ';
174
175
/* stuff below is used internally by libedit for readline emulation */
176
177
static History *h = NULL;
178
static EditLine *e = NULL;
179
static rl_command_func_t *map[256];
180
static jmp_buf topbuf;
181
182
/* internal functions */
183
static unsigned char _el_rl_complete(EditLine *, int);
184
static unsigned char _el_rl_tstp(EditLine *, int);
185
static char *_get_prompt(EditLine *);
186
static int _getc_function(EditLine *, wchar_t *);
187
static int _history_expand_command(const char *, size_t, size_t,
188
char **);
189
static char *_rl_compat_sub(const char *, const char *,
190
const char *, int);
191
static int _rl_event_read_char(EditLine *, wchar_t *);
192
static void _rl_update_pos(void);
193
194
static HIST_ENTRY rl_he;
195
196
/* ARGSUSED */
197
static char *
198
_get_prompt(EditLine *el __attribute__((__unused__)))
199
{
200
rl_already_prompted = 1;
201
return rl_prompt;
202
}
203
204
205
/*
206
* read one key from user defined input function
207
*/
208
static int
209
/*ARGSUSED*/
210
_getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c)
211
{
212
int i;
213
214
i = (*rl_getc_function)(rl_instream);
215
if (i == -1)
216
return 0;
217
*c = (wchar_t)i;
218
return 1;
219
}
220
221
static void
222
_resize_fun(EditLine *el, void *a)
223
{
224
const LineInfo *li;
225
const char **ap = a;
226
227
li = el_line(el);
228
*ap = li->buffer;
229
}
230
231
static const char *
232
_default_history_file(void)
233
{
234
struct passwd *p;
235
static char *path;
236
size_t len;
237
238
if (path)
239
return path;
240
241
if ((p = getpwuid(getuid())) == NULL)
242
return NULL;
243
244
len = strlen(p->pw_dir) + sizeof("/.history");
245
if ((path = el_malloc(len)) == NULL)
246
return NULL;
247
248
(void)snprintf(path, len, "%s/.history", p->pw_dir);
249
return path;
250
}
251
252
/*
253
* READLINE compatibility stuff
254
*/
255
256
/*
257
* Set the prompt
258
*/
259
int
260
rl_set_prompt(const char *prompt)
261
{
262
char *p;
263
264
if (!prompt)
265
prompt = "";
266
if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
267
return 0;
268
if (rl_prompt)
269
el_free(rl_prompt);
270
rl_prompt = strdup(prompt);
271
if (rl_prompt == NULL)
272
return -1;
273
274
while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) {
275
/* Remove adjacent end/start markers to avoid double-escapes. */
276
if (p[1] == RL_PROMPT_START_IGNORE) {
277
memmove(p, p + 2, 1 + strlen(p + 2));
278
} else {
279
*p = RL_PROMPT_START_IGNORE;
280
}
281
}
282
283
return 0;
284
}
285
286
void
287
rl_save_prompt(void)
288
{
289
rl_prompt_saved = strdup(rl_prompt);
290
}
291
292
void
293
rl_restore_prompt(void)
294
{
295
if (!rl_prompt_saved)
296
return;
297
rl_prompt = rl_prompt_saved;
298
rl_prompt_saved = NULL;
299
}
300
301
/*
302
* initialize rl compat stuff
303
*/
304
int
305
rl_initialize(void)
306
{
307
HistEvent ev;
308
int editmode = 1;
309
struct termios t;
310
311
if (e != NULL)
312
el_end(e);
313
if (h != NULL)
314
history_end(h);
315
316
RL_UNSETSTATE(RL_STATE_DONE);
317
318
if (!rl_instream)
319
rl_instream = stdin;
320
if (!rl_outstream)
321
rl_outstream = stdout;
322
323
/*
324
* See if we don't really want to run the editor
325
*/
326
if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
327
editmode = 0;
328
329
e = el_init_internal(rl_readline_name, rl_instream, rl_outstream,
330
stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr),
331
NO_RESET);
332
333
if (!editmode)
334
el_set(e, EL_EDITMODE, 0);
335
336
h = history_init();
337
if (!e || !h)
338
return -1;
339
340
history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
341
history_length = 0;
342
max_input_history = INT_MAX;
343
el_set(e, EL_HIST, history, h);
344
345
/* Setup resize function */
346
el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
347
348
/* setup getc function if valid */
349
if (rl_getc_function)
350
el_set(e, EL_GETCFN, _getc_function);
351
352
/* for proper prompt printing in readline() */
353
if (rl_set_prompt("") == -1) {
354
history_end(h);
355
el_end(e);
356
return -1;
357
}
358
el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
359
el_set(e, EL_SIGNAL, rl_catch_signals);
360
361
/* set default mode to "emacs"-style and read setting afterwards */
362
/* so this can be overridden */
363
el_set(e, EL_EDITOR, "emacs");
364
if (rl_terminal_name != NULL)
365
el_set(e, EL_TERMINAL, rl_terminal_name);
366
else
367
el_get(e, EL_TERMINAL, &rl_terminal_name);
368
369
/*
370
* Word completion - this has to go AFTER rebinding keys
371
* to emacs-style.
372
*/
373
el_set(e, EL_ADDFN, "rl_complete",
374
"ReadLine compatible completion function",
375
_el_rl_complete);
376
el_set(e, EL_BIND, "^I", "rl_complete", NULL);
377
378
/*
379
* Send TSTP when ^Z is pressed.
380
*/
381
el_set(e, EL_ADDFN, "rl_tstp",
382
"ReadLine compatible suspend function",
383
_el_rl_tstp);
384
el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
385
386
/*
387
* Set some readline compatible key-bindings.
388
*/
389
el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL);
390
391
/*
392
* Allow the use of Home/End keys.
393
*/
394
el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
395
el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
396
el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL);
397
el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL);
398
el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL);
399
el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL);
400
401
/*
402
* Allow the use of the Delete/Insert keys.
403
*/
404
el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
405
el_set(e, EL_BIND, "\\e[2~", "em-toggle-overwrite", NULL);
406
407
/*
408
* Ctrl-left-arrow and Ctrl-right-arrow for word moving.
409
*/
410
el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
411
el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
412
el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL);
413
el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL);
414
el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
415
el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
416
417
/* read settings from configuration file */
418
el_source(e, NULL);
419
420
/*
421
* Unfortunately, some applications really do use rl_point
422
* and rl_line_buffer directly.
423
*/
424
_resize_fun(e, &rl_line_buffer);
425
_rl_update_pos();
426
427
tty_end(e, TCSADRAIN);
428
429
return 0;
430
}
431
432
433
/*
434
* read one line from input stream and return it, chomping
435
* trailing newline (if there is any)
436
*/
437
char *
438
readline(const char *p)
439
{
440
HistEvent ev;
441
const char * volatile prompt = p;
442
int count;
443
const char *ret;
444
char *buf;
445
static int used_event_hook;
446
447
if (e == NULL || h == NULL)
448
rl_initialize();
449
if (rl_startup_hook) {
450
(*rl_startup_hook)();
451
}
452
tty_init(e);
453
454
455
rl_done = 0;
456
457
(void)setjmp(topbuf);
458
buf = NULL;
459
460
/* update prompt accordingly to what has been passed */
461
if (rl_set_prompt(prompt) == -1)
462
goto out;
463
464
if (rl_pre_input_hook)
465
(*rl_pre_input_hook)();
466
467
if (rl_event_hook && !(e->el_flags & NO_TTY)) {
468
el_set(e, EL_GETCFN, _rl_event_read_char);
469
used_event_hook = 1;
470
}
471
472
if (!rl_event_hook && used_event_hook) {
473
el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
474
used_event_hook = 0;
475
}
476
477
rl_already_prompted = 0;
478
479
/* get one line from input stream */
480
ret = el_gets(e, &count);
481
482
if (ret && count > 0) {
483
int lastidx;
484
485
buf = strdup(ret);
486
if (buf == NULL)
487
goto out;
488
lastidx = count - 1;
489
if (buf[lastidx] == '\n')
490
buf[lastidx] = '\0';
491
} else
492
buf = NULL;
493
494
history(h, &ev, H_GETSIZE);
495
history_length = ev.num;
496
497
out:
498
tty_end(e, TCSADRAIN);
499
return buf;
500
}
501
502
/*
503
* history functions
504
*/
505
506
/*
507
* is normally called before application starts to use
508
* history expansion functions
509
*/
510
void
511
using_history(void)
512
{
513
if (h == NULL || e == NULL)
514
rl_initialize();
515
history_offset = history_length;
516
}
517
518
519
/*
520
* substitute ``what'' with ``with'', returning resulting string; if
521
* globally == 1, substitutes all occurrences of what, otherwise only the
522
* first one
523
*/
524
static char *
525
_rl_compat_sub(const char *str, const char *what, const char *with,
526
int globally)
527
{
528
const char *s;
529
char *r, *result;
530
size_t len, with_len, what_len;
531
532
len = strlen(str);
533
with_len = strlen(with);
534
what_len = strlen(what);
535
536
/* calculate length we need for result */
537
s = str;
538
while (*s) {
539
if (*s == *what && !strncmp(s, what, what_len)) {
540
len += with_len - what_len;
541
if (!globally)
542
break;
543
s += what_len;
544
} else
545
s++;
546
}
547
r = result = el_calloc(len + 1, sizeof(*r));
548
if (result == NULL)
549
return NULL;
550
s = str;
551
while (*s) {
552
if (*s == *what && !strncmp(s, what, what_len)) {
553
memcpy(r, with, with_len);
554
r += with_len;
555
s += what_len;
556
if (!globally) {
557
(void)strcpy(r, s);
558
return result;
559
}
560
} else
561
*r++ = *s++;
562
}
563
*r = '\0';
564
return result;
565
}
566
567
static char *last_search_pat; /* last !?pat[?] search pattern */
568
static char *last_search_match; /* last !?pat[?] that matched */
569
570
const char *
571
get_history_event(const char *cmd, int *cindex, int qchar)
572
{
573
int idx, sign, sub, num, begin, ret;
574
size_t len;
575
char *pat;
576
const char *rptr;
577
HistEvent ev;
578
579
idx = *cindex;
580
if (cmd[idx++] != history_expansion_char)
581
return NULL;
582
583
/* find out which event to take */
584
if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
585
if (history(h, &ev, H_FIRST) != 0)
586
return NULL;
587
*cindex = cmd[idx]? (idx + 1):idx;
588
return ev.str;
589
}
590
sign = 0;
591
if (cmd[idx] == '-') {
592
sign = 1;
593
idx++;
594
}
595
596
if ('0' <= cmd[idx] && cmd[idx] <= '9') {
597
HIST_ENTRY *he;
598
599
num = 0;
600
while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
601
num = num * 10 + cmd[idx] - '0';
602
idx++;
603
}
604
if (sign)
605
num = history_length - num + history_base;
606
607
if (!(he = history_get(num)))
608
return NULL;
609
610
*cindex = idx;
611
return he->line;
612
}
613
sub = 0;
614
if (cmd[idx] == '?') {
615
sub = 1;
616
idx++;
617
}
618
begin = idx;
619
while (cmd[idx]) {
620
if (cmd[idx] == '\n')
621
break;
622
if (sub && cmd[idx] == '?')
623
break;
624
if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
625
|| cmd[idx] == '\t' || cmd[idx] == qchar))
626
break;
627
idx++;
628
}
629
len = (size_t)idx - (size_t)begin;
630
if (sub && cmd[idx] == '?')
631
idx++;
632
if (sub && len == 0 && last_search_pat && *last_search_pat)
633
pat = last_search_pat;
634
else if (len == 0)
635
return NULL;
636
else {
637
if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL)
638
return NULL;
639
(void)strlcpy(pat, cmd + begin, len + 1);
640
}
641
642
if (history(h, &ev, H_CURR) != 0) {
643
if (pat != last_search_pat)
644
el_free(pat);
645
return NULL;
646
}
647
num = ev.num;
648
649
if (sub) {
650
if (pat != last_search_pat) {
651
el_free(last_search_pat);
652
last_search_pat = pat;
653
}
654
ret = history_search(pat, -1);
655
} else
656
ret = history_search_prefix(pat, -1);
657
658
if (ret == -1) {
659
/* restore to end of list on failed search */
660
history(h, &ev, H_FIRST);
661
(void)fprintf(rl_outstream, "%s: Event not found\n", pat);
662
if (pat != last_search_pat)
663
el_free(pat);
664
return NULL;
665
}
666
667
if (sub && len) {
668
el_free(last_search_match);
669
last_search_match = strdup(pat);
670
}
671
672
if (pat != last_search_pat)
673
el_free(pat);
674
675
if (history(h, &ev, H_CURR) != 0)
676
return NULL;
677
*cindex = idx;
678
rptr = ev.str;
679
680
/* roll back to original position */
681
(void)history(h, &ev, H_SET, num);
682
683
return rptr;
684
}
685
686
static int
687
getfrom(const char **cmdp, char **fromp, const char *search, int delim)
688
{
689
size_t size = 16;
690
size_t len = 0;
691
const char *cmd = *cmdp;
692
char *what = el_realloc(*fromp, size * sizeof(*what));
693
if (what == NULL){
694
el_free(*fromp);
695
*fromp = NULL;
696
return 0;
697
}
698
for (; *cmd && *cmd != delim; cmd++) {
699
if (*cmd == '\\' && cmd[1] == delim)
700
cmd++;
701
if (len - 1 >= size) {
702
char *nwhat;
703
nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat));
704
if (nwhat == NULL) {
705
el_free(what);
706
el_free(*fromp);
707
*cmdp = cmd;
708
*fromp = NULL;
709
return 0;
710
}
711
what = nwhat;
712
}
713
what[len++] = *cmd;
714
}
715
what[len] = '\0';
716
*fromp = what;
717
*cmdp = cmd;
718
if (*what == '\0') {
719
el_free(what);
720
if (search) {
721
*fromp = strdup(search);
722
if (*fromp == NULL) {
723
return 0;
724
}
725
} else {
726
*fromp = NULL;
727
return -1;
728
}
729
}
730
if (!*cmd) {
731
el_free(what);
732
*fromp = NULL;
733
return -1;
734
}
735
736
cmd++; /* shift after delim */
737
*cmdp = cmd;
738
739
if (!*cmd) {
740
el_free(what);
741
*fromp = NULL;
742
return -1;
743
}
744
return 1;
745
}
746
747
static int
748
getto(const char **cmdp, char **top, const char *from, int delim)
749
{
750
size_t size = 16;
751
size_t len = 0;
752
size_t from_len = strlen(from);
753
const char *cmd = *cmdp;
754
char *with = el_realloc(*top, size * sizeof(*with));
755
*top = NULL;
756
if (with == NULL)
757
goto out;
758
759
for (; *cmd && *cmd != delim; cmd++) {
760
if (len + from_len + 1 >= size) {
761
char *nwith;
762
size += from_len + 1;
763
nwith = el_realloc(with, size * sizeof(*nwith));
764
if (nwith == NULL)
765
goto out;
766
with = nwith;
767
}
768
if (*cmd == '&') {
769
/* safe */
770
strcpy(&with[len], from);
771
len += from_len;
772
continue;
773
}
774
if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&'))
775
cmd++;
776
with[len++] = *cmd;
777
}
778
if (!*cmd)
779
goto out;
780
with[len] = '\0';
781
*top = with;
782
*cmdp = cmd;
783
return 1;
784
out:
785
el_free(with);
786
el_free(*top);
787
*top = NULL;
788
*cmdp = cmd;
789
return -1;
790
}
791
792
static void
793
replace(char **tmp, int c)
794
{
795
char *aptr;
796
if ((aptr = strrchr(*tmp, c)) == NULL)
797
return;
798
aptr = strdup(aptr + 1); // XXX: check
799
el_free(*tmp);
800
*tmp = aptr;
801
}
802
803
/*
804
* the real function doing history expansion - takes as argument command
805
* to do and data upon which the command should be executed
806
* does expansion the way I've understood readline documentation
807
*
808
* returns 0 if data was not modified, 1 if it was and 2 if the string
809
* should be only printed and not executed; in case of error,
810
* returns -1 and *result points to NULL
811
* it's the caller's responsibility to free() the string returned in *result
812
*/
813
static int
814
_history_expand_command(const char *command, size_t offs, size_t cmdlen,
815
char **result)
816
{
817
char *tmp, *search = NULL, *aptr, delim;
818
const char *ptr, *cmd;
819
static char *from = NULL, *to = NULL;
820
int start, end, idx, has_mods = 0;
821
int p_on = 0, g_on = 0, ev;
822
823
*result = NULL;
824
aptr = NULL;
825
ptr = NULL;
826
827
/* First get event specifier */
828
idx = 0;
829
830
if (strchr(":^*$", command[offs + 1])) {
831
char str[4];
832
/*
833
* "!:" is shorthand for "!!:".
834
* "!^", "!*" and "!$" are shorthand for
835
* "!!:^", "!!:*" and "!!:$" respectively.
836
*/
837
str[0] = str[1] = '!';
838
str[2] = '0';
839
ptr = get_history_event(str, &idx, 0);
840
idx = (command[offs + 1] == ':')? 1:0;
841
has_mods = 1;
842
} else {
843
if (command[offs + 1] == '#') {
844
/* use command so far */
845
if ((aptr = el_calloc(offs + 1, sizeof(*aptr)))
846
== NULL)
847
return -1;
848
(void)strlcpy(aptr, command, offs + 1);
849
idx = 1;
850
} else {
851
int qchar;
852
853
qchar = (offs > 0 && command[offs - 1] == '"')
854
? '"' : '\0';
855
ptr = get_history_event(command + offs, &idx, qchar);
856
}
857
has_mods = command[offs + (size_t)idx] == ':';
858
}
859
860
if (ptr == NULL && aptr == NULL)
861
return -1;
862
863
if (!has_mods) {
864
*result = strdup(aptr ? aptr : ptr);
865
if (aptr)
866
el_free(aptr);
867
if (*result == NULL)
868
return -1;
869
return 1;
870
}
871
872
cmd = command + offs + idx + 1;
873
874
/* Now parse any word designators */
875
876
if (*cmd == '%') /* last word matched by ?pat? */
877
tmp = strdup(last_search_match ? last_search_match : "");
878
else if (strchr("^*$-0123456789", *cmd)) {
879
start = end = -1;
880
if (*cmd == '^')
881
start = end = 1, cmd++;
882
else if (*cmd == '$')
883
start = -1, cmd++;
884
else if (*cmd == '*')
885
start = 1, cmd++;
886
else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
887
start = 0;
888
while (*cmd && '0' <= *cmd && *cmd <= '9')
889
start = start * 10 + *cmd++ - '0';
890
891
if (*cmd == '-') {
892
if (isdigit((unsigned char) cmd[1])) {
893
cmd++;
894
end = 0;
895
while (*cmd && '0' <= *cmd && *cmd <= '9')
896
end = end * 10 + *cmd++ - '0';
897
} else if (cmd[1] == '$') {
898
cmd += 2;
899
end = -1;
900
} else {
901
cmd++;
902
end = -2;
903
}
904
} else if (*cmd == '*')
905
end = -1, cmd++;
906
else
907
end = start;
908
}
909
tmp = history_arg_extract(start, end, aptr? aptr:ptr);
910
if (tmp == NULL) {
911
(void)fprintf(rl_outstream, "%s: Bad word specifier",
912
command + offs + idx);
913
if (aptr)
914
el_free(aptr);
915
return -1;
916
}
917
} else
918
tmp = strdup(aptr? aptr:ptr);
919
920
if (aptr)
921
el_free(aptr);
922
923
if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
924
*result = tmp;
925
return 1;
926
}
927
928
for (; *cmd; cmd++) {
929
switch (*cmd) {
930
case ':':
931
continue;
932
case 'h': /* remove trailing path */
933
if ((aptr = strrchr(tmp, '/')) != NULL)
934
*aptr = '\0';
935
continue;
936
case 't': /* remove leading path */
937
replace(&tmp, '/');
938
continue;
939
case 'r': /* remove trailing suffix */
940
if ((aptr = strrchr(tmp, '.')) != NULL)
941
*aptr = '\0';
942
continue;
943
case 'e': /* remove all but suffix */
944
replace(&tmp, '.');
945
continue;
946
case 'p': /* print only */
947
p_on = 1;
948
continue;
949
case 'g':
950
g_on = 2;
951
continue;
952
case '&':
953
if (from == NULL || to == NULL)
954
continue;
955
/*FALLTHROUGH*/
956
case 's':
957
ev = -1;
958
delim = *++cmd;
959
if (delim == '\0' || *++cmd == '\0')
960
goto out;
961
if ((ev = getfrom(&cmd, &from, search, delim)) != 1)
962
goto out;
963
if ((ev = getto(&cmd, &to, from, delim)) != 1)
964
goto out;
965
aptr = _rl_compat_sub(tmp, from, to, g_on);
966
if (aptr) {
967
el_free(tmp);
968
tmp = aptr;
969
}
970
g_on = 0;
971
cmd--;
972
continue;
973
}
974
}
975
*result = tmp;
976
return p_on ? 2 : 1;
977
out:
978
el_free(tmp);
979
return ev;
980
981
}
982
983
984
/*
985
* csh-style history expansion
986
*/
987
int
988
history_expand(char *str, char **output)
989
{
990
int ret = 0;
991
size_t idx, i, size;
992
char *tmp, *result;
993
994
if (h == NULL || e == NULL)
995
rl_initialize();
996
997
if (history_expansion_char == 0) {
998
*output = strdup(str);
999
return 0;
1000
}
1001
1002
*output = NULL;
1003
if (str[0] == history_subst_char) {
1004
/* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
1005
*output = el_calloc(strlen(str) + 4 + 1, sizeof(**output));
1006
if (*output == NULL)
1007
return 0;
1008
(*output)[0] = (*output)[1] = history_expansion_char;
1009
(*output)[2] = ':';
1010
(*output)[3] = 's';
1011
(void)strcpy((*output) + 4, str);
1012
str = *output;
1013
} else {
1014
*output = strdup(str);
1015
if (*output == NULL)
1016
return 0;
1017
}
1018
1019
#define ADD_STRING(what, len, fr) \
1020
{ \
1021
if (idx + len + 1 > size) { \
1022
char *nresult = el_realloc(result, \
1023
(size += len + 1) * sizeof(*nresult)); \
1024
if (nresult == NULL) { \
1025
el_free(*output); \
1026
el_free(fr); \
1027
return 0; \
1028
} \
1029
result = nresult; \
1030
} \
1031
(void)strlcpy(&result[idx], what, len + 1); \
1032
idx += len; \
1033
}
1034
1035
result = NULL;
1036
size = idx = 0;
1037
tmp = NULL;
1038
for (i = 0; str[i];) {
1039
int qchar, loop_again;
1040
size_t len, start, j;
1041
1042
qchar = 0;
1043
loop_again = 1;
1044
start = j = i;
1045
loop:
1046
for (; str[j]; j++) {
1047
if (str[j] == '\\' &&
1048
str[j + 1] == history_expansion_char) {
1049
len = strlen(&str[j + 1]) + 1;
1050
memmove(&str[j], &str[j + 1], len);
1051
continue;
1052
}
1053
if (!loop_again) {
1054
if (isspace((unsigned char) str[j])
1055
|| str[j] == qchar)
1056
break;
1057
}
1058
if (str[j] == history_expansion_char
1059
&& !strchr(history_no_expand_chars, str[j + 1])
1060
&& (!history_inhibit_expansion_function ||
1061
(*history_inhibit_expansion_function)(str,
1062
(int)j) == 0))
1063
break;
1064
}
1065
1066
if (str[j] && loop_again) {
1067
i = j;
1068
qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
1069
j++;
1070
if (str[j] == history_expansion_char)
1071
j++;
1072
loop_again = 0;
1073
goto loop;
1074
}
1075
len = i - start;
1076
ADD_STRING(&str[start], len, NULL);
1077
1078
if (str[i] == '\0' || str[i] != history_expansion_char) {
1079
len = j - i;
1080
ADD_STRING(&str[i], len, NULL);
1081
if (start == 0)
1082
ret = 0;
1083
else
1084
ret = 1;
1085
break;
1086
}
1087
ret = _history_expand_command (str, i, (j - i), &tmp);
1088
if (ret > 0 && tmp) {
1089
len = strlen(tmp);
1090
ADD_STRING(tmp, len, tmp);
1091
}
1092
if (tmp) {
1093
el_free(tmp);
1094
tmp = NULL;
1095
}
1096
i = j;
1097
}
1098
1099
/* ret is 2 for "print only" option */
1100
if (ret == 2) {
1101
add_history(result);
1102
#ifdef GDB_411_HACK
1103
/* gdb 4.11 has been shipped with readline, where */
1104
/* history_expand() returned -1 when the line */
1105
/* should not be executed; in readline 2.1+ */
1106
/* it should return 2 in such a case */
1107
ret = -1;
1108
#endif
1109
}
1110
el_free(*output);
1111
*output = result;
1112
1113
return ret;
1114
}
1115
1116
/*
1117
* Return a string consisting of arguments of "str" from "start" to "end".
1118
*/
1119
char *
1120
history_arg_extract(int start, int end, const char *str)
1121
{
1122
size_t i, len, max;
1123
char **arr, *result = NULL;
1124
1125
arr = history_tokenize(str);
1126
if (!arr)
1127
return NULL;
1128
if (arr && *arr == NULL)
1129
goto out;
1130
1131
for (max = 0; arr[max]; max++)
1132
continue;
1133
max--;
1134
1135
if (start == '$')
1136
start = (int)max;
1137
if (end == '$')
1138
end = (int)max;
1139
if (end < 0)
1140
end = (int)max + end + 1;
1141
if (start < 0)
1142
start = end;
1143
1144
if (start < 0 || end < 0 || (size_t)start > max ||
1145
(size_t)end > max || start > end)
1146
goto out;
1147
1148
for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
1149
len += strlen(arr[i]) + 1;
1150
len++;
1151
result = el_calloc(len, sizeof(*result));
1152
if (result == NULL)
1153
goto out;
1154
1155
for (i = (size_t)start, len = 0; i <= (size_t)end; i++) {
1156
(void)strcpy(result + len, arr[i]);
1157
len += strlen(arr[i]);
1158
if (i < (size_t)end)
1159
result[len++] = ' ';
1160
}
1161
result[len] = '\0';
1162
1163
out:
1164
for (i = 0; arr[i]; i++)
1165
el_free(arr[i]);
1166
el_free(arr);
1167
1168
return result;
1169
}
1170
1171
/*
1172
* Parse the string into individual tokens,
1173
* similar to how shell would do it.
1174
*/
1175
char **
1176
history_tokenize(const char *str)
1177
{
1178
int size = 1, idx = 0, i, start;
1179
size_t len;
1180
char **result = NULL, *temp, delim = '\0';
1181
1182
for (i = 0; str[i];) {
1183
while (isspace((unsigned char) str[i]))
1184
i++;
1185
start = i;
1186
for (; str[i];) {
1187
if (str[i] == '\\') {
1188
if (str[i+1] != '\0')
1189
i++;
1190
} else if (str[i] == delim)
1191
delim = '\0';
1192
else if (!delim &&
1193
(isspace((unsigned char) str[i]) ||
1194
strchr("()<>;&|$", str[i])))
1195
break;
1196
else if (!delim && strchr("'`\"", str[i]))
1197
delim = str[i];
1198
if (str[i])
1199
i++;
1200
}
1201
1202
if (idx + 2 >= size) {
1203
char **nresult;
1204
size <<= 1;
1205
nresult = el_realloc(result, (size_t)size * sizeof(*nresult));
1206
if (nresult == NULL) {
1207
el_free(result);
1208
return NULL;
1209
}
1210
result = nresult;
1211
}
1212
len = (size_t)i - (size_t)start;
1213
temp = el_calloc(len + 1, sizeof(*temp));
1214
if (temp == NULL) {
1215
for (i = 0; i < idx; i++)
1216
el_free(result[i]);
1217
el_free(result);
1218
return NULL;
1219
}
1220
(void)strlcpy(temp, &str[start], len + 1);
1221
result[idx++] = temp;
1222
result[idx] = NULL;
1223
if (str[i])
1224
i++;
1225
}
1226
return result;
1227
}
1228
1229
1230
/*
1231
* limit size of history record to ``max'' events
1232
*/
1233
void
1234
stifle_history(int max)
1235
{
1236
HistEvent ev;
1237
HIST_ENTRY *he;
1238
1239
if (h == NULL || e == NULL)
1240
rl_initialize();
1241
1242
if (history(h, &ev, H_SETSIZE, max) == 0) {
1243
max_input_history = max;
1244
if (history_length > max)
1245
history_base = history_length - max;
1246
while (history_length > max) {
1247
he = remove_history(0);
1248
el_free(he->data);
1249
el_free((void *)(unsigned long)he->line);
1250
el_free(he);
1251
}
1252
}
1253
}
1254
1255
1256
/*
1257
* "unlimit" size of history - set the limit to maximum allowed int value
1258
*/
1259
int
1260
unstifle_history(void)
1261
{
1262
HistEvent ev;
1263
int omax;
1264
1265
history(h, &ev, H_SETSIZE, INT_MAX);
1266
omax = max_input_history;
1267
max_input_history = INT_MAX;
1268
return omax; /* some value _must_ be returned */
1269
}
1270
1271
1272
int
1273
history_is_stifled(void)
1274
{
1275
1276
/* cannot return true answer */
1277
return max_input_history != INT_MAX;
1278
}
1279
1280
static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
1281
1282
int
1283
history_truncate_file (const char *filename, int nlines)
1284
{
1285
int ret = 0;
1286
FILE *fp, *tp;
1287
char template[sizeof(_history_tmp_template)];
1288
char buf[4096];
1289
int fd;
1290
char *cp;
1291
off_t off;
1292
int count = 0;
1293
ssize_t left = 0;
1294
1295
if (filename == NULL && (filename = _default_history_file()) == NULL)
1296
return errno;
1297
if ((fp = fopen(filename, "r+")) == NULL)
1298
return errno;
1299
strcpy(template, _history_tmp_template);
1300
if ((fd = mkstemp(template)) == -1) {
1301
ret = errno;
1302
goto out1;
1303
}
1304
1305
if ((tp = fdopen(fd, "r+")) == NULL) {
1306
close(fd);
1307
ret = errno;
1308
goto out2;
1309
}
1310
1311
for(;;) {
1312
if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) {
1313
if (ferror(fp)) {
1314
ret = errno;
1315
break;
1316
}
1317
if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
1318
(off_t)-1) {
1319
ret = errno;
1320
break;
1321
}
1322
left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp);
1323
if (ferror(fp)) {
1324
ret = errno;
1325
break;
1326
}
1327
if (left == 0) {
1328
count--;
1329
left = sizeof(buf);
1330
} else if (fwrite(buf, (size_t)left, (size_t)1, tp)
1331
!= 1) {
1332
ret = errno;
1333
break;
1334
}
1335
fflush(tp);
1336
break;
1337
}
1338
if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) {
1339
ret = errno;
1340
break;
1341
}
1342
count++;
1343
}
1344
if (ret)
1345
goto out3;
1346
cp = buf + left - 1;
1347
if(*cp != '\n')
1348
cp++;
1349
for(;;) {
1350
while (--cp >= buf) {
1351
if (*cp == '\n') {
1352
if (--nlines == 0) {
1353
if (++cp >= buf + sizeof(buf)) {
1354
count++;
1355
cp = buf;
1356
}
1357
break;
1358
}
1359
}
1360
}
1361
if (nlines <= 0 || count == 0)
1362
break;
1363
count--;
1364
if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
1365
ret = errno;
1366
break;
1367
}
1368
if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) {
1369
if (ferror(tp)) {
1370
ret = errno;
1371
break;
1372
}
1373
ret = EAGAIN;
1374
break;
1375
}
1376
cp = buf + sizeof(buf);
1377
}
1378
1379
if (ret || nlines > 0)
1380
goto out3;
1381
1382
if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) {
1383
ret = errno;
1384
goto out3;
1385
}
1386
1387
if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
1388
(off_t)-1) {
1389
ret = errno;
1390
goto out3;
1391
}
1392
1393
for(;;) {
1394
if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) {
1395
if (ferror(fp))
1396
ret = errno;
1397
break;
1398
}
1399
if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) {
1400
ret = errno;
1401
break;
1402
}
1403
}
1404
fflush(fp);
1405
if((off = ftello(fp)) > 0)
1406
(void)ftruncate(fileno(fp), off);
1407
out3:
1408
fclose(tp);
1409
out2:
1410
unlink(template);
1411
out1:
1412
fclose(fp);
1413
1414
return ret;
1415
}
1416
1417
1418
/*
1419
* read history from a file given
1420
*/
1421
int
1422
read_history(const char *filename)
1423
{
1424
HistEvent ev;
1425
1426
if (h == NULL || e == NULL)
1427
rl_initialize();
1428
if (filename == NULL && (filename = _default_history_file()) == NULL)
1429
return errno;
1430
errno = 0;
1431
if (history(h, &ev, H_LOAD, filename) == -1)
1432
return errno ? errno : EINVAL;
1433
if (history(h, &ev, H_GETSIZE) == 0)
1434
history_length = ev.num;
1435
if (history_length < 0)
1436
return EINVAL;
1437
return 0;
1438
}
1439
1440
1441
/*
1442
* write history to a file given
1443
*/
1444
int
1445
write_history(const char *filename)
1446
{
1447
HistEvent ev;
1448
1449
if (h == NULL || e == NULL)
1450
rl_initialize();
1451
if (filename == NULL && (filename = _default_history_file()) == NULL)
1452
return errno;
1453
return history(h, &ev, H_SAVE, filename) == -1 ?
1454
(errno ? errno : EINVAL) : 0;
1455
}
1456
1457
int
1458
append_history(int n, const char *filename)
1459
{
1460
HistEvent ev;
1461
FILE *fp;
1462
1463
if (h == NULL || e == NULL)
1464
rl_initialize();
1465
if (filename == NULL && (filename = _default_history_file()) == NULL)
1466
return errno;
1467
1468
if ((fp = fopen(filename, "a")) == NULL)
1469
return errno;
1470
1471
if (history(h, &ev, H_NSAVE_FP, (size_t)n, fp) == -1) {
1472
int serrno = errno ? errno : EINVAL;
1473
fclose(fp);
1474
return serrno;
1475
}
1476
fclose(fp);
1477
return 0;
1478
}
1479
1480
/*
1481
* returns history ``num''th event
1482
*
1483
* returned pointer points to static variable
1484
*/
1485
HIST_ENTRY *
1486
history_get(int num)
1487
{
1488
static HIST_ENTRY she;
1489
HistEvent ev;
1490
int curr_num;
1491
1492
if (h == NULL || e == NULL)
1493
rl_initialize();
1494
1495
if (num < history_base)
1496
return NULL;
1497
1498
/* save current position */
1499
if (history(h, &ev, H_CURR) != 0)
1500
return NULL;
1501
curr_num = ev.num;
1502
1503
/*
1504
* use H_DELDATA to set to nth history (without delete) by passing
1505
* (void **)-1 -- as in history_set_pos
1506
*/
1507
if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
1508
goto out;
1509
1510
/* get current entry */
1511
if (history(h, &ev, H_CURR) != 0)
1512
goto out;
1513
if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
1514
goto out;
1515
she.line = ev.str;
1516
1517
/* restore pointer to where it was */
1518
(void)history(h, &ev, H_SET, curr_num);
1519
1520
return &she;
1521
1522
out:
1523
/* restore pointer to where it was */
1524
(void)history(h, &ev, H_SET, curr_num);
1525
return NULL;
1526
}
1527
1528
1529
/*
1530
* add the line to history table
1531
*/
1532
int
1533
add_history(const char *line)
1534
{
1535
HistEvent ev;
1536
1537
if (h == NULL || e == NULL)
1538
rl_initialize();
1539
1540
if (history(h, &ev, H_ENTER, line) == -1)
1541
return 0;
1542
1543
(void)history(h, &ev, H_GETSIZE);
1544
if (ev.num == history_length)
1545
history_base++;
1546
else {
1547
history_offset++;
1548
history_length = ev.num;
1549
}
1550
return 0;
1551
}
1552
1553
1554
/*
1555
* remove the specified entry from the history list and return it.
1556
*/
1557
HIST_ENTRY *
1558
remove_history(int num)
1559
{
1560
HIST_ENTRY *he;
1561
HistEvent ev;
1562
1563
if (h == NULL || e == NULL)
1564
rl_initialize();
1565
1566
if ((he = el_malloc(sizeof(*he))) == NULL)
1567
return NULL;
1568
1569
if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
1570
el_free(he);
1571
return NULL;
1572
}
1573
1574
he->line = ev.str;
1575
if (history(h, &ev, H_GETSIZE) == 0)
1576
history_length = ev.num;
1577
1578
return he;
1579
}
1580
1581
1582
/*
1583
* replace the line and data of the num-th entry
1584
*/
1585
HIST_ENTRY *
1586
replace_history_entry(int num, const char *line, histdata_t data)
1587
{
1588
HIST_ENTRY *he;
1589
HistEvent ev;
1590
int curr_num;
1591
1592
if (h == NULL || e == NULL)
1593
rl_initialize();
1594
1595
/* save current position */
1596
if (history(h, &ev, H_CURR) != 0)
1597
return NULL;
1598
curr_num = ev.num;
1599
1600
/* start from the oldest */
1601
if (history(h, &ev, H_LAST) != 0)
1602
return NULL; /* error */
1603
1604
if ((he = el_malloc(sizeof(*he))) == NULL)
1605
return NULL;
1606
1607
/* look forwards for event matching specified offset */
1608
if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
1609
goto out;
1610
1611
he->line = ev.str;
1612
if (he->line == NULL)
1613
goto out;
1614
1615
if (history(h, &ev, H_REPLACE, line, data))
1616
goto out;
1617
1618
/* restore pointer to where it was */
1619
if (history(h, &ev, H_SET, curr_num))
1620
goto out;
1621
1622
return he;
1623
out:
1624
el_free(he);
1625
return NULL;
1626
}
1627
1628
/*
1629
* clear the history list - delete all entries
1630
*/
1631
void
1632
clear_history(void)
1633
{
1634
HistEvent ev;
1635
1636
if (h == NULL || e == NULL)
1637
rl_initialize();
1638
1639
(void)history(h, &ev, H_CLEAR);
1640
history_offset = history_length = 0;
1641
}
1642
1643
1644
/*
1645
* returns offset of the current history event
1646
*/
1647
int
1648
where_history(void)
1649
{
1650
return history_offset;
1651
}
1652
1653
static HIST_ENTRY **_history_listp;
1654
static HIST_ENTRY *_history_list;
1655
1656
HIST_ENTRY **
1657
history_list(void)
1658
{
1659
HistEvent ev;
1660
HIST_ENTRY **nlp, *nl;
1661
int i;
1662
1663
if (history(h, &ev, H_LAST) != 0)
1664
return NULL;
1665
1666
if ((nlp = el_realloc(_history_listp,
1667
((size_t)history_length + 1) * sizeof(*nlp))) == NULL)
1668
return NULL;
1669
_history_listp = nlp;
1670
1671
if ((nl = el_realloc(_history_list,
1672
(size_t)history_length * sizeof(*nl))) == NULL)
1673
return NULL;
1674
_history_list = nl;
1675
1676
i = 0;
1677
do {
1678
_history_listp[i] = &_history_list[i];
1679
_history_list[i].line = ev.str;
1680
_history_list[i].data = NULL;
1681
if (i++ == history_length)
1682
abort();
1683
} while (history(h, &ev, H_PREV) == 0);
1684
_history_listp[i] = NULL;
1685
return _history_listp;
1686
}
1687
1688
/*
1689
* returns current history event or NULL if there is no such event
1690
*/
1691
HIST_ENTRY *
1692
current_history(void)
1693
{
1694
HistEvent ev;
1695
1696
if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0)
1697
return NULL;
1698
1699
rl_he.line = ev.str;
1700
rl_he.data = NULL;
1701
return &rl_he;
1702
}
1703
1704
1705
/*
1706
* returns total number of bytes history events' data are using
1707
*/
1708
int
1709
history_total_bytes(void)
1710
{
1711
HistEvent ev;
1712
int curr_num;
1713
size_t size;
1714
1715
if (history(h, &ev, H_CURR) != 0)
1716
return -1;
1717
curr_num = ev.num;
1718
1719
(void)history(h, &ev, H_FIRST);
1720
size = 0;
1721
do
1722
size += strlen(ev.str) * sizeof(*ev.str);
1723
while (history(h, &ev, H_NEXT) == 0);
1724
1725
/* get to the same position as before */
1726
history(h, &ev, H_PREV_EVENT, curr_num);
1727
1728
return (int)size;
1729
}
1730
1731
1732
/*
1733
* sets the position in the history list to ``pos''
1734
*/
1735
int
1736
history_set_pos(int pos)
1737
{
1738
if (pos >= history_length || pos < 0)
1739
return 0;
1740
1741
history_offset = pos;
1742
return 1;
1743
}
1744
1745
1746
/*
1747
* returns previous event in history and shifts pointer accordingly
1748
* Note that readline and editline define directions in opposite ways.
1749
*/
1750
HIST_ENTRY *
1751
previous_history(void)
1752
{
1753
HistEvent ev;
1754
1755
if (history_offset == 0)
1756
return NULL;
1757
1758
if (history(h, &ev, H_LAST) != 0)
1759
return NULL;
1760
1761
history_offset--;
1762
return current_history();
1763
}
1764
1765
1766
/*
1767
* returns next event in history and shifts pointer accordingly
1768
*/
1769
HIST_ENTRY *
1770
next_history(void)
1771
{
1772
HistEvent ev;
1773
1774
if (history_offset >= history_length)
1775
return NULL;
1776
1777
if (history(h, &ev, H_LAST) != 0)
1778
return NULL;
1779
1780
history_offset++;
1781
return current_history();
1782
}
1783
1784
1785
/*
1786
* searches for first history event containing the str
1787
*/
1788
int
1789
history_search(const char *str, int direction)
1790
{
1791
HistEvent ev;
1792
const char *strp;
1793
int curr_num;
1794
1795
if (history(h, &ev, H_CURR) != 0)
1796
return -1;
1797
curr_num = ev.num;
1798
1799
for (;;) {
1800
if ((strp = strstr(ev.str, str)) != NULL)
1801
return (int)(strp - ev.str);
1802
if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
1803
break;
1804
}
1805
(void)history(h, &ev, H_SET, curr_num);
1806
return -1;
1807
}
1808
1809
1810
/*
1811
* searches for first history event beginning with str
1812
*/
1813
int
1814
history_search_prefix(const char *str, int direction)
1815
{
1816
HistEvent ev;
1817
1818
return (history(h, &ev, direction < 0 ?
1819
H_PREV_STR : H_NEXT_STR, str));
1820
}
1821
1822
1823
/*
1824
* search for event in history containing str, starting at offset
1825
* abs(pos); continue backward, if pos<0, forward otherwise
1826
*/
1827
/* ARGSUSED */
1828
int
1829
history_search_pos(const char *str,
1830
int direction __attribute__((__unused__)), int pos)
1831
{
1832
HistEvent ev;
1833
int curr_num, off;
1834
1835
off = (pos > 0) ? pos : -pos;
1836
pos = (pos > 0) ? 1 : -1;
1837
1838
if (history(h, &ev, H_CURR) != 0)
1839
return -1;
1840
curr_num = ev.num;
1841
1842
if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0)
1843
return -1;
1844
1845
for (;;) {
1846
if (strstr(ev.str, str))
1847
return off;
1848
if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1849
break;
1850
}
1851
1852
/* set "current" pointer back to previous state */
1853
(void)history(h, &ev,
1854
pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1855
1856
return -1;
1857
}
1858
1859
1860
/********************************/
1861
/* completion functions */
1862
1863
char *
1864
tilde_expand(char *name)
1865
{
1866
return fn_tilde_expand(name);
1867
}
1868
1869
char *
1870
filename_completion_function(const char *name, int state)
1871
{
1872
return fn_filename_completion_function(name, state);
1873
}
1874
1875
/*
1876
* a completion generator for usernames; returns _first_ username
1877
* which starts with supplied text
1878
* text contains a partial username preceded by random character
1879
* (usually '~'); state resets search from start (??? should we do that anyway)
1880
* it's the caller's responsibility to free the returned value
1881
*/
1882
char *
1883
username_completion_function(const char *text, int state)
1884
{
1885
#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1886
struct passwd pwres;
1887
char pwbuf[1024];
1888
#endif
1889
struct passwd *pass = NULL;
1890
1891
if (text[0] == '\0')
1892
return NULL;
1893
1894
if (*text == '~')
1895
text++;
1896
1897
if (state == 0)
1898
setpwent();
1899
1900
while (
1901
#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1902
getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
1903
#else
1904
(pass = getpwent()) != NULL
1905
#endif
1906
&& text[0] == pass->pw_name[0]
1907
&& strcmp(text, pass->pw_name) == 0)
1908
continue;
1909
1910
if (pass == NULL) {
1911
endpwent();
1912
return NULL;
1913
}
1914
return strdup(pass->pw_name);
1915
}
1916
1917
1918
/*
1919
* el-compatible wrapper to send TSTP on ^Z
1920
*/
1921
/* ARGSUSED */
1922
static unsigned char
1923
_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
1924
{
1925
(void)kill(0, SIGTSTP);
1926
return CC_NORM;
1927
}
1928
1929
static const char *
1930
/*ARGSUSED*/
1931
_rl_completion_append_character_function(const char *dummy
1932
__attribute__((__unused__)))
1933
{
1934
static char buf[2];
1935
buf[0] = (char)rl_completion_append_character;
1936
buf[1] = '\0';
1937
return buf;
1938
}
1939
1940
1941
/*
1942
* Display list of strings in columnar format on readline's output stream.
1943
* 'matches' is list of strings, 'len' is number of strings in 'matches',
1944
* 'max' is maximum length of string in 'matches'.
1945
*/
1946
void
1947
rl_display_match_list(char **matches, int len, int max)
1948
{
1949
1950
fn_display_match_list(e, matches, (size_t)len, (size_t)max,
1951
_rl_completion_append_character_function);
1952
}
1953
1954
/*
1955
* complete word at current point
1956
*/
1957
/* ARGSUSED */
1958
int
1959
rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
1960
{
1961
static ct_buffer_t wbreak_conv, sprefix_conv;
1962
const char *breakchars;
1963
1964
if (h == NULL || e == NULL)
1965
rl_initialize();
1966
1967
if (rl_inhibit_completion) {
1968
char arr[2];
1969
arr[0] = (char)invoking_key;
1970
arr[1] = '\0';
1971
el_insertstr(e, arr);
1972
return CC_REFRESH;
1973
}
1974
1975
if (rl_completion_word_break_hook != NULL)
1976
breakchars = (*rl_completion_word_break_hook)();
1977
else
1978
breakchars = rl_basic_word_break_characters;
1979
1980
_rl_update_pos();
1981
1982
/* Just look at how many global variables modify this operation! */
1983
return fn_complete2(e,
1984
(rl_compentry_func_t *)rl_completion_entry_function,
1985
rl_attempted_completion_function,
1986
ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
1987
ct_decode_string(breakchars, &sprefix_conv),
1988
_rl_completion_append_character_function,
1989
(size_t)rl_completion_query_items,
1990
&rl_completion_type, &rl_attempted_completion_over,
1991
&rl_point, &rl_end, 0);
1992
1993
1994
}
1995
1996
1997
/* ARGSUSED */
1998
static unsigned char
1999
_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
2000
{
2001
return (unsigned char)rl_complete(0, ch);
2002
}
2003
2004
/*
2005
* misc other functions
2006
*/
2007
2008
/*
2009
* bind key c to readline-type function func
2010
*/
2011
int
2012
rl_bind_key(int c, rl_command_func_t *func)
2013
{
2014
int retval = -1;
2015
2016
if (h == NULL || e == NULL)
2017
rl_initialize();
2018
2019
if (func == rl_insert) {
2020
/* XXX notice there is no range checking of ``c'' */
2021
e->el_map.key[c] = ED_INSERT;
2022
retval = 0;
2023
}
2024
return retval;
2025
}
2026
2027
2028
/*
2029
* read one key from input - handles chars pushed back
2030
* to input stream also
2031
*/
2032
int
2033
rl_read_key(void)
2034
{
2035
char fooarr[2 * sizeof(int)];
2036
2037
if (e == NULL || h == NULL)
2038
rl_initialize();
2039
2040
return el_getc(e, fooarr);
2041
}
2042
2043
2044
/*
2045
* reset the terminal
2046
*/
2047
/* ARGSUSED */
2048
int
2049
rl_reset_terminal(const char *p __attribute__((__unused__)))
2050
{
2051
2052
if (h == NULL || e == NULL)
2053
rl_initialize();
2054
el_reset(e);
2055
return 0;
2056
}
2057
2058
2059
/*
2060
* insert character ``c'' back into input stream, ``count'' times
2061
*/
2062
int
2063
rl_insert(int count, int c)
2064
{
2065
char arr[2];
2066
2067
if (h == NULL || e == NULL)
2068
rl_initialize();
2069
2070
/* XXX - int -> char conversion can lose on multichars */
2071
arr[0] = (char)c;
2072
arr[1] = '\0';
2073
2074
for (; count > 0; count--)
2075
el_push(e, arr);
2076
2077
return 0;
2078
}
2079
2080
int
2081
rl_insert_text(const char *text)
2082
{
2083
if (!text || *text == 0)
2084
return 0;
2085
2086
if (h == NULL || e == NULL)
2087
rl_initialize();
2088
2089
if (el_insertstr(e, text) < 0)
2090
return 0;
2091
return (int)strlen(text);
2092
}
2093
2094
/*ARGSUSED*/
2095
int
2096
rl_newline(int count __attribute__((__unused__)),
2097
int c __attribute__((__unused__)))
2098
{
2099
/*
2100
* Readline-4.0 appears to ignore the args.
2101
*/
2102
return rl_insert(1, '\n');
2103
}
2104
2105
/*ARGSUSED*/
2106
static unsigned char
2107
rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
2108
{
2109
if (map[c] == NULL)
2110
return CC_ERROR;
2111
2112
_rl_update_pos();
2113
2114
(*map[c])(1, c);
2115
2116
/* If rl_done was set by the above call, deal with it here */
2117
if (rl_done)
2118
return CC_EOF;
2119
2120
return CC_NORM;
2121
}
2122
2123
int
2124
rl_add_defun(const char *name, rl_command_func_t *fun, int c)
2125
{
2126
char dest[8];
2127
if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
2128
return -1;
2129
map[(unsigned char)c] = fun;
2130
el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
2131
vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
2132
el_set(e, EL_BIND, dest, name, NULL);
2133
return 0;
2134
}
2135
2136
void
2137
rl_callback_read_char(void)
2138
{
2139
int count = 0, done = 0;
2140
const char *buf = el_gets(e, &count);
2141
char *wbuf;
2142
2143
el_set(e, EL_UNBUFFERED, 1);
2144
if (buf == NULL || count-- <= 0)
2145
return;
2146
if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
2147
done = 1;
2148
if (buf[count] == '\n' || buf[count] == '\r')
2149
done = 2;
2150
2151
if (done && rl_linefunc != NULL) {
2152
el_set(e, EL_UNBUFFERED, 0);
2153
if (done == 2) {
2154
if ((wbuf = strdup(buf)) != NULL)
2155
wbuf[count] = '\0';
2156
RL_SETSTATE(RL_STATE_DONE);
2157
} else
2158
wbuf = NULL;
2159
(*(void (*)(const char *))rl_linefunc)(wbuf);
2160
}
2161
_rl_update_pos();
2162
}
2163
2164
void
2165
rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
2166
{
2167
if (e == NULL) {
2168
rl_initialize();
2169
}
2170
(void)rl_set_prompt(prompt);
2171
rl_linefunc = linefunc;
2172
el_set(e, EL_UNBUFFERED, 1);
2173
}
2174
2175
void
2176
rl_callback_handler_remove(void)
2177
{
2178
el_set(e, EL_UNBUFFERED, 0);
2179
rl_linefunc = NULL;
2180
}
2181
2182
void
2183
rl_redisplay(void)
2184
{
2185
char a[2];
2186
a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT];
2187
a[1] = '\0';
2188
el_push(e, a);
2189
rl_forced_update_display();
2190
}
2191
2192
int
2193
rl_get_previous_history(int count, int key)
2194
{
2195
char a[2];
2196
a[0] = (char)key;
2197
a[1] = '\0';
2198
while (count--)
2199
el_push(e, a);
2200
return 0;
2201
}
2202
2203
void
2204
/*ARGSUSED*/
2205
rl_prep_terminal(int meta_flag __attribute__((__unused__)))
2206
{
2207
el_set(e, EL_PREP_TERM, 1);
2208
}
2209
2210
void
2211
rl_deprep_terminal(void)
2212
{
2213
el_set(e, EL_PREP_TERM, 0);
2214
}
2215
2216
int
2217
rl_read_init_file(const char *s)
2218
{
2219
return el_source(e, s);
2220
}
2221
2222
int
2223
rl_parse_and_bind(const char *line)
2224
{
2225
const char **argv;
2226
int argc;
2227
Tokenizer *tok;
2228
2229
tok = tok_init(NULL);
2230
tok_str(tok, line, &argc, &argv);
2231
argc = el_parse(e, argc, argv);
2232
tok_end(tok);
2233
return argc ? 1 : 0;
2234
}
2235
2236
int
2237
rl_variable_bind(const char *var, const char *value)
2238
{
2239
/*
2240
* The proper return value is undocument, but this is what the
2241
* readline source seems to do.
2242
*/
2243
return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
2244
}
2245
2246
int
2247
rl_stuff_char(int c)
2248
{
2249
char buf[2];
2250
2251
buf[0] = (char)c;
2252
buf[1] = '\0';
2253
el_insertstr(e, buf);
2254
return 1;
2255
}
2256
2257
static int
2258
_rl_event_read_char(EditLine *el, wchar_t *wc)
2259
{
2260
char ch;
2261
int n;
2262
ssize_t num_read = 0;
2263
2264
ch = '\0';
2265
*wc = L'\0';
2266
while (rl_event_hook) {
2267
2268
(*rl_event_hook)();
2269
2270
#if defined(FIONREAD)
2271
if (ioctl(el->el_infd, FIONREAD, &n) < 0)
2272
return -1;
2273
if (n)
2274
num_read = read(el->el_infd, &ch, (size_t)1);
2275
else
2276
num_read = 0;
2277
#elif defined(F_SETFL) && defined(O_NDELAY)
2278
if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
2279
return -1;
2280
if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
2281
return -1;
2282
num_read = read(el->el_infd, &ch, 1);
2283
if (fcntl(el->el_infd, F_SETFL, n))
2284
return -1;
2285
#else
2286
/* not non-blocking, but what you gonna do? */
2287
num_read = read(el->el_infd, &ch, 1);
2288
return -1;
2289
#endif
2290
2291
if (num_read < 0 && errno == EAGAIN)
2292
continue;
2293
if (num_read == 0)
2294
continue;
2295
break;
2296
}
2297
if (!rl_event_hook)
2298
el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
2299
*wc = (wchar_t)ch;
2300
return (int)num_read;
2301
}
2302
2303
static void
2304
_rl_update_pos(void)
2305
{
2306
const LineInfo *li = el_line(e);
2307
2308
rl_point = (int)(li->cursor - li->buffer);
2309
rl_end = (int)(li->lastchar - li->buffer);
2310
rl_line_buffer[rl_end] = '\0';
2311
}
2312
2313
char *
2314
rl_copy_text(int from, int to)
2315
{
2316
const LineInfo *li;
2317
size_t len;
2318
char * out;
2319
2320
if (h == NULL || e == NULL)
2321
rl_initialize();
2322
2323
li = el_line(e);
2324
2325
if (from > to)
2326
return NULL;
2327
2328
if (li->buffer + from > li->lastchar)
2329
from = (int)(li->lastchar - li->buffer);
2330
2331
if (li->buffer + to > li->lastchar)
2332
to = (int)(li->lastchar - li->buffer);
2333
2334
len = (size_t)(to - from);
2335
out = el_malloc((size_t)len + 1);
2336
if (out == NULL)
2337
return NULL;
2338
(void)strlcpy(out, li->buffer + from , len);
2339
2340
return out;
2341
}
2342
2343
void
2344
rl_replace_line(const char * text, int clear_undo __attribute__((__unused__)))
2345
{
2346
if (!text || *text == 0)
2347
return;
2348
2349
if (h == NULL || e == NULL)
2350
rl_initialize();
2351
2352
el_replacestr(e, text);
2353
}
2354
2355
int
2356
rl_delete_text(int start, int end)
2357
{
2358
2359
if (h == NULL || e == NULL)
2360
rl_initialize();
2361
2362
return el_deletestr1(e, start, end);
2363
}
2364
2365
void
2366
rl_get_screen_size(int *rows, int *cols)
2367
{
2368
if (rows)
2369
el_get(e, EL_GETTC, "li", rows);
2370
if (cols)
2371
el_get(e, EL_GETTC, "co", cols);
2372
}
2373
2374
#define MAX_MESSAGE 160
2375
void
2376
rl_message(const char *format, ...)
2377
{
2378
char msg[MAX_MESSAGE];
2379
va_list args;
2380
2381
va_start(args, format);
2382
vsnprintf(msg, sizeof(msg), format, args);
2383
va_end(args);
2384
2385
rl_set_prompt(msg);
2386
rl_forced_update_display();
2387
}
2388
2389
void
2390
rl_set_screen_size(int rows, int cols)
2391
{
2392
char buf[64];
2393
(void)snprintf(buf, sizeof(buf), "%d", rows);
2394
el_set(e, EL_SETTC, "li", buf, NULL);
2395
(void)snprintf(buf, sizeof(buf), "%d", cols);
2396
el_set(e, EL_SETTC, "co", buf, NULL);
2397
}
2398
2399
char **
2400
rl_completion_matches(const char *str, rl_compentry_func_t *fun)
2401
{
2402
size_t len, max, i, j, min;
2403
char **list, *match, *a, *b;
2404
2405
len = 1;
2406
max = 10;
2407
if ((list = el_calloc(max, sizeof(*list))) == NULL)
2408
return NULL;
2409
2410
while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
2411
list[len++] = match;
2412
if (len == max) {
2413
char **nl;
2414
max += 10;
2415
if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
2416
goto out;
2417
list = nl;
2418
}
2419
}
2420
if (len == 1)
2421
goto out;
2422
list[len] = NULL;
2423
if (len == 2) {
2424
if ((list[0] = strdup(list[1])) == NULL)
2425
goto out;
2426
return list;
2427
}
2428
qsort(&list[1], len - 1, sizeof(*list),
2429
(int (*)(const void *, const void *)) strcmp);
2430
min = SIZE_MAX;
2431
for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
2432
b = list[i + 1];
2433
for (j = 0; a[j] && a[j] == b[j]; j++)
2434
continue;
2435
if (min > j)
2436
min = j;
2437
}
2438
if (min == 0 && *str) {
2439
if ((list[0] = strdup(str)) == NULL)
2440
goto out;
2441
} else {
2442
if ((list[0] = el_calloc(min + 1, sizeof(*list[0]))) == NULL)
2443
goto out;
2444
(void)memcpy(list[0], list[1], min);
2445
list[0][min] = '\0';
2446
}
2447
return list;
2448
2449
out:
2450
el_free(list);
2451
return NULL;
2452
}
2453
2454
char *
2455
rl_filename_completion_function (const char *text, int state)
2456
{
2457
return fn_filename_completion_function(text, state);
2458
}
2459
2460
void
2461
rl_forced_update_display(void)
2462
{
2463
el_set(e, EL_REFRESH);
2464
}
2465
2466
int
2467
_rl_abort_internal(void)
2468
{
2469
el_beep(e);
2470
longjmp(topbuf, 1);
2471
/*NOTREACHED*/
2472
}
2473
2474
int
2475
_rl_qsort_string_compare(char **s1, char **s2)
2476
{
2477
return strcoll(*s1, *s2);
2478
}
2479
2480
HISTORY_STATE *
2481
history_get_history_state(void)
2482
{
2483
HISTORY_STATE *hs;
2484
2485
if ((hs = el_malloc(sizeof(*hs))) == NULL)
2486
return NULL;
2487
hs->length = history_length;
2488
return hs;
2489
}
2490
2491
int
2492
/*ARGSUSED*/
2493
rl_kill_text(int from __attribute__((__unused__)),
2494
int to __attribute__((__unused__)))
2495
{
2496
return 0;
2497
}
2498
2499
Keymap
2500
rl_make_bare_keymap(void)
2501
{
2502
return NULL;
2503
}
2504
2505
Keymap
2506
rl_get_keymap(void)
2507
{
2508
return NULL;
2509
}
2510
2511
void
2512
/*ARGSUSED*/
2513
rl_set_keymap(Keymap k __attribute__((__unused__)))
2514
{
2515
}
2516
2517
int
2518
/*ARGSUSED*/
2519
rl_generic_bind(int type __attribute__((__unused__)),
2520
const char * keyseq __attribute__((__unused__)),
2521
const char * data __attribute__((__unused__)),
2522
Keymap k __attribute__((__unused__)))
2523
{
2524
return 0;
2525
}
2526
2527
int
2528
/*ARGSUSED*/
2529
rl_bind_key_in_map(int key __attribute__((__unused__)),
2530
rl_command_func_t *fun __attribute__((__unused__)),
2531
Keymap k __attribute__((__unused__)))
2532
{
2533
return 0;
2534
}
2535
2536
int
2537
rl_set_key(const char *keyseq __attribute__((__unused__)),
2538
rl_command_func_t *function __attribute__((__unused__)),
2539
Keymap k __attribute__((__unused__)))
2540
{
2541
return 0;
2542
}
2543
2544
/* unsupported, but needed by python */
2545
void
2546
rl_cleanup_after_signal(void)
2547
{
2548
}
2549
2550
int
2551
rl_on_new_line(void)
2552
{
2553
return 0;
2554
}
2555
2556
void
2557
rl_free_line_state(void)
2558
{
2559
}
2560
2561
int
2562
/*ARGSUSED*/
2563
rl_set_keyboard_input_timeout(int u __attribute__((__unused__)))
2564
{
2565
return 0;
2566
}
2567
2568
void
2569
rl_resize_terminal(void)
2570
{
2571
el_resize(e);
2572
}
2573
2574
void
2575
rl_reset_after_signal(void)
2576
{
2577
if (rl_prep_term_function)
2578
(*rl_prep_term_function)(1);
2579
}
2580
2581
void
2582
rl_echo_signal_char(int sig)
2583
{
2584
int c = tty_get_signal_character(e, sig);
2585
if (c == -1)
2586
return;
2587
re_putc(e, c, 0);
2588
}
2589
2590
int
2591
rl_crlf(void)
2592
{
2593
re_putc(e, '\n', 0);
2594
return 0;
2595
}
2596
2597
int
2598
rl_ding(void)
2599
{
2600
re_putc(e, '\a', 0);
2601
return 0;
2602
}
2603
2604
int
2605
rl_abort(int count, int key)
2606
{
2607
return count && key ? 0 : 0;
2608
}
2609
2610
int
2611
rl_set_keymap_name(const char *name, Keymap k)
2612
{
2613
return name && k ? 0 : 0;
2614
}
2615
2616
histdata_t
2617
free_history_entry(HIST_ENTRY *he)
2618
{
2619
return he ? NULL : NULL;
2620
}
2621
2622
void
2623
_rl_erase_entire_line(void)
2624
{
2625
}
2626
2627