~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to cmd-line-utils/libedit/readline.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD: readline.c,v 1.78 2009/02/05 19:15:26 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
#endif /* not lint && not SCCSID */
 
35
 
 
36
#include <sys/types.h>
 
37
#include <sys/stat.h>
 
38
#include <stdio.h>
 
39
#include <dirent.h>
 
40
#include <string.h>
 
41
#include <pwd.h>
 
42
#include <ctype.h>
 
43
#include <stdlib.h>
 
44
#include <unistd.h>
 
45
#include <limits.h>
 
46
#include <errno.h>
 
47
#include <fcntl.h>
 
48
#include <setjmp.h>
 
49
#ifdef HAVE_VIS_H
 
50
#include <vis.h>
 
51
#else
 
52
#include "np/vis.h"
 
53
#endif
 
54
#include "readline/readline.h"
 
55
#include "el.h"
 
56
#include "fcns.h"               /* for EL_NUM_FCNS */
 
57
#include "histedit.h"
 
58
#include "filecomplete.h"
 
59
 
 
60
void rl_prep_terminal(int);
 
61
void rl_deprep_terminal(void);
 
62
 
 
63
/* for rl_complete() */
 
64
#define TAB             '\r'
 
65
 
 
66
/* see comment at the #ifdef for sense of this */
 
67
/* #define GDB_411_HACK */
 
68
 
 
69
/* readline compatibility stuff - look at readline sources/documentation */
 
70
/* to see what these variables mean */
 
71
const char *rl_library_version = "EditLine wrapper";
 
72
static char empty[] = { '\0' };
 
73
static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
 
74
static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
 
75
    '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
 
76
char *rl_readline_name = empty;
 
77
FILE *rl_instream = NULL;
 
78
FILE *rl_outstream = NULL;
 
79
int rl_point = 0;
 
80
int rl_end = 0;
 
81
char *rl_line_buffer = NULL;
 
82
VCPFunction *rl_linefunc = NULL;
 
83
int rl_done = 0;
 
84
VFunction *rl_event_hook = NULL;
 
85
KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
 
86
    emacs_meta_keymap,
 
87
    emacs_ctlx_keymap;
 
88
 
 
89
int history_base = 1;           /* probably never subject to change */
 
90
int history_length = 0;
 
91
int max_input_history = 0;
 
92
char history_expansion_char = '!';
 
93
char history_subst_char = '^';
 
94
char *history_no_expand_chars = expand_chars;
 
95
Function *history_inhibit_expansion_function = NULL;
 
96
char *history_arg_extract(int start, int end, const char *str);
 
97
 
 
98
int rl_inhibit_completion = 0;
 
99
int rl_attempted_completion_over = 0;
 
100
char *rl_basic_word_break_characters = break_chars;
 
101
char *rl_completer_word_break_characters = NULL;
 
102
char *rl_completer_quote_characters = NULL;
 
103
Function *rl_completion_entry_function = NULL;
 
104
CPPFunction *rl_attempted_completion_function = NULL;
 
105
Function *rl_pre_input_hook = NULL;
 
106
Function *rl_startup1_hook = NULL;
 
107
int (*rl_getc_function)(FILE *) = NULL;
 
108
char *rl_terminal_name = NULL;
 
109
int rl_already_prompted = 0;
 
110
int rl_filename_completion_desired = 0;
 
111
int rl_ignore_completion_duplicates = 0;
 
112
int rl_catch_signals = 1;
 
113
int readline_echoing_p = 1;
 
114
int _rl_print_completions_horizontally = 0;
 
115
VFunction *rl_redisplay_function = NULL;
 
116
Function *rl_startup_hook = NULL;
 
117
VFunction *rl_completion_display_matches_hook = NULL;
 
118
VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
 
119
VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
 
120
 
 
121
/*
 
122
 * The current prompt string.
 
123
 */
 
124
char *rl_prompt = NULL;
 
125
/*
 
126
 * This is set to character indicating type of completion being done by
 
127
 * rl_complete_internal(); this is available for application completion
 
128
 * functions.
 
129
 */
 
130
int rl_completion_type = 0;
 
131
 
 
132
/*
 
133
 * If more than this number of items results from query for possible
 
134
 * completions, we ask user if they are sure to really display the list.
 
135
 */
 
136
int rl_completion_query_items = 100;
 
137
 
 
138
/*
 
139
 * List of characters which are word break characters, but should be left
 
140
 * in the parsed text when it is passed to the completion function.
 
141
 * Shell uses this to help determine what kind of completing to do.
 
142
 */
 
143
char *rl_special_prefixes = NULL;
 
144
 
 
145
/*
 
146
 * This is the character appended to the completed words if at the end of
 
147
 * the line. Default is ' ' (a space).
 
148
 */
 
149
int rl_completion_append_character = ' ';
 
150
 
 
151
/* stuff below is used internally by libedit for readline emulation */
 
152
 
 
153
static History *h = NULL;
 
154
static EditLine *e = NULL;
 
155
static Function *map[256];
 
156
static jmp_buf topbuf;
 
157
 
 
158
/* internal functions */
 
159
static unsigned char     _el_rl_complete(EditLine *, int);
 
160
static unsigned char     _el_rl_tstp(EditLine *, int);
 
161
static char             *_get_prompt(EditLine *);
 
162
static int               _getc_function(EditLine *, char *);
 
163
static HIST_ENTRY       *_move_history(int);
 
164
static int               _history_expand_command(const char *, size_t, size_t,
 
165
    char **);
 
166
static char             *_rl_compat_sub(const char *, const char *,
 
167
    const char *, int);
 
168
static int               _rl_event_read_char(EditLine *, char *);
 
169
static void              _rl_update_pos(void);
 
170
 
 
171
 
 
172
/* ARGSUSED */
 
173
static char *
 
174
_get_prompt(EditLine *el __attribute__((__unused__)))
 
175
{
 
176
        rl_already_prompted = 1;
 
177
        return (rl_prompt);
 
178
}
 
179
 
 
180
 
 
181
/*
 
182
 * generic function for moving around history
 
183
 */
 
184
static HIST_ENTRY *
 
185
_move_history(int op)
 
186
{
 
187
        HistEvent ev;
 
188
        static HIST_ENTRY rl_he;
 
189
 
 
190
        if (history(h, &ev, op) != 0)
 
191
                return (HIST_ENTRY *) NULL;
 
192
 
 
193
        rl_he.line = ev.str;
 
194
        rl_he.data = NULL;
 
195
 
 
196
        return (&rl_he);
 
197
}
 
198
 
 
199
 
 
200
/*
 
201
 * read one key from user defined input function
 
202
 */
 
203
static int
 
204
/*ARGSUSED*/
 
205
_getc_function(EditLine *el, char *c)
 
206
{
 
207
        int i;
 
208
 
 
209
        i = (*rl_getc_function)(NULL);
 
210
        if (i == -1)
 
211
                return 0;
 
212
        *c = i;
 
213
        return 1;
 
214
}
 
215
 
 
216
 
 
217
/*
 
218
 * READLINE compatibility stuff
 
219
 */
 
220
 
 
221
/*
 
222
 * Set the prompt
 
223
 */
 
224
int
 
225
rl_set_prompt(const char *prompt)
 
226
{
 
227
        if (!prompt)
 
228
                prompt = "";
 
229
        if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) 
 
230
                return 0;
 
231
        if (rl_prompt)
 
232
                free(rl_prompt);
 
233
        rl_prompt = strdup(prompt);
 
234
        return rl_prompt == NULL ? -1 : 0;
 
235
}
 
236
 
 
237
/*
 
238
 * initialize rl compat stuff
 
239
 */
 
240
int
 
241
rl_initialize(void)
 
