/libcli/smbreadline/smbreadline.c

https://bitbucket.org/knarf/samba · C · 185 lines · 111 code · 27 blank · 47 comment · 15 complexity · 1d4e659c081ab79837e4ca9e2f04fb30 MD5 · raw file

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