tool_getpass.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "tool_setup.h"
  25. #if defined(__AMIGA__) && !defined(__amigaos4__)
  26. # undef HAVE_TERMIOS_H
  27. #endif
  28. #ifndef HAVE_GETPASS_R
  29. /* this file is only for systems without getpass_r() */
  30. #ifdef HAVE_FCNTL_H
  31. # include <fcntl.h>
  32. #endif
  33. #ifdef HAVE_TERMIOS_H
  34. # include <termios.h>
  35. #elif defined(HAVE_TERMIO_H)
  36. # include <termio.h>
  37. #endif
  38. #ifdef __VMS
  39. # include descrip
  40. # include starlet
  41. # include iodef
  42. #endif
  43. #ifdef _WIN32
  44. # include <conio.h>
  45. #endif
  46. #ifdef HAVE_UNISTD_H
  47. #include <unistd.h>
  48. #endif
  49. #include "tool_getpass.h"
  50. #include "memdebug.h" /* keep this as LAST include */
  51. #ifdef __VMS
  52. /* VMS implementation */
  53. char *getpass_r(const char *prompt, char *buffer, size_t buflen)
  54. {
  55. long sts;
  56. short chan;
  57. /* MSK, 23-JAN-2004, iosbdef.h was not in VAX V7.2 or CC 6.4 */
  58. /* distribution so I created this. May revert back later to */
  59. /* struct _iosb iosb; */
  60. struct _iosb
  61. {
  62. short int iosb$w_status; /* status */
  63. short int iosb$w_bcnt; /* byte count */
  64. int unused; /* unused */
  65. } iosb;
  66. $DESCRIPTOR(ttdesc, "TT");
  67. buffer[0] = '\0';
  68. sts = sys$assign(&ttdesc, &chan, 0, 0);
  69. if(sts & 1) {
  70. sts = sys$qiow(0, chan,
  71. IO$_READPROMPT | IO$M_NOECHO,
  72. &iosb, 0, 0, buffer, buflen, 0, 0,
  73. prompt, strlen(prompt));
  74. if((sts & 1) && (iosb.iosb$w_status & 1))
  75. buffer[iosb.iosb$w_bcnt] = '\0';
  76. sys$dassgn(chan);
  77. }
  78. return buffer; /* we always return success */
  79. }
  80. #define DONE
  81. #endif /* __VMS */
  82. #if defined(_WIN32)
  83. char *getpass_r(const char *prompt, char *buffer, size_t buflen)
  84. {
  85. size_t i;
  86. fputs(prompt, tool_stderr);
  87. for(i = 0; i < buflen; i++) {
  88. buffer[i] = (char)_getch();
  89. if(buffer[i] == '\r' || buffer[i] == '\n') {
  90. buffer[i] = '\0';
  91. break;
  92. }
  93. else
  94. if(buffer[i] == '\b')
  95. /* remove this letter and if this is not the first key, remove the
  96. previous one as well */
  97. i = i - (i >= 1 ? 2 : 1);
  98. }
  99. /* since echo is disabled, print a newline */
  100. fputs("\n", tool_stderr);
  101. /* if user did not hit ENTER, terminate buffer */
  102. if(i == buflen)
  103. buffer[buflen-1] = '\0';
  104. return buffer; /* we always return success */
  105. }
  106. #define DONE
  107. #endif /* _WIN32 */
  108. #ifndef DONE /* not previously provided */
  109. #ifdef HAVE_TERMIOS_H
  110. # define struct_term struct termios
  111. #elif defined(HAVE_TERMIO_H)
  112. # define struct_term struct termio
  113. #else
  114. # undef struct_term
  115. #endif
  116. static bool ttyecho(bool enable, int fd)
  117. {
  118. #ifdef struct_term
  119. static struct_term withecho;
  120. static struct_term noecho;
  121. #endif
  122. if(!enable) {
  123. /* disable echo by extracting the current 'withecho' mode and remove the
  124. ECHO bit and set back the struct */
  125. #ifdef HAVE_TERMIOS_H
  126. tcgetattr(fd, &withecho);
  127. noecho = withecho;
  128. noecho.c_lflag &= ~(tcflag_t)ECHO;
  129. tcsetattr(fd, TCSANOW, &noecho);
  130. #elif defined(HAVE_TERMIO_H)
  131. ioctl(fd, TCGETA, &withecho);
  132. noecho = withecho;
  133. noecho.c_lflag &= ~(tcflag_t)ECHO;
  134. ioctl(fd, TCSETA, &noecho);
  135. #else
  136. /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we cannot disable echo! */
  137. (void)fd;
  138. return FALSE; /* not disabled */
  139. #endif
  140. return TRUE; /* disabled */
  141. }
  142. /* re-enable echo, assumes we disabled it before (and set the structs we
  143. now use to reset the terminal status) */
  144. #ifdef HAVE_TERMIOS_H
  145. tcsetattr(fd, TCSAFLUSH, &withecho);
  146. #elif defined(HAVE_TERMIO_H)
  147. ioctl(fd, TCSETA, &withecho);
  148. #else
  149. return FALSE; /* not enabled */
  150. #endif
  151. return TRUE; /* enabled */
  152. }
  153. char *getpass_r(const char *prompt, /* prompt to display */
  154. char *password, /* buffer to store password in */
  155. size_t buflen) /* size of buffer to store password in */
  156. {
  157. ssize_t nread;
  158. bool disabled;
  159. int fd = open("/dev/tty", O_RDONLY);
  160. if(-1 == fd)
  161. fd = STDIN_FILENO; /* use stdin if the tty could not be used */
  162. disabled = ttyecho(FALSE, fd); /* disable terminal echo */
  163. fputs(prompt, tool_stderr);
  164. nread = read(fd, password, buflen);
  165. if(nread > 0)
  166. password[--nread] = '\0'; /* null-terminate where enter is stored */
  167. else
  168. password[0] = '\0'; /* got nothing */
  169. if(disabled) {
  170. /* if echo actually was disabled, add a newline */
  171. fputs("\n", tool_stderr);
  172. (void)ttyecho(TRUE, fd); /* enable echo */
  173. }
  174. if(STDIN_FILENO != fd)
  175. close(fd);
  176. return password; /* return pointer to buffer */
  177. }
  178. #endif /* DONE */
  179. #endif /* HAVE_GETPASS_R */