242
{
 
243
        HistEvent ev;
 
244
        const LineInfo *li;
 
245
        int editmode = 1;
 
246
        struct termios t;
 
247
 
 
248
        if (e != NULL)
 
249
                el_end(e);
 
250
        if (h != NULL)
 
251
                history_end(h);
 
252
 
 
253
        if (!rl_instream)
 
254
                rl_instream = stdin;
 
255
        if (!rl_outstream)
 
256
                rl_outstream = stdout;
 
257
 
 
258
        /*
 
259
         * See if we don't really want to run the editor
 
260
         */
 
261
        if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
 
262
                editmode = 0;
 
263
 
 
264
        e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
 
265
 
 
266
        if (!editmode)
 
267
                el_set(e, EL_EDITMODE, 0);
 
268
 
 
269
        h = history_init();
 
270
        if (!e || !h)
 
271
                return (-1);
 
272
 
 
273
        history(h, &ev, H_SETSIZE, INT_MAX);    /* unlimited */
 
274
        history_length = 0;
 
275
        max_input_history = INT_MAX;
 
276
        el_set(e, EL_HIST, history, h);
 
277
 
 
278
        /* setup getc function if valid */
 
279
        if (rl_getc_function)
 
280
                el_set(e, EL_GETCFN, _getc_function);
 
281
 
 
282
        /* for proper prompt printing in readline() */
 
283
        if (rl_set_prompt("") == -1) {
 
284
                history_end(h);
 
285
                el_end(e);
 
286
                return -1;
 
287
        }
 
288
        el_set(e, EL_PROMPT, _get_prompt);
 
289
        el_set(e, EL_SIGNAL, rl_catch_signals);
 
290
 
 
291
        /* set default mode to "emacs"-style and read setting afterwards */
 
292
        /* so this can be overriden */
 
293
        el_set(e, EL_EDITOR, "emacs");
 
294
        if (rl_terminal_name != NULL)
 
295
                el_set(e, EL_TERMINAL, rl_terminal_name);
 
296
        else
 
297
                el_get(e, EL_TERMINAL, &rl_terminal_name);
 
298
 
 
299
        /*
 
300
         * Word completion - this has to go AFTER rebinding keys
 
301
         * to emacs-style.
 
302
         */
 
303
        el_set(e, EL_ADDFN, "rl_complete",
 
304
            "ReadLine compatible completion function",
 
305
            _el_rl_complete);
 
306
        el_set(e, EL_BIND, "^I", "rl_complete", NULL);
 
307
 
 
308
        /*
 
309
         * Send TSTP when ^Z is pressed.
 
310
         */
 
311
        el_set(e, EL_ADDFN, "rl_tstp",
 
312
            "ReadLine compatible suspend function",
 
313
            _el_rl_tstp);
 
314
        el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
 
315
                
 
316
        /* read settings from configuration file */
 
317
        el_source(e, NULL);
 
318
 
 
319
        /*
 
320
         * Unfortunately, some applications really do use rl_point
 
321
         * and rl_line_buffer directly.
 
322
         */
 
323
        li = el_line(e);
 
324
        /* a cheesy way to get rid of const cast. */
 
325
        rl_line_buffer = memchr(li->buffer, *li->buffer, 1);
 
326
        _rl_update_pos();
 
327
 
 
328
        if (rl_startup_hook)
 
329
                (*rl_startup_hook)(NULL, 0);
 
330
 
 
331
        return (0);
 
332
}
 
333
 
 
334
 
 
335
/*
 
336
 * read one line from input stream and return it, chomping
 
337
 * trailing newline (if there is any)
 
338
 */
 
339
char *
 
340
readline(const char *p)
 
341
{
 
342
        HistEvent ev;
 
343
        const char * volatile prompt = p;
 
344
        int count;
 
345
        const char *ret;
 
346
        char *buf;
 
347
        static int used_event_hook;
 
348
 
 
349
        if (e == NULL || h == NULL)
 
350
                rl_initialize();
 
351
 
 
352
        rl_done = 0;
 
353
 
 
354
        (void)setjmp(topbuf);
 
355
 
 
356
        /* update prompt accordingly to what has been passed */
 
357
        if (rl_set_prompt(prompt) == -1)
 
358
                return NULL;
 
359
 
 
360
        if (rl_pre_input_hook)
 
361
                (*rl_pre_input_hook)(NULL, 0);
 
362
 
 
363
        if (rl_event_hook && !(e->el_flags&NO_TTY)) {
 
364
                el_set(e, EL_GETCFN, _rl_event_read_char);
 
365
                used_event_hook = 1;
 
366
        }
 
367
 
 
368
        if (!rl_event_hook && used_event_hook) {
 
369
                el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
 
370
                used_event_hook = 0;
 
371
        }
 
372
 
 
373
        rl_already_prompted = 0;
 
374
 
 
375
        /* get one line from input stream */
 
376
        ret = el_gets(e, &count);
 
377
 
 
378
        if (ret && count > 0) {
 
379
                int lastidx;
 
380
 
 
381
                buf = strdup(ret);
 
382
                if (buf == NULL)
 
383
                        return NULL;
 
384
                lastidx = count - 1;
 
385
                if (buf[lastidx] == '\n')
 
386
                        buf[lastidx] = '\0';
 
387
        } else
 
388
                buf = NULL;
 
389
 
 
390
        history(h, &ev, H_GETSIZE);
 
391
        history_length = ev.num;
 
392
 
 
393
        return buf;
 
394
}
 
395
 
 
396
/*
 
397
 * history functions
 
398
 */
 
399
 
 
400
/*
 
401
 * is normally called before application starts to use
 
402
 * history expansion functions
 
403
 */
 
404
void
 
405
using_history(void)
 
406
{
 
407
        if (h == NULL || e == NULL)
 
408
                rl_initialize();
 
409
}
 
410
 
 
411
 
 
412
/*
 
413
 * substitute ``what'' with ``with'', returning resulting string; if
 
414
 * globally == 1, substitutes all occurrences of what, otherwise only the
 
415
 * first one
 
416
 */
 
417
static char *
 
418
_rl_compat_sub(const char *str, const char *what, const char *with,
 
419
    int globally)
 
420
{
 
421
        const   char    *s;
 
422
        char    *r, *result;
 
423
        size_t  len, with_len, what_len;
 
424
 
 
425
        len = strlen(str);
 
426
        with_len = strlen(with);
 
427
        what_len = strlen(what);
 
428
 
 
429
        /* calculate length we need for result */
 
430
        s = str;
 
431
        while (*s) {
 
432
                if (*s == *what && !strncmp(s, what, what_len)) {
 
433
                        len += with_len - what_len;
 
434
                        if (!globally)
 
435
                                break;
 
436
                        s += what_len;
 
437
                } else
 
438
                        s++;
 
439
        }
 
440
        r = result = malloc(len + 1);
 
441
        if (result == NULL)
 
442
                return NULL;
 
443
        s = str;
 
444
        while (*s) {
 
445
                if (*s == *what && !strncmp(s, what, what_len)) {
 
446
                        (void)strncpy(r, with, with_len);
 
447
                        r += with_len;
 
448
                        s += what_len;
 
449
                        if (!globally) {
 
450
                                (void)strcpy(r, s);
 
451
                                return(result);
 
452
                        }
 
453
                } else
 
454
                        *r++ = *s++;
 
455
        }
 
456
        *r = '\0';
 
457
        return(result);
 
458
}
 
459
 
 
460
static  char    *last_search_pat;       /* last !?pat[?] search pattern */
 
461
static  char    *last_search_match;     /* last !?pat[?] that matched */
 
462
 
 
463
const char *
 
464
get_history_event(const char *cmd, int *cindex, int qchar)
 
465
{
 
466
        int idx, sign, sub, num, begin, ret;
 
467
        size_t len;
 
468
        char    *pat;
 
469
        const char *rptr;
 
470
        HistEvent ev;
 
471
 
 
472
        idx = *cindex;
 
473
        if (cmd[idx++] != history_expansion_char)
 
474
                return(NULL);
 
475
 
 
476
        /* find out which event to take */
 
477
        if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
 
478
                if (history(h, &ev, H_FIRST) != 0)
 
479
                        return(NULL);
 
480
                *cindex = cmd[idx]? (idx + 1):idx;
 
481
                return(ev.str);
 
482
        }
 
483
        sign = 0;
 
484
        if (cmd[idx] == '-') {
 
485
                sign = 1;
 
486
                idx++;
 
487
        }
 
488
 
 
489
        if ('0' <= cmd[idx] && cmd[idx] <= '9') {
 
490
                HIST_ENTRY *rl_he;
 
491
 
 
492
                num = 0;
 
493
                while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
 
494
                        num = num * 10 + cmd[idx] - '0';
 
495
                        idx++;
 
496
                }
 
497
                if (sign)
 
498
                        num = history_length - num + 1;
 
499
 
 
500
                if (!(rl_he = history_get(num)))
 
501
                        return(NULL);
 
502
 
 
503
                *cindex = idx;
 
504
                return(rl_he->line);
 
505
        }
 
506
        sub = 0;
 
