~ubuntu-branches/ubuntu/trusty/bash/trusty-security

« back to all changes in this revision

Viewing changes to lib/readline/examples/excallback.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-03-03 22:52:05 UTC
  • mfrom: (1.3.5) (2.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20140303225205-87ltrt5kspeq0g1b
Tags: 4.3-1ubuntu1
* Merge with Debian; remaining changes:
  - skel.bashrc:
    - Run lesspipe.
    - Enable ls aliases.
    - Set options in ll alias to -alF.
    - Define an alert alias.
    - Enabled colored grep aliases.
  - etc.bash.bashrc:
    - Add sudo hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
From: Jeff Solomon <jsolomon@stanford.edu>
 
3
Date: Fri,  9 Apr 1999 10:13:27 -0700 (PDT)
 
4
To: chet@po.cwru.edu
 
5
Subject: new readline example
 
6
Message-ID: <14094.12094.527305.199695@mrclean.Stanford.EDU>
 
7
 
 
8
Chet,
 
9
 
 
10
I've been using readline 4.0. Specifically, I've been using the perl
 
11
version Term::ReadLine::Gnu. It works great.
 
12
 
 
13
Anyway, I've been playing around the alternate interface and I wanted
 
14
to contribute a little C program, callback.c, to you that you could
 
15
use as an example of the alternate interface in the /examples
 
16
directory of the readline distribution.
 
17
 
 
18
My example shows how, using the alternate interface, you can
 
19
interactively change the prompt (which is very nice imo). Also, I
 
20
point out that you must roll your own terminal setting when using the
 
21
alternate interface because readline depreps (using your parlance) the
 
22
terminal while in the user callback. I try to demostrate what I mean
 
23
with an example. I've included the program below.
 
24
 
 
25
To compile, I just put the program in the examples directory and made
 
26
the appropriate changes to the EXECUTABLES and OBJECTS line and added
 
27
an additional target 'callback'.
 
28
 
 
29
I compiled on my Sun Solaris2.6 box using Sun's cc.
 
30
 
 
31
Let me know what you think.
 
32
 
 
33
Jeff
 
34
*/
 
35
/*
 
36
Copyright (C) 1999 Jeff Solomon
 
37
*/
 
38
 
 
39
#if defined (HAVE_CONFIG_H)
 
40
#include <config.h>
 
41
#endif
 
42
 
 
43
#include <sys/types.h>
 
44
 
 
45
#ifdef HAVE_UNISTD_H
 
46
#include <unistd.h>
 
47
#endif
 
48
#include <stdlib.h>
 
49
 
 
50
#include <stdio.h>
 
51
#include <termios.h>    /* xxx - should make this more general */
 
52
 
 
53
#ifdef READLINE_LIBRARY
 
54
#  include "readline.h"
 
55
#else
 
56
#  include <readline/readline.h>
 
57
#endif
 
58
 
 
59
#ifndef STDIN_FILENO
 
60
#  define STDIN_FILENO 0
 
61
#endif
 
62
 
 
63
/* This little examples demonstrates the alternate interface to using readline.
 
64
 * In the alternate interface, the user maintains control over program flow and
 
65
 * only calls readline when STDIN is readable. Using the alternate interface,
 
66
 * you can do anything else while still using readline (like talking to a
 
67
 * network or another program) without blocking.
 
68
 *
 
69
 * Specifically, this program highlights two importants features of the
 
70
 * alternate interface. The first is the ability to interactively change the
 
71
 * prompt, which can't be done using the regular interface since rl_prompt is
 
72
 * read-only.
 
73
 * 
 
74
 * The second feature really highlights a subtle point when using the alternate
 
75
 * interface. That is, readline will not alter the terminal when inside your
 
76
 * callback handler. So let's so, your callback executes a user command that
 
77
 * takes a non-trivial amount of time to complete (seconds). While your
 
78
 * executing the command, the user continues to type keystrokes and expects them
 
79
 * to be re-echoed on the new prompt when it returns. Unfortunately, the default
 
80
 * terminal configuration doesn't do this. After the prompt returns, the user
 
81
 * must hit one additional keystroke and then will see all of his previous
 
82
 * keystrokes. To illustrate this, compile and run this program. Type "sleep" at
 
83
 * the prompt and then type "bar" before the prompt returns (you have 3
 
84
 * seconds). Notice how "bar" is re-echoed on the prompt after the prompt
 
85
 * returns? This is what you expect to happen. Now comment out the 4 lines below
 
86
 * the line that says COMMENT LINE BELOW. Recompile and rerun the program and do
 
87
 * the same thing. When the prompt returns, you should not see "bar". Now type
 
88
 * "f", see how "barf" magically appears? This behavior is un-expected and not
 
89
 * desired.
 
90
 */
 
91
 
 
92
void process_line(char *line);
 
93
int  change_prompt(void);
 
94
char *get_prompt(void);
 
95
 
 
96
int prompt = 1;
 
97
char prompt_buf[40], line_buf[256];
 
98
tcflag_t old_lflag;
 
99
cc_t     old_vtime;
 
100
struct termios term;
 
101
 
 
102
int 
 
103
main()
 
104
{
 
105
    fd_set fds;
 
106
 
 
107
    /* Adjust the terminal slightly before the handler is installed. Disable
 
108
     * canonical mode processing and set the input character time flag to be
 
109
     * non-blocking.
 
110
     */
 
111
    if( tcgetattr(STDIN_FILENO, &term) < 0 ) {
 
112
        perror("tcgetattr");
 
113
        exit(1);
 
114
    }
 
115
    old_lflag = term.c_lflag;
 
116
    old_vtime = term.c_cc[VTIME];
 
117
    term.c_lflag &= ~ICANON;
 
118
    term.c_cc[VTIME] = 1;
 
119
    /* COMMENT LINE BELOW - see above */
 
120
    if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) {
 
121
        perror("tcsetattr");
 
122
        exit(1);
 
123
    }
 
124
 
 
125
    rl_add_defun("change-prompt", change_prompt, CTRL('t'));
 
126
    rl_callback_handler_install(get_prompt(), process_line);
 
127
 
 
128
    while(1) {
 
129
      FD_ZERO(&fds);
 
130
      FD_SET(fileno(stdin), &fds);
 
131
 
 
132
      if( select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) {
 
133
        perror("select");
 
134
        exit(1);
 
135
      }
 
136
 
 
137
      if( FD_ISSET(fileno(stdin), &fds) ) {
 
138
        rl_callback_read_char();
 
139
      }
 
140
    }
 
141
}
 
