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 2 : void smb_readline_done(void) 59 : { 60 2 : smb_rl_done = true; 61 : #ifdef HAVE_LIBREADLINE 62 2 : rl_done = 1; 63 : #endif 64 2 : } 65 : 66 : /**************************************************************************** 67 : Display the prompt and wait for input. Call callback() regularly 68 : ****************************************************************************/ 69 : 70 295 : static char *smb_readline_replacement(const char *prompt, void (*callback)(void), 71 : char **(completion_fn)(const char *text, int start, int end)) 72 : { 73 295 : char *line = NULL; 74 295 : int fd = fileno(stdin); 75 0 : char *ret; 76 : 77 : /* Prompt might be NULL in non-interactive mode. */ 78 295 : if (prompt) { 79 0 : printf("%s", prompt); 80 0 : fflush(stdout); 81 : } 82 : 83 295 : line = (char *)malloc(BUFSIZ); 84 295 : if (!line) { 85 0 : return NULL; 86 : } 87 : 88 295 : while (!smb_rl_done) { 89 0 : struct pollfd pfd; 90 : 91 295 : ZERO_STRUCT(pfd); 92 295 : pfd.fd = fd; 93 295 : pfd.events = POLLIN|POLLHUP; 94 : 95 295 : if (sys_poll_intr(&pfd, 1, 5000) == 1) { 96 295 : ret = fgets(line, BUFSIZ, stdin); 97 295 : if (ret == 0) { 98 80 : SAFE_FREE(line); 99 : } 100 295 : 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 7094 : char *smb_readline(const char *prompt, void (*callback)(void), 115 : char **(completion_fn)(const char *text, int start, int end)) 116 : { 117 0 : char *ret; 118 0 : bool interactive; 119 : 120 7094 : interactive = isatty(fileno(stdin)) || getenv("CLI_FORCE_INTERACTIVE"); 121 7094 : if (!interactive) { 122 295 : return smb_readline_replacement(NULL, callback, completion_fn); 123 : } 124 : 125 : #ifdef HAVE_LIBREADLINE 126 : 127 : /* Aargh! Readline does bizarre 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 6799 : if (getenv("CLI_NO_READLINE")) 132 0 : return smb_readline_replacement(prompt, callback, completion_fn); 133 : 134 6799 : 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 6799 : 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 6799 : rl_basic_word_break_characters = " \t\n"; 146 : } 147 : 148 : #ifdef HAVE_DECL_RL_EVENT_HOOK 149 6799 : if (callback) 150 6799 : rl_event_hook = (rl_hook_func_t *)callback; 151 : #endif 152 6799 : ret = readline(prompt); 153 6799 : if (ret && *ret) 154 6787 : add_history(ret); 155 : 156 : #else 157 : ret = smb_readline_replacement(prompt, callback, completion_fn); 158 : #endif 159 : 160 6799 : 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 : }