507
        if (cmd[idx] == '?') {
 
508
                sub = 1;
 
509
                idx++;
 
510
        }
 
511
        begin = idx;
 
512
        while (cmd[idx]) {
 
513
                if (cmd[idx] == '\n')
 
514
                        break;
 
515
                if (sub && cmd[idx] == '?')
 
516
                        break;
 
517
                if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
 
518
                                    || cmd[idx] == '\t' || cmd[idx] == qchar))
 
519
                        break;
 
520
                idx++;
 
521
        }
 
522
        len = idx - begin;
 
523
        if (sub && cmd[idx] == '?')
 
524
                idx++;
 
525
        if (sub && len == 0 && last_search_pat && *last_search_pat)
 
526
                pat = last_search_pat;
 
527
        else if (len == 0)
 
528
                return(NULL);
 
529
        else {
 
530
                if ((pat = malloc(len + 1)) == NULL)
 
531
                        return NULL;
 
532
                (void)strncpy(pat, cmd + begin, len);
 
533
                pat[len] = '\0';
 
534
        }
 
535
 
 
536
        if (history(h, &ev, H_CURR) != 0) {
 
537
                if (pat != last_search_pat)
 
538
                        free(pat);
 
539
                return (NULL);
 
540
        }
 
541
        num = ev.num;
 
542
 
 
543
        if (sub) {
 
544
                if (pat != last_search_pat) {
 
545
                        if (last_search_pat)
 
546
                                free(last_search_pat);
 
547
                        last_search_pat = pat;
 
548
                }
 
549
                ret = history_search(pat, -1);
 
550
        } else
 
551
                ret = history_search_prefix(pat, -1);
 
552
 
 
553
        if (ret == -1) {
 
554
                /* restore to end of list on failed search */
 
555
                history(h, &ev, H_FIRST);
 
556
                (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
 
557
                if (pat != last_search_pat)
 
558
                        free(pat);
 
559
                return(NULL);
 
560
        }
 
561
 
 
562
        if (sub && len) {
 
563
                if (last_search_match && last_search_match != pat)
 
564
                        free(last_search_match);
 
565
                last_search_match = pat;
 
566
        }
 
567
 
 
568
        if (pat != last_search_pat)
 
569
                free(pat);
 
570
 
 
571
        if (history(h, &ev, H_CURR) != 0)
 
572
                return(NULL);
 
573
        *cindex = idx;
 
574
        rptr = ev.str;
 
575
 
 
576
        /* roll back to original position */
 
577
        (void)history(h, &ev, H_SET, num);
 
578
 
 
579
        return rptr;
 
580
}
 
581
 
 
582
/*
 
583
 * the real function doing history expansion - takes as argument command
 
584
 * to do and data upon which the command should be executed
 
585
 * does expansion the way I've understood readline documentation
 
586
 *
 
587
 * returns 0 if data was not modified, 1 if it was and 2 if the string
 
588
 * should be only printed and not executed; in case of error,
 
589
 * returns -1 and *result points to NULL
 
590
 * it's callers responsibility to free() string returned in *result
 
591
 */
 
592
static int
 
593
_history_expand_command(const char *command, size_t offs, size_t cmdlen,
 
594
    char **result)
 
595
{
 
596
        char *tmp, *search = NULL, *aptr;
 
597
        const char *ptr, *cmd;
 
598
        static char *from = NULL, *to = NULL;
 
599
        int start, end, idx, has_mods = 0;
 
600
        int p_on = 0, g_on = 0;
 
601
 
 
602
        *result = NULL;
 
603
        aptr = NULL;
 
604
        ptr = NULL;
 
605
 
 
606
        /* First get event specifier */
 
607
        idx = 0;
 
608
 
 
609
        if (strchr(":^*$", command[offs + 1])) {
 
610
                char str[4];
 
611
                /*
 
612
                * "!:" is shorthand for "!!:".
 
613
                * "!^", "!*" and "!$" are shorthand for
 
614
                * "!!:^", "!!:*" and "!!:$" respectively.
 
615
                */
 
616
                str[0] = str[1] = '!';
 
617
                str[2] = '0';
 
618
                ptr = get_history_event(str, &idx, 0);
 
619
                idx = (command[offs + 1] == ':')? 1:0;
 
620
                has_mods = 1;
 
621
        } else {
 
622
                if (command[offs + 1] == '#') {
 
623
                        /* use command so far */
 
624
                        if ((aptr = malloc(offs + 1)) == NULL)
 
625
                                return -1;
 
626
                        (void)strncpy(aptr, command, offs);
 
627
                        aptr[offs] = '\0';
 
628
                        idx = 1;
 
629
                } else {
 
630
                        int     qchar;
 
631
 
 
632
                        qchar = (offs > 0 && command[offs - 1] == '"')? '"':0;
 
633
                        ptr = get_history_event(command + offs, &idx, qchar);
 
634
                }
 
635
                has_mods = command[offs + idx] == ':';
 
636
        }
 
637
 
 
638
        if (ptr == NULL && aptr == NULL)
 
639
                return(-1);
 
640
 
 
641
        if (!has_mods) {
 
642
                *result = strdup(aptr? aptr : ptr);
 
643
                if (aptr)
 
644
                        free(aptr);
 
645
                return(1);
 
646
        }
 
647
 
 
648
        cmd = command + offs + idx + 1;
 
649
 
 
650
        /* Now parse any word designators */
 
651
 
 
652
        if (*cmd == '%')        /* last word matched by ?pat? */
 
653
                tmp = strdup(last_search_match? last_search_match:"");
 
654
        else if (strchr("^*$-0123456789", *cmd)) {
 
655
                start = end = -1;
 
656
                if (*cmd == '^')
 
657
                        start = end = 1, cmd++;
 
658
                else if (*cmd == '$')
 
659
                        start = -1, cmd++;
 
660
                else if (*cmd == '*')
 
661
                        start = 1, cmd++;
 
662
               else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
 
663
                        start = 0;
 
664
                        while (*cmd && '0' <= *cmd && *cmd <= '9')
 
665
                                start = start * 10 + *cmd++ - '0';
 
666
 
 
667
                        if (*cmd == '-') {
 
668
                                if (isdigit((unsigned char) cmd[1])) {
 
669
                                        cmd++;
 
670
                                        end = 0;
 
671
                                        while (*cmd && '0' <= *cmd && *cmd <= '9')
 
672
                                                end = end * 10 + *cmd++ - '0';
 
673
                                } else if (cmd[1] == '$') {
 
674
                                        cmd += 2;
 
675
                                        end = -1;
 
676
                                } else {
 
677
                                        cmd++;
 
678
                                        end = -2;
 
679
                                }
 
680
                        } else if (*cmd == '*')
 
681
                                end = -1, cmd++;
 
682
                        else
 
683
                                end = start;
 
684
                }
 
685
                tmp = history_arg_extract(start, end, aptr? aptr:ptr);
 
686
                if (tmp == NULL) {
 
687
                        (void)fprintf(rl_outstream, "%s: Bad word specifier",
 
688
                            command + offs + idx);
 
689
                        if (aptr)
 
690
                                free(aptr);
 
691
                        return(-1);
 
692
                }
 
693
        } else
 
694
                tmp = strdup(aptr? aptr:ptr);
 
695
 
 
696
        if (aptr)
 
697
                free(aptr);
 
698
 
 
699
        if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
 
700
                *result = tmp;
 
701
                return(1);
 
702
        }
 