142
 
 
143
void
 
144
process_line(char *line)
 
145
{
 
146
  if( line == NULL ) {
 
147
    fprintf(stderr, "\n", line);
 
148
 
 
149
    /* reset the old terminal setting before exiting */
 
150
    term.c_lflag     = old_lflag;
 
151
    term.c_cc[VTIME] = old_vtime;
 
152
    if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) {
 
153
        perror("tcsetattr");
 
154
        exit(1);
 
155
    }
 
156
    exit(0);
 
157
  }
 
158
 
 
159
  if( strcmp(line, "sleep") == 0 ) {
 
160
    sleep(3);
 
161
  } else {
 
162
    fprintf(stderr, "|%s|\n", line);
 
163
  }
 
164
 
 
165
  free (line);
 
166
}
 
167
 
 
168
int
 
169
change_prompt(void)
 
170
{
 
171
  /* toggle the prompt variable */
 
172
  prompt = !prompt;
 
173
 
 
174
  /* save away the current contents of the line */
 
175
  strcpy(line_buf, rl_line_buffer);
 
176
 
 
177
  /* install a new handler which will change the prompt and erase the current line */
 
178
  rl_callback_handler_install(get_prompt(), process_line);
 
179
 
 
180
  /* insert the old text on the new line */
 
181
  rl_insert_text(line_buf);
 
182
 
 
183
  /* redraw the current line - this is an undocumented function. It invokes the
 
184
   * redraw-current-line command.
 
185
   */
 
186
  rl_refresh_line(0, 0);
 
187
}
 
188
 
 
189
char *
 
190
get_prompt(void)
 
191
{
 
192
  /* The prompts can even be different lengths! */
 
193
  sprintf(prompt_buf, "%s", 
 
194
    prompt ? "Hit ctrl-t to toggle prompt> " : "Pretty cool huh?> ");
 
195
  return prompt_buf;
 
196
}