Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Samba readline wrapper implementation
4 : Copyright (C) Simo Sorce 2001
5 : Copyright (C) Andrew Tridgell 2001
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "../lib/util/select.h"
23 : #include "system/filesys.h"
24 : #include "system/select.h"
25 : #include "system/readline.h"
26 : #include "libcli/smbreadline/smbreadline.h"
27 :
28 : #undef malloc
29 :
30 : #ifdef HAVE_LIBREADLINE
31 : # ifdef HAVE_READLINE_READLINE_H
32 : # include <readline/readline.h>
33 : # ifdef HAVE_READLINE_HISTORY_H
34 : # include <readline/history.h>
35 : # endif
36 : # else
37 : # ifdef HAVE_READLINE_H
38 : # include <readline.h>
39 : # ifdef HAVE_HISTORY_H
40 : # include <history.h>
41 : # endif
42 : # else
43 : # undef HAVE_LIBREADLINE
44 : # endif
45 : # endif
46 : #endif
47 :
48 : static bool smb_rl_done;
49 :
50 : #ifdef HAVE_LIBREADLINE
51 : /*
52 : * MacOS/X does not have rl_done in readline.h, but
53 : * readline.so has it
54 : */
55 : extern int rl_done;
56 : #endif
57 :
58 0 : void smb_readline_done(void)
59 : {
60 0 : smb_rl_done = true;
61 : #ifdef HAVE_LIBREADLINE
62 0 : rl_done = 1;
63 : #endif
64 0 : }
65 :
66 : /****************************************************************************
67 : Display the prompt and wait for input. Call callback() regularly
68 : ****************************************************************************/
69 :
70 69 : static char *smb_readline_replacement(const char *prompt, void (*callback)(void),
71 : char **(completion_fn)(const char *text, int start, int end))
72 : {
73 69 : char *line = NULL;
74 69 : int fd = fileno(stdin);
75 : char *ret;
76 :
77 : /* Prompt might be NULL in non-interactive mode. */
78 69 : if (prompt) {
79 0 : printf("%s", prompt);
80 0 : fflush(stdout);
81 : }
82 :
83 69 : line = (char *)malloc(BUFSIZ);
84 69 : if (!line) {
85 0 : return NULL;
86 : }
87 :
88 106 : while (!smb_rl_done) {
89 : struct pollfd pfd;
90 :
91 69 : ZERO_STRUCT(pfd);
92 69 : pfd.fd = fd;
93 69 : pfd.events = POLLIN|POLLHUP;
94 :
95 69 : if (sys_poll_intr(&pfd, 1, 5000) == 1) {
96 69 : ret = fgets(line, BUFSIZ, stdin);
97 69 : if (ret == 0) {
98 16 : SAFE_FREE(line);
99 : }
100 69 : return ret;
101 : }
102 0 : if (callback) {
103 0 : callback();
104 : }
105 : }
106 0 : SAFE_FREE(line);
107 0 : return NULL;
108 : }
109 :
110 : /****************************************************************************
111 : Display the prompt and wait for input. Call callback() regularly.
112 : ****************************************************************************/
113 :
114 925 : char *smb_readline(const char *prompt, void (*callback)(void),
115 : char **(completion_fn)(const char *text, int start, int end))
116 : {
117 : char *ret;
118 : bool interactive;
119 :
120 925 : interactive = isatty(fileno(stdin)) || getenv("CLI_FORCE_INTERACTIVE");
121 925 : if (!interactive) {
122 69 : return smb_readline_replacement(NULL, callback, completion_fn);
123 : }
124 :
125 : #ifdef HAVE_LIBREADLINE
126 :
127 : /* Aargh! Readline does bizzare things with the terminal width
128 : that mucks up expect(1). Set CLI_NO_READLINE in the environment
129 : to force readline not to be used. */
130 :
131 856 : if (getenv("CLI_NO_READLINE"))
132 0 : return smb_readline_replacement(prompt, callback, completion_fn);
133 :
134 856 : if (completion_fn) {
135 : /* The callback prototype has changed slightly between
136 : different versions of Readline, so the same function
137 : works in all of them to date, but we get compiler
138 : warnings in some. */
139 856 : rl_attempted_completion_function = RL_COMPLETION_CAST completion_fn;
140 :
141 : /*
142 : * We only want sensible characters as the word-break chars
143 : * for the most part. This allows us to tab through a path.
144 : */
145 856 : rl_basic_word_break_characters = " \t\n";
146 : }
147 :
148 : #ifdef HAVE_DECL_RL_EVENT_HOOK
149 856 : if (callback)
150 856 : rl_event_hook = (rl_hook_func_t *)callback;
151 : #endif
152 856 : ret = readline(prompt);
153 856 : if (ret && *ret)
154 856 : add_history(ret);
155 :
156 : #else
157 : ret = smb_readline_replacement(prompt, callback, completion_fn);
158 : #endif
159 :
160 856 : return ret;
161 : }
162 :
163 : /****************************************************************************
164 : * return line buffer text
165 : ****************************************************************************/
166 0 : const char *smb_readline_get_line_buffer(void)
167 : {
168 : #if defined(HAVE_LIBREADLINE)
169 0 : return rl_line_buffer;
170 : #else
171 : return NULL;
172 : #endif
173 : }
174 :
175 :
176 : /****************************************************************************
177 : * set completion append character
178 : ***************************************************************************/
179 0 : void smb_readline_ca_char(char c)
180 : {
181 : #if defined(HAVE_LIBREADLINE)
182 0 : rl_completion_append_character = c;
183 : #endif
184 0 : }
|