703
 
 
704
        for (; *cmd; cmd++) {
 
705
                if (*cmd == ':')
 
706
                        continue;
 
707
                else if (*cmd == 'h') {         /* remove trailing path */
 
708
                        if ((aptr = strrchr(tmp, '/')) != NULL)
 
709
                                *aptr = '\0';
 
710
                } else if (*cmd == 't') {       /* remove leading path */
 
711
                        if ((aptr = strrchr(tmp, '/')) != NULL) {
 
712
                                aptr = strdup(aptr + 1);
 
713
                                free(tmp);
 
714
                                tmp = aptr;
 
715
                        }
 
716
                } else if (*cmd == 'r') {       /* remove trailing suffix */
 
717
                        if ((aptr = strrchr(tmp, '.')) != NULL)
 
718
                                *aptr = '\0';
 
719
                } else if (*cmd == 'e') {       /* remove all but suffix */
 
720
                        if ((aptr = strrchr(tmp, '.')) != NULL) {
 
721
                                aptr = strdup(aptr);
 
722
                                free(tmp);
 
723
                                tmp = aptr;
 
724
                        }
 
725
                } else if (*cmd == 'p')         /* print only */
 
726
                        p_on = 1;
 
727
                else if (*cmd == 'g')
 
728
                        g_on = 2;
 
729
                else if (*cmd == 's' || *cmd == '&') {
 
730
                        char *what, *with, delim;
 
731
                        size_t len, from_len;
 
732
                        size_t size;
 
733
 
 
734
                        if (*cmd == '&' && (from == NULL || to == NULL))
 
735
                                continue;
 
736
                        else if (*cmd == 's') {
 
737
                                delim = *(++cmd), cmd++;
 
738
                                size = 16;
 
739
                                what = realloc(from, size);
 
740
                                if (what == NULL) {
 
741
                                        free(from);
 
742
                                        free(tmp);
 
743
                                        return 0;
 
744
                                }
 
745
                                len = 0;
 
746
                                for (; *cmd && *cmd != delim; cmd++) {
 
747
                                        if (*cmd == '\\' && cmd[1] == delim)
 
748
                                                cmd++;
 
749
                                        if (len >= size) {
 
750
                                                char *nwhat;
 
751
                                                nwhat = realloc(what,
 
752
                                                                (size <<= 1));
 
753
                                                if (nwhat == NULL) {
 
754
                                                        free(what);
 
755
                                                        free(tmp);
 
756
                                                        return 0;
 
757
                                                }
 
758
                                                what = nwhat;
 
759
                                        }
 
760
                                        what[len++] = *cmd;
 
761
                                }
 
762
                                what[len] = '\0';
 
763
                                from = what;
 
764
                                if (*what == '\0') {
 
765
                                        free(what);
 
766
                                        if (search) {
 
767
                                                from = strdup(search);
 
768
                                                if (from == NULL) {
 
769
                                                        free(tmp);
 
770
                                                        return 0;
 
771
                                                }
 
772
                                        } else {
 
773
                                                from = NULL;
 
774
                                                free(tmp);
 
775
                                                return (-1);
 
776
                                        }
 
777
                                }
 
778
                                cmd++;  /* shift after delim */
 
779
                                if (!*cmd)
 
780
                                        continue;
 
781
 
 
782
                                size = 16;
 
783
                                with = realloc(to, size);
 
784
                                if (with == NULL) {
 
785
                                        free(to);
 
786
                                        free(tmp);
 
787
                                        return -1;
 
788
                                }
 
789
                                len = 0;
 
790
                                from_len = strlen(from);
 
791
                                for (; *cmd && *cmd != delim; cmd++) {
 
792
                                        if (len + from_len + 1 >= size) {
 
793
                                                char *nwith;
 
794
                                                size += from_len + 1;
 
795
                                                nwith = realloc(with, size);
 
796
                                                if (nwith == NULL) {
 
797
                                                        free(with);
 
798
                                                        free(tmp);
 
799
                                                        return -1;
 
800
                                                }
 
801
                                                with = nwith;
 
802
                                        }
 
803
                                        if (*cmd == '&') {
 
804
                                                /* safe */
 
805
                                                (void)strcpy(&with[len], from);
 
806
                                                len += from_len;
 
807
                                                continue;
 
808
                                        }
 
809
                                        if (*cmd == '\\'
 
810
                                            && (*(cmd + 1) == delim
 
811
                                                || *(cmd + 1) == '&'))
 
812
                                                cmd++;
 
813
                                        with[len++] = *cmd;
 
814
                                }
 
815
                                with[len] = '\0';
 
816
                                to = with;
 
817
                        }
 
818
 
 
819
                        aptr = _rl_compat_sub(tmp, from, to, g_on);
 
820
                        if (aptr) {
 
821
                                free(tmp);
 
822
                                tmp = aptr;
 
823
                        }
 
824
                        g_on = 0;
 
825
                }
 
826
        }
 
827
        *result = tmp;
 
828
        return (p_on? 2:1);
 
829
}
 
830
 
 
831
 
 
832
/*
 
833
 * csh-style history expansion
 
834
 */
 
835
int
 
836
history_expand(char *str, char **output)
 
837
{
 
838
        int ret = 0;
 
839
        size_t idx, i, size;
 
840
        char *tmp, *result;
 
841
 
 
842
        if (h == NULL || e == NULL)
 
843
                rl_initialize();
 
844
 
 
845
        if (history_expansion_char == 0) {
 
846
                *output = strdup(str);
 
847
                return(0);
 
848
        }
 
849
 
 
850
        *output = NULL;
 
851
        if (str[0] == history_subst_char) {
 
852
                /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
 
853
                *output = malloc(strlen(str) + 4 + 1);
 
854
                if (*output == NULL)
 
855
                        return 0;
 
856
                (*output)[0] = (*output)[1] = history_expansion_char;
 
857
                (*output)[2] = ':';
 
858
                (*output)[3] = 's';
 
859
                (void)strcpy((*output) + 4, str);
 
860
                str = *output;
 
861
        } else {
 
862
                *output = strdup(str);
 
863
                if (*output == NULL)
 
864
                        return 0;
 
865
        }
 
866
 
 
867
#define ADD_STRING(what, len, fr)                                       \
 
868
        {                                                               \
 
869
                if (idx + len + 1 > size) {                             \
 
870
                        char *nresult = realloc(result, (size += len + 1));\
 
871
                        if (nresult == NULL) {                          \
 
872
                                free(*output);                          \
 
873
                                if (/*CONSTCOND*/fr)                    \
 
874
                                        free(tmp);                      \
 
875
                                return 0;                               \
 
876
                        }                                               \
 
877
                        result = nresult;                               \
 
878
                }                                                       \
 
879
                (void)strncpy(&result[idx], what, len);                 \
 
880
                idx += len;                                             \
 
881
                result[idx] = '\0';                                     \
 
882
        }
 
883
 
 
884
        result = NULL;
 
885
        size = idx = 0;
 
886
        tmp = NULL;
 
887
        for (i = 0; str[i];) {
 
888
                int qchar, loop_again;
 
889
                size_t len, start, j;
 
890
 
 
891
                qchar = 0;
 
892
                loop_again = 1;
 
893
                start = j = i;
 
894
loop:
 
895
                for (; str[j]; j++) {
 
896
                        if (str[j] == '\\' &&
 
897
                            str[j + 1] == history_expansion_char) {
 
898
                                (void)strcpy(&str[j], &str[j + 1]);
 
899
                                continue;
 
900
                        }
 
901
                        if (!loop_again) {
 
902
                                if (isspace((unsigned char) str[j])
 
903
                                    || str[j] == qchar)
 
904
                                        break;
 
905
                        }
 
906
                        if (str[j] == history_expansion_char
 
907
                            && !strchr(history_no_expand_chars, str[j + 1])
 
908
                            && (!history_inhibit_expansion_function ||
 
909
                            (*history_inhibit_expansion_function)(str,
 
910
                            (int)j) == 0))
 
911
                                break;
 
912
                }
 
913
 
 
914
                if (str[j] && loop_again) {
 
915
                        i = j;
 
916
                        qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
 
917
                        j++;
 
918
                        if (str[j] == history_expansion_char)
 
919
                                j++;
 
920
                        loop_again = 0;
 
921
                        goto loop;
 
922
                }
 
923
                len = i - start;
 
924
                ADD_STRING(&str[start], len, 0);
 
925
 
 
926
                if (str[i] == '\0' || str[i] != history_expansion_char) {
 
927
                        len = j - i;
 
928
                        ADD_STRING(&str[i], len, 0);
 
929
                        if (start == 0)
 
930
                                ret = 0;
 
931
                        else
 
932
                                ret = 1;
 
933
                        break;
 
934
                }
 
935
                ret = _history_expand_command (str, i, (j - i), &tmp);
 
936
                if (ret > 0 && tmp) {
 
937
                        len = strlen(tmp);
 
938
                        ADD_STRING(tmp, len, 1);
 
939
                }
 
940
                if (tmp) {
 
941
                        free(tmp);
 
942
                        tmp = NULL;
 
943
                }
 
944
                i = j;
 
945
        }
 
946
 
 
947
        /* ret is 2 for "print only" option */
 
948
        if (ret == 2) {
 
949
                add_history(result);
 
950
#ifdef GDB_411_HACK
 
951
                /* gdb 4.11 has been shipped with readline, where */
 
952
                /* history_expand() returned -1 when the line     */
 
953
                /* should not be executed; in readline 2.1+       */
 
954
                /* it should return 2 in such a case              */
 
955
                ret = -1;
 
956
#endif
 
957
        }
 
958
        free(*output);
 
959
        *output = result;
 
960
 
 
961
        return (ret);
 
962
}
 
963
 
 
964
/*
 
965
* Return a string consisting of arguments of "str" from "start" to "end".
 
966
*/
 
967
char *
 
968
history_arg_extract(int start, int end, const char *str)
 
969
{
 
970
        size_t  i, len, max;
 
971
        char    **arr, *result;
 
972
 
 
973
        arr = history_tokenize(str);
 
974
        if (!arr)
 
975
                return(NULL);
 
976
        if (arr && *arr == NULL) {
 
977
                free(arr);
 
978
                return(NULL);
 
979
        }
 
980
 
 
981
        for (max = 0; arr[max]; max++)
 
982
                continue;
 
983
        max--;
 
984
 
 
985
        if (start == '$')
 
986
                start = max;
 
987
        if (end == '$')
 
988
                end = max;
 
989
        if (end < 0)
 
990
                end = max + end + 1;
 
991
        if (start < 0)
 
992
                start = end;
 
993
 
 
994
        if (start < 0 || end < 0 || (size_t)start > max || (size_t)end > max || start > end)
 
995
                return(NULL);
 
996
 
 
997
        for (i = start, len = 0; i <= (size_t)end; i++)
 
998
                len += strlen(arr[i]) + 1;
 
999
        len++;
 
1000
        result = malloc(len);
 
1001
        if (result == NULL)
 
1002
                return NULL;
 
1003
 
 
1004
        for (i = start, len = 0; i <= (size_t)end; i++) {
 
1005
                (void)strcpy(result + len, arr[i]);
 
1006
                len += strlen(arr[i]);
 
1007
                if (i < (size_t)end)
 
1008
                        result[len++] = ' ';
 
1009
        }
 
1010
        result[len] = '\0';
 
1011
 
 
1012
        for (i = 0; arr[i]; i++)
 
1013
                free(arr[i]);
 
1014
        free(arr);
 
1015
 
 
1016
        return(result);
 
1017
}
 
1018
 
 
1019
/*
 
1020
 * Parse the string into individual tokens,
 
1021
 * similar to how shell would do it.
 
1022
 */
 
1023
char **
 
1024
history_tokenize(const char *str)
 
1025
{
 
1026
        int size = 1, idx = 0, i, start;
 
1027
        size_t len;
 
1028
        char **result = NULL, *temp, delim = '\0';
 
1029
 
 
1030
        for (i = 0; str[i];) {
 
1031
                while (isspace((unsigned char) str[i]))
 
1032
                        i++;
 
1033
                start = i;
 
1034
                for (; str[i];) {
 
1035
                        if (str[i] == '\\') {
 
1036
                                if (str[i+1] != '\0')
 
1037
                                        i++;
 
1038
                        } else if (str[i] == delim)
 
1039
                                delim = '\0';
 
1040
                        else if (!delim &&
 
1041
                                    (isspace((unsigned char) str[i]) ||
 
1042
                                strchr("()<>;&|$", str[i])))
 
1043
                                break;
 
1044
                        else if (!delim && strchr("'`\"", str[i]))
 
1045
                                delim = str[i];
 
1046
                        if (str[i])
 
1047
                                i++;
 
1048
                }
 
1049
 
 
1050
                if (idx + 2 >= size) {
 
1051
                        char **nresult;
 
1052
                        size <<= 1;
 
1053
                        nresult = realloc(result, size * sizeof(char *));
 
1054
                        if (nresult == NULL) {
 
1055
                                free(result);
 
1056
                                return NULL;
 
1057
                        }
 
1058
                        result = nresult;
 
1059
                }
 
1060
                len = i - start;
 
1061
                temp = malloc(len + 1);
 
1062
                if (temp == NULL) {
 
1063
                        for (i = 0; i < idx; i++)
 
1064
                                free(result[i]);
 
1065
                        free(result);
 
1066
                        return NULL;
 
1067
                }
 
1068
                (void)strncpy(temp, &str[start], len);
 
1069
                temp[len] = '\0';
 
1070
                result[idx++] = temp;
 
1071
                result[idx] = NULL;
 
1072
                if (str[i])
 
1073
                        i++;
 
1074
        }
 
1075
        return (result);
 
1076
}
 
1077
 
 
1078
 
 
1079
/*
 
1080
 * limit size of history record to ``max'' events
 
1081
 */
 
1082
void
 
1083
stifle_history(int max)
 
1084
{
 
1085
        HistEvent ev;
 
1086
 
 
1087
        if (h == NULL || e == NULL)
 
1088
                rl_initialize();
 
1089
 
 
1090
        if (history(h, &ev, H_SETSIZE, max) == 0)
 
1091
                max_input_history = max;
 
1092
}
 
1093
 
 
1094
 
 
1095
/*
 
1096
 * "unlimit" size of history - set the limit to maximum allowed int value
 
1097
 */
 
1098
int
 
1099
unstifle_history(void)
 
1100
{
 
1101
        HistEvent ev;
 
1102
        int omax;
 
1103
 
 
1104
        history(h, &ev, H_SETSIZE, INT_MAX);
 
1105
        omax = max_input_history;
 
1106
        max_input_history = INT_MAX;
 
1107
        return (omax);          /* some value _must_ be returned */
 
1108
}
 
1109
 
 
1110
 
 
1111
int
 
1112
history_is_stifled(void)
 
1113
{
 
1114
 
 
1115
        /* cannot return true answer */
 
1116
        return (max_input_history != INT_MAX);
 
1117
}
 
1118
 
 
1119
 
 
1120
/*
 
1121
 * read history from a file given
 
1122
 */
 
1123
int
 
1124
read_history(const char *filename)
 
1125
{
 
1126
        HistEvent ev;
 
1127
 
 
1128
        if (h == NULL || e == NULL)
 
1129
                rl_initialize();
 
1130
        return (history(h, &ev, H_LOAD, filename) == -1);
 
1131
}
 
1132
 
 
1133
 
 
1134
/*
 
1135
 * write history to a file given
 
1136
 */
 
1137
int
 
1138
write_history(const char *filename)
 
1139
{
 
1140
        HistEvent ev;
 
1141
 
 
1142
        if (h == NULL || e == NULL)
 
1143
                rl_initialize();
 
1144
        return (history(h, &ev, H_SAVE, filename) == -1);
 
1145
}
 
1146
 
 
1147
 
 
1148
/*
 
1149
 * returns history ``num''th event
 
1150
 *
 
1151
 * returned pointer points to static variable
 
1152
 */
 
1153
HIST_ENTRY *
 
1154
history_get(int num)
 
1155
{
 
1156
        static HIST_ENTRY she;
 
1157
        HistEvent ev;
 
1158
        int curr_num;
 
1159
 
 
1160
        if (h == NULL || e == NULL)
 
1161
                rl_initialize();
 
1162
 
 
1163
        /* save current position */
 
1164
        if (history(h, &ev, H_CURR) != 0)
 
1165
                return (NULL);
 
1166
        curr_num = ev.num;
 
1167
 
 
1168
        /* start from most recent */
 
1169
        if (history(h, &ev, H_FIRST) != 0)
 
1170
                return (NULL);  /* error */
 
1171
 
 
1172
        /* look backwards for event matching specified offset */
 
1173
        if (history(h, &ev, H_NEXT_EVENT, num + 1))
 
1174
                return (NULL);
 
1175
 
 
1176
        she.line = ev.str;
 
1177
        she.data = NULL;
 
1178
 
 
1179
        /* restore pointer to where it was */
 
1180
        (void)history(h, &ev, H_SET, curr_num);
 
1181
 
 
1182
        return (&she);
 
1183
}
 
1184
 
 
1185
 
 
1186
/*
 
1187
 * add the line to history table
 
1188
 */
 
1189
int
 
1190
add_history(const char *line)
 
1191
{
 
1192
        HistEvent ev;
 
1193
 
 
1194
        if (h == NULL || e == NULL)
 
1195
                rl_initialize();
 
1196
 
 
1197
        (void)history(h, &ev, H_ENTER, line);
 
1198
        if (history(h, &ev, H_GETSIZE) == 0)
 
1199
                history_length = ev.num;
 
1200
 
 
1201
        return (!(history_length > 0)); /* return 0 if all is okay */
 
1202
}
 
1203
 
 
1204
 
 
1205
/*
 
1206
 * remove the specified entry from the history list and return it.
 
1207
 */
 
1208
HIST_ENTRY *
 
1209
remove_history(int num)
 
1210
{
 
1211
        HIST_ENTRY *she;
 
1212
        HistEvent ev;
 
1213
 
 
1214
        if (h == NULL || e == NULL)
 
1215
                rl_initialize();
 
1216
 
 
1217
        if (history(h, &ev, H_DEL, num) != 0)
 
1218
                return NULL;
 
1219
 
 
1220
        if ((she = malloc(sizeof(*she))) == NULL)
 
1221
                return NULL;
 
1222
 
 
1223
        she->line = ev.str;
 
1224
        she->data = NULL;
 
1225
 
 
1226
        return she;
 
1227
}
 
1228
 
 
1229
 
 
1230
/*
 
1231
 * clear the history list - delete all entries
 
1232
 */
 
1233
void
 
1234
clear_history(void)
 
1235
{
 
1236
        HistEvent ev;
 
1237
 
 
1238
        history(h, &ev, H_CLEAR);
 
1239
}
 
1240
 
 
1241
 
 
1242
/*
 
1243
 * returns offset of the current history event
 
1244
 */
 
1245
int
 
1246
where_history(void)
 
1247
{
 
1248
        HistEvent ev;
 
1249
        int curr_num, off;
 
1250
 
 
1251
        if (history(h, &ev, H_CURR) != 0)
 
1252
                return (0);
 
1253
        curr_num = ev.num;
 
1254
 
 
1255
        history(h, &ev, H_FIRST);
 
1256
        off = 1;
 
1257
        while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
 
1258
                off++;
 
1259
 
 
1260
        return (off);
 
1261
}
 
1262
 
 
1263
 
 
1264
/*
 
1265
 * returns current history event or NULL if there is no such event
 
1266
 */
 
1267
HIST_ENTRY *
 
1268
current_history(void)
 
1269
{
 
1270
 
 
1271
        return (_move_history(H_CURR));
 
1272
}
 
1273
 
 
1274
 
 
1275
/*
 
1276
 * returns total number of bytes history events' data are using
 
1277
 */
 
1278
int
 
1279
history_total_bytes(void)
 
1280
{
 
1281
        HistEvent ev;
 
1282
        int curr_num, size;
 
1283
 
 
1284
        if (history(h, &ev, H_CURR) != 0)
 
1285
                return (-1);
 
1286
        curr_num = ev.num;
 
1287
 
 
1288
        history(h, &ev, H_FIRST);
 
1289
        size = 0;
 
1290
        do
 
1291
                size += strlen(ev.str);
 
1292
        while (history(h, &ev, H_NEXT) == 0);
 
1293
 
 
1294
        /* get to the same position as before */
 
1295
        history(h, &ev, H_PREV_EVENT, curr_num);
 
1296
 
 
1297
        return (size);
 
1298
}
 
1299
 
 
1300
 
 
1301
/*
 
1302
 * sets the position in the history list to ``pos''
 
1303
 */
 
1304
int
 
1305
history_set_pos(int pos)
 
1306
{
 
1307
        HistEvent ev;
 
1308
        int curr_num;
 
1309
 
 
1310
        if (pos > history_length || pos < 0)
 
1311
                return (-1);
 
1312
 
 
1313
        history(h, &ev, H_CURR);
 
1314
        curr_num = ev.num;
 
1315
 
 
1316
        if (history(h, &ev, H_SET, pos)) {
 
1317
                history(h, &ev, H_SET, curr_num);
 
1318
                return(-1);
 
1319
        }
 
1320
        return (0);
 
1321
}
 
1322
 
 
1323
 
 
1324
/*
 
1325
 * returns previous event in history and shifts pointer accordingly
 
1326
 */
 
1327
HIST_ENTRY *
 
1328
previous_history(void)
 
1329
{
 
1330
 
 
1331
        return (_move_history(H_PREV));
 
1332
}
 
1333
 
 
1334
 
 
1335
/*
 
1336
 * returns next event in history and shifts pointer accordingly
 
1337
 */
 
1338
HIST_ENTRY *
 
1339
next_history(void)
 
1340
{
 
1341
 
 
1342
        return (_move_history(H_NEXT));
 
1343
}
 
1344
 
 
1345
 
 
1346
/*
 
1347
 * searches for first history event containing the str
 
1348
 */
 
1349
int
 
1350
history_search(const char *str, int direction)
 
1351
{
 
1352
        HistEvent ev;
 
1353
        const char *strp;
 
1354
        int curr_num;
 
1355
 
 
1356
        if (history(h, &ev, H_CURR) != 0)
 
1357
                return (-1);
 
1358
        curr_num = ev.num;
 
1359
 
 
1360
        for (;;) {
 
1361
                if ((strp = strstr(ev.str, str)) != NULL)
 
1362
                        return (int) (strp - ev.str);
 
1363
                if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
 
1364
                        break;
 
1365
        }
 
1366
        history(h, &ev, H_SET, curr_num);
 
1367
        return (-1);
 
1368
}
 
1369
 
 
1370
 
 
1371
/*
 
1372
 * searches for first history event beginning with str
 
1373
 */
 
1374
int
 
1375
history_search_prefix(const char *str, int direction)
 
1376
{
 
1377
        HistEvent ev;
 
1378
 
 
1379
        return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str));
 
1380
}
 
1381
 
 
1382
 
 
1383
/*
 
1384
 * search for event in history containing str, starting at offset
 
1385
 * abs(pos); continue backward, if pos<0, forward otherwise
 
1386
 */
 
1387
/* ARGSUSED */
 
1388
int
 
1389
history_search_pos(const char *str,
 
1390
                   int direction __attribute__((__unused__)), int pos)
 
1391
{
 
1392
        HistEvent ev;
 
1393
        int curr_num, off;
 
1394
 
 
1395
        off = (pos > 0) ? pos : -pos;
 
1396
        pos = (pos > 0) ? 1 : -1;
 
1397
 
 
1398
        if (history(h, &ev, H_CURR) != 0)
 
1399
                return (-1);
 
1400
        curr_num = ev.num;
 
1401
 
 
1402
        if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
 
1403
                return (-1);
 
1404
 
 
1405
 
 
1406
        for (;;) {
 
1407
                if (strstr(ev.str, str))
 
1408
                        return (off);
 
1409
                if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
 
1410
                        break;
 
1411
        }
 
1412
 
 
1413
        /* set "current" pointer back to previous state */
 
1414
        history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
 
1415
 
 
1416
        return (-1);
 
1417
}
 
1418
 
 
1419
 
 
1420
/********************************/
 
1421
/* completion functions */
 
1422
 
 
1423
char *
 
1424
tilde_expand(char *name)
 
1425
{
 
1426
        return fn_tilde_expand(name);
 
1427
}
 
1428
 
 
1429
char *
 
1430
filename_completion_function(const char *name, int state)
 
1431
{
 
1432
        return fn_filename_completion_function(name, state);
 
1433
}
 
1434
 
 
1435
/*
 
1436
 * a completion generator for usernames; returns _first_ username
 
1437
 * which starts with supplied text
 
1438
 * text contains a partial username preceded by random character
 
1439
 * (usually '~'); state is ignored
 
1440
 * it's callers responsibility to free returned value
 
1441
 */
 
1442
char *
 
1443
username_completion_function(const char *text, int state)
 
1444
{
 
1445
        struct passwd *pwd;
 
1446
 
 
1447
        if (text[0] == '\0')
 
1448
                return (NULL);
 
1449
 
 
1450
        if (*text == '~')
 
1451
                text++;
 
1452
 
 
1453
        if (state == 0)
 
1454
                setpwent();
 
1455
 
 
1456
        /* XXXMYSQL: just use non-_r functions for now */
 
1457
        while ((pwd = getpwent()) && text[0] == pwd->pw_name[0]
 
1458
            && strcmp(text, pwd->pw_name) == 0);
 
1459
 
 
1460
        if (pwd == NULL) {
 
1461
                endpwent();
 
1462
                return (NULL);
 
1463
        }
 
1464
        return (strdup(pwd->pw_name));
 
1465
}
 
