YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/postgres/src/port/sprompt.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * sprompt.c
4
 *    simple_prompt() routine
5
 *
6
 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *
10
 * IDENTIFICATION
11
 *    src/port/sprompt.c
12
 *
13
 *-------------------------------------------------------------------------
14
 */
15
#include "c.h"
16
17
#ifdef HAVE_TERMIOS_H
18
#include <termios.h>
19
#endif
20
21
22
/*
23
 * simple_prompt
24
 *
25
 * Generalized function especially intended for reading in usernames and
26
 * passwords interactively.  Reads from /dev/tty or stdin/stderr.
27
 *
28
 * prompt:    The prompt to print, or NULL if none (automatically localized)
29
 * destination: buffer in which to store result
30
 * destlen:   allocated length of destination
31
 * echo:    Set to false if you want to hide what is entered (for passwords)
32
 *
33
 * The input (without trailing newline) is returned in the destination buffer,
34
 * with a '\0' appended.
35
 */
36
void
37
simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
38
0
{
39
0
  int     length;
40
0
  FILE     *termin,
41
0
         *termout;
42
43
0
#if defined(HAVE_TERMIOS_H)
44
0
  struct termios t_orig,
45
0
        t;
46
#elif defined(WIN32)
47
  HANDLE    t = NULL;
48
  DWORD   t_orig = 0;
49
#endif
50
51
#ifdef WIN32
52
53
  /*
54
   * A Windows console has an "input code page" and an "output code page";
55
   * these usually match each other, but they rarely match the "Windows ANSI
56
   * code page" defined at system boot and expected of "char *" arguments to
57
   * Windows API functions.  The Microsoft CRT write() implementation
58
   * automatically converts text between these code pages when writing to a
59
   * console.  To identify such file descriptors, it calls GetConsoleMode()
60
   * on the underlying HANDLE, which in turn requires GENERIC_READ access on
61
   * the HANDLE.  Opening termout in mode "w+" allows that detection to
62
   * succeed.  Otherwise, write() would not recognize the descriptor as a
63
   * console, and non-ASCII characters would display incorrectly.
64
   *
65
   * XXX fgets() still receives text in the console's input code page.  This
66
   * makes non-ASCII credentials unportable.
67
   *
68
   * Unintuitively, we also open termin in mode "w+", even though we only
69
   * read it; that's needed for SetConsoleMode() to succeed.
70
   */
71
  termin = fopen("CONIN$", "w+");
72
  termout = fopen("CONOUT$", "w+");
73
#else
74
75
  /*
76
   * Do not try to collapse these into one "w+" mode file. Doesn't work on
77
   * some platforms (eg, HPUX 10.20).
78
   */
79
0
  termin = fopen("/dev/tty", "r");
80
0
  termout = fopen("/dev/tty", "w");
81
0
#endif
82
0
  if (!termin || !termout
83
#ifdef WIN32
84
85
  /*
86
   * Direct console I/O does not work from the MSYS 1.0.10 console.  Writes
87
   * reach nowhere user-visible; reads block indefinitely.  XXX This affects
88
   * most Windows terminal environments, including rxvt, mintty, Cygwin
89
   * xterm, Cygwin sshd, and PowerShell ISE.  Switch to a more-generic test.
90
   */
91
    || (getenv("OSTYPE") && strcmp(getenv("OSTYPE"), "msys") == 0)
92
#endif
93
0
    )
94
0
  {
95
0
    if (termin)
96
0
      fclose(termin);
97
0
    if (termout)
98
0
      fclose(termout);
99
0
    termin = stdin;
100
0
    termout = stderr;
101
0
  }
102
103
0
  if (!echo)
104
0
  {
105
0
#if defined(HAVE_TERMIOS_H)
106
    /* disable echo via tcgetattr/tcsetattr */
107
0
    tcgetattr(fileno(termin), &t);
108
0
    t_orig = t;
109
0
    t.c_lflag &= ~ECHO;
110
0
    tcsetattr(fileno(termin), TCSAFLUSH, &t);
111
#elif defined(WIN32)
112
    /* need the file's HANDLE to turn echo off */
113
    t = (HANDLE) _get_osfhandle(_fileno(termin));
114
115
    /* save the old configuration first */
116
    GetConsoleMode(t, &t_orig);
117
118
    /* set to the new mode */
119
    SetConsoleMode(t, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
120
#endif
121
0
  }
122
123
0
  if (prompt)
124
0
  {
125
0
    fputs(_(prompt), termout);
126
0
    fflush(termout);
127
0
  }
128
129
0
  if (fgets(destination, destlen, termin) == NULL)
130
0
    destination[0] = '\0';
131
132
0
  length = strlen(destination);
133
0
  if (length > 0 && destination[length - 1] != '\n')
134
0
  {
135
    /* eat rest of the line */
136
0
    char    buf[128];
137
0
    int     buflen;
138
139
0
    do
140
0
    {
141
0
      if (fgets(buf, sizeof(buf), termin) == NULL)
142
0
        break;
143
0
      buflen = strlen(buf);
144
0
    } while (buflen > 0 && buf[buflen - 1] != '\n');
145
0
  }
146
147
0
  if (length > 0 && destination[length - 1] == '\n')
148
    /* remove trailing newline */
149
0
    destination[length - 1] = '\0';
150
151
0
  if (!echo)
152
0
  {
153
    /* restore previous echo behavior, then echo \n */
154
0
#if defined(HAVE_TERMIOS_H)
155
0
    tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
156
0
    fputs("\n", termout);
157
0
    fflush(termout);
158
#elif defined(WIN32)
159
    SetConsoleMode(t, t_orig);
160
    fputs("\n", termout);
161
    fflush(termout);
162
#endif
163
0
  }
164
165
0
  if (termin != stdin)
166
0
  {
167
0
    fclose(termin);
168
0
    fclose(termout);
169
0
  }
170
0
}