1466
 
 
1467
 
 
1468
/*
 
1469
 * el-compatible wrapper to send TSTP on ^Z
 
1470
 */
 
1471
/* ARGSUSED */
 
1472
static unsigned char
 
1473
_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
 
1474
{
 
1475
        (void)kill(0, SIGTSTP);
 
1476
        return CC_NORM;
 
1477
}
 
1478
 
 
1479
/*
 
1480
 * Display list of strings in columnar format on readline's output stream.
 
1481
 * 'matches' is list of strings, 'len' is number of strings in 'matches',
 
1482
 * 'max' is maximum length of string in 'matches'.
 
1483
 */
 
1484
void
 
1485
rl_display_match_list(char **matches, int len, int max)
 
1486
{
 
1487
 
 
1488
        fn_display_match_list(e, matches, len, max);
 
1489
}
 
1490
 
 
1491
static const char *
 
1492
/*ARGSUSED*/
 
1493
_rl_completion_append_character_function(const char *dummy
 
1494
    __attribute__((__unused__)))
 
1495
{
 
1496
        static char buf[2];
 
1497
        buf[0] = rl_completion_append_character;
 
1498
        buf[1] = '\0';
 
1499
        return buf;
 
1500
}
 
1501
 
 
1502
 
 
1503
/*
 
1504
 * complete word at current point
 
1505
 */
 
1506
/* ARGSUSED */
 
1507
int
 
1508
rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
 
1509
{
 
1510
        if (h == NULL || e == NULL)
 
1511
                rl_initialize();
 
1512
 
 
1513
        if (rl_inhibit_completion) {
 
1514
                char arr[2];
 
1515
                arr[0] = (char)invoking_key;
 
1516
                arr[1] = '\0';
 
1517
                el_insertstr(e, arr);
 
1518
                return (CC_REFRESH);
 
1519
        }
 
1520
 
 
1521
        /* Just look at how many global variables modify this operation! */
 
1522
        return fn_complete(e,
 
1523
            (CPFunction *)rl_completion_entry_function,
 
1524
            rl_attempted_completion_function,
 
1525
            rl_basic_word_break_characters, rl_special_prefixes,
 
1526
            _rl_completion_append_character_function, rl_completion_query_items,
 
1527
            &rl_completion_type, &rl_attempted_completion_over,
 
1528
            &rl_point, &rl_end);
 
1529
}
 
1530
 
 
1531
 
 
1532
/* ARGSUSED */
 
1533
static unsigned char
 
1534
_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
 
1535
{
 
1536
        return (unsigned char)rl_complete(0, ch);
 
1537
}
 
1538
 
 
1539
/*
 
1540
 * misc other functions
 
1541
 */
 
1542
 
 
1543
/*
 
1544
 * bind key c to readline-type function func
 
1545
 */
 
1546
int
 
1547
rl_bind_key(int c, int func(int, int))
 
1548
{
 
1549
        int retval = -1;
 
1550
 
 
1551
        if (h == NULL || e == NULL)
 
1552
                rl_initialize();
 
1553
 
 
1554
        if (func == rl_insert) {
 
1555
                /* XXX notice there is no range checking of ``c'' */
 
1556
                e->el_map.key[c] = ED_INSERT;
 
1557
                retval = 0;
 
1558
        }
 
1559
        return (retval);
 
1560
}
 
1561
 
 
1562
 
 
1563
/*
 
1564
 * read one key from input - handles chars pushed back
 
1565
 * to input stream also
 
1566
 */
 
1567
int
 
1568
rl_read_key(void)
 
1569
{
 
1570
        char fooarr[2 * sizeof(int)];
 
1571
 
 
1572
        if (e == NULL || h == NULL)
 
1573
                rl_initialize();
 
1574
 
 
1575
        return (el_getc(e, fooarr));
 
1576
}
 
1577
 
 
1578
 
 
1579
/*
 
1580
 * reset the terminal
 
1581
 */
 
1582
/* ARGSUSED */
 
1583
void
 
1584
rl_reset_terminal(const char *p __attribute__((__unused__)))
 
1585
{
 
1586
 
 
1587
        if (h == NULL || e == NULL)
 
1588
                rl_initialize();
 
1589
        el_reset(e);
 
1590
}
 
1591
 
 
1592
 
 
1593
/*
 
1594
 * insert character ``c'' back into input stream, ``count'' times
 
1595
 */
 
1596
int
 
1597
rl_insert(int count, int c)
 
1598
{
 
1599
        char arr[2];
 
1600
 
 
1601
        if (h == NULL || e == NULL)
 
1602
                rl_initialize();
 
1603
 
 
1604
        /* XXX - int -> char conversion can lose on multichars */
 
1605
        arr[0] = c;
 
1606
        arr[1] = '\0';
 
1607
 
 
1608
        for (; count > 0; count--)
 
1609
                el_push(e, arr);
 
1610
 
 
1611
        return (0);
 
1612
}
 
1613
 
 
1614
/*ARGSUSED*/
 
1615
int
 
1616
rl_newline(int count, int c)
 
1617
{
 
1618
        /*
 
1619
         * Readline-4.0 appears to ignore the args.
 
1620
         */
 
1621
        return rl_insert(1, '\n');
 
1622
}
 
1623
 
 
1624
/*ARGSUSED*/
 
1625
static unsigned char
 
1626
rl_bind_wrapper(EditLine *el, unsigned char c)
 
1627
{
 
1628
        if (map[c] == NULL)
 
1629
            return CC_ERROR;
 
1630
 
 
1631
        _rl_update_pos();
 
1632
 
 
1633
        (*map[c])(NULL, c);
 
1634
 
 
1635
        /* If rl_done was set by the above call, deal with it here */
 
1636
        if (rl_done)
 
1637
                return CC_EOF;
 
1638
 
 
1639
        return CC_NORM;
 
1640
}
 
1641
 
 
1642
int
 
1643
rl_add_defun(const char *name, Function *fun, int c)
 
1644
{
 
1645
        char dest[8];
 
1646
        if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
 
1647
                return -1;
 
1648
        map[(unsigned char)c] = fun;
 
1649
        el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
 
1650
        vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
 
1651
        el_set(e, EL_BIND, dest, name);
 
1652
        return 0;
 
1653
}
 
1654
 
 
1655
void
 
1656
rl_callback_read_char()
 
1657
{
 
1658
        int count = 0, done = 0;
 
1659
        const char *buf = el_gets(e, &count);
 
1660
        char *wbuf;
 
1661
 
 
1662
        if (buf == NULL || count-- <= 0)
 
1663
                return;
 
1664
        if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
 
1665
                done = 1;
 
1666
        if (buf[count] == '\n' || buf[count] == '\r')
 
1667
                done = 2;
 
1668
 
 
1669
        if (done && rl_linefunc != NULL) {
 
1670
                el_set(e, EL_UNBUFFERED, 0);
 
1671
                if (done == 2) {
 
1672
                    if ((wbuf = strdup(buf)) != NULL)
 
1673
                        wbuf[count] = '\0';
 
1674
                } else
 
1675
                        wbuf = NULL;
 
1676
                (*(void (*)(const char *))rl_linefunc)(wbuf);
 
1677
                el_set(e, EL_UNBUFFERED, 1);
 
1678
        }
 
1679
}
 
1680
 
 
1681
void 
 
1682
rl_callback_handler_install(const char *prompt, VCPFunction *linefunc)
 
1683
{
 
1684
        if (e == NULL) {
 
1685
                rl_initialize();
 
1686
        }
 
1687
        (void)rl_set_prompt(prompt);
 
1688
        rl_linefunc = linefunc;
 
1689
        el_set(e, EL_UNBUFFERED, 1);
 
1690
}   
 
1691
 
 
1692
void 
 
1693
rl_callback_handler_remove(void)
 
1694
{
 
1695
        el_set(e, EL_UNBUFFERED, 0);
 
1696
        rl_linefunc = NULL;
 
1697
}
 
1698
 
 
1699
void
 
1700
rl_redisplay(void)
 
1701
{
 
1702
        char a[2];
 
1703
        a[0] = e->el_tty.t_c[TS_IO][C_REPRINT];
 
1704
        a[1] = '\0';
 
1705
        el_push(e, a);
 
1706
}
 
1707
 
 
1708
int
 
1709
rl_get_previous_history(int count, int key)
 
1710
{
 
1711
        char a[2];
 
1712
        a[0] = key;
 
1713
        a[1] = '\0';
 
1714
        while (count--)
 
1715
                el_push(e, a);
 
1716
        return 0;
 
1717
}
 
1718
 
 
1719
void
 
1720
/*ARGSUSED*/
 
1721
rl_prep_terminal(int meta_flag)
 
1722
{
 
1723
        el_set(e, EL_PREP_TERM, 1);
 
1724
}
 
1725
 
 
1726
void
 
1727
rl_deprep_terminal(void)
 
1728
{
 
1729
        el_set(e, EL_PREP_TERM, 0);
 
1730
}
 
1731
 
 
1732
int
 
1733
rl_read_init_file(const char *s)
 
1734
{
 
1735
        return(el_source(e, s));
 
1736
}
 
1737
 
 
1738
int
 
1739
rl_parse_and_bind(const char *line)
 
1740
{
 
1741
        const char **argv;
 
1742
        int argc;
 
1743
        Tokenizer *tok;
 
1744
 
 
1745
        tok = tok_init(NULL);
 
1746
        tok_str(tok, line, &argc, &argv);
 
1747
        argc = el_parse(e, argc, argv);
 
1748
        tok_end(tok);
 
1749
        return (argc ? 1 : 0);
 
1750
}
 
1751
 
 
1752
int
 
1753
rl_variable_bind(const char *var, const char *value)
 
1754
{
 
1755
        /*
 
1756
         * The proper return value is undocument, but this is what the
 
1757
         * readline source seems to do.
 
1758
         */
 
1759
        return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0);
 
1760
}
 
1761
 
 
1762
void
 
1763
rl_stuff_char(int c)
 
1764
{
 
1765
        char buf[2];
 
1766
 
 
1767
        buf[0] = c;
 
1768
        buf[1] = '\0';
 
1769
        el_insertstr(e, buf);
 
1770
}
 
1771
 
 
1772
static int
 
1773
_rl_event_read_char(EditLine *el, char *cp)
 
1774
{
 
1775
        int     n, num_read = 0;
 
1776
 
 
1777
        *cp = '\0';
 
1778
        while (rl_event_hook) {
 
1779
 
 
1780
                (*rl_event_hook)();
 
1781
 
 
1782
#if defined(FIONREAD)
 
1783
                if (ioctl(el->el_infd, FIONREAD, &n) < 0)
 
1784
                        return(-1);
 
1785
                if (n)
 
1786
                        num_read = read(el->el_infd, cp, 1);
 
1787
                else
 
1788
                        num_read = 0;
 
1789
#elif defined(F_SETFL) && defined(O_NDELAY)
 
1790
                if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
 
1791
                        return(-1);
 
1792
                if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
 
1793
                        return(-1);
 
1794
                num_read = read(el->el_infd, cp, 1);
 
1795
                if (fcntl(el->el_infd, F_SETFL, n))
 
1796
                        return(-1);
 
1797
#else
 
1798
                /* not non-blocking, but what you gonna do? */
 
1799
                num_read = read(el->el_infd, cp, 1);
 
1800
                return(-1);
 
1801
#endif
 
1802
 
 
1803
                if (num_read < 0 && errno == EAGAIN)
 
1804
                        continue;
 
1805
                if (num_read == 0)
 
1806
                        continue;
 
1807
                break;
 
1808
        }
 
1809
        if (!rl_event_hook)
 
1810
                el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
 
1811
        return(num_read);
 
1812
}
 
1813
 
 
1814
static void
 
1815
_rl_update_pos(void)
 
1816
{
 
1817
        const LineInfo *li = el_line(e);
 
1818
 
 
1819
        rl_point = li->cursor - li->buffer;
 
1820
        rl_end = li->lastchar - li->buffer;
 
1821
}
 
1822
 
 
1823
void
 
1824
rl_get_screen_size(int *rows, int *cols)
 
1825
{
 
1826
        if (rows)
 
1827
                el_get(e, EL_GETTC, "li", rows);
 
1828
        if (cols)
 
1829
                el_get(e, EL_GETTC, "co", cols);
 
1830
}
 
1831
 
 
1832
void
 
1833
rl_set_screen_size(int rows, int cols)
 
1834
{
 
1835
        char buf[64];
 
1836
        (void)snprintf(buf, sizeof(buf), "%d", rows);
 
1837
        el_set(e, EL_SETTC, "li", buf);
 
1838
        (void)snprintf(buf, sizeof(buf), "%d", cols);
 
1839
        el_set(e, EL_SETTC, "co", buf);
 
1840
}
 
1841
 
 
1842
char **
 
1843
rl_completion_matches(const char *str, rl_compentry_func_t *fun)
 
1844
{
 
1845
        size_t len, max, i, j, min;
 
1846
        char **list, *match, *a, *b;
 
1847
 
 
1848
        len = 1;
 
1849
        max = 10;
 
1850
        if ((list = malloc(max * sizeof(*list))) == NULL)
 
1851
                return NULL;
 
1852
 
 
1853
        while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
 
1854
                if (len == max) {
 
1855
                        char **nl;
 
1856
                        max += 10;
 
1857
                        if ((nl = realloc(list, max * sizeof(*nl))) == NULL)
 
1858
                                goto out;
 
1859
                        list = nl;
 
1860
                }
 
1861
                list[len++] = match;
 
1862
        }
 
1863
        if (len == 1)
 
1864
                goto out;
 
1865
        list[len] = NULL;
 
1866
        if (len == 2) {
 
1867
                if ((list[0] = strdup(list[1])) == NULL)
 
1868
                        goto out;
 
1869
                return list;
 
1870
        }
 
1871
        qsort(&list[1], len - 1, sizeof(*list),
 
1872
            (int (*)(const void *, const void *)) strcmp);
 
1873
        min = SIZE_T_MAX;
 
1874
        for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
 
1875
                b = list[i + 1];
 
1876
                for (j = 0; a[j] && a[j] == b[j]; j++)
 
1877
                        continue;
 
1878
                if (min > j)
 
1879
                        min = j;
 
1880
        }
 
1881
        if (min == 0 && *str) {
 
1882
                if ((list[0] = strdup(str)) == NULL)
 
1883
                        goto out;
 
1884
        } else {
 
1885
                if ((list[0] = malloc(min + 1)) == NULL)
 
1886
                        goto out;
 
1887
                (void)memcpy(list[0], list[1], min);
 
1888
                list[0][min] = '\0';
 
1889
        }
 
1890
        return list;
 
1891
                
 
1892
out:
 
1893
        free(list);
 
1894
        return NULL;
 
1895
}
 
1896
 
 
1897
char *
 
1898
rl_filename_completion_function (const char *text, int state)
 
1899
{
 
1900
        return fn_filename_completion_function(text, state);
 
1901
}
 
1902
 
 
1903
void
 
1904
rl_forced_update_display(void)
 
1905
{
 
1906
        el_set(e, EL_REFRESH);
 
1907
}
 
1908
 
 
1909
int
 
1910
_rl_abort_internal(void)
 
1911
{
 
1912
        el_beep(e);
 
1913
        longjmp(topbuf, 1);
 
1914
        /*NOTREACHED*/
 
1915
}
 
1916
 
 
1917
int
 
1918
_rl_qsort_string_compare(char **s1, char **s2)
 
1919
{
 
1920
        return strcoll(*s1, *s2);
 
1921
}
 
1922
 
 
1923
int
 
1924
/*ARGSUSED*/
 
1925
rl_kill_text(int from, int to)
 
1926
{
 
1927
        return 0;
 
1928
}
 
1929
 
 
1930
Keymap
 
1931
rl_make_bare_keymap(void)
 
1932
{
 
1933
        return NULL;
 
1934
}
 
1935
 
 
1936
Keymap
 
1937
rl_get_keymap(void)
 
1938
{
 
1939
        return NULL;
 
1940
}
 
1941
 
 
1942
void
 
1943
/*ARGSUSED*/
 
1944
rl_set_keymap(Keymap k)
 
1945
{
 
1946
}
 
1947
 
 
1948
int
 
1949
/*ARGSUSED*/
 
1950
rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k)
 
1951
{
 
1952
        return 0;
 
1953
}
 
1954
 
 
1955
int
 
1956
/*ARGSUSED*/
 
1957
rl_bind_key_in_map(int key, Function *fun, Keymap k)
 
1958
{
 
1959
        return 0;
 
1960
}