LCOV - code coverage report
Current view: top level - src/port - sprompt.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 0 38 0.0 %
Date: 2019-11-13 21:06:57 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * sprompt.c
       4             :  *    simple_prompt() routine
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, 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           0 : simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
      38             : {
      39             :     int         length;
      40             :     FILE       *termin,
      41             :                *termout;
      42             : 
      43             : #if defined(HAVE_TERMIOS_H)
      44             :     struct termios t_orig,
      45             :                 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             : #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             :         )
      94             :     {
      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             :     }
     102             : 
     103           0 :     if (!echo)
     104             :     {
     105             : #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             :     }
     122             : 
     123           0 :     if (prompt)
     124             :     {
     125           0 :         fputs(_(prompt), termout);
     126           0 :         fflush(termout);
     127             :     }
     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             :     {
     135             :         /* eat rest of the line */
     136             :         char        buf[128];
     137             :         int         buflen;
     138             : 
     139             :         do
     140             :         {
     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             :     }
     146             : 
     147             :     /* strip trailing newline, including \r in case we're on Windows */
     148           0 :     while (length > 0 &&
     149           0 :            (destination[length - 1] == '\n' ||
     150           0 :             destination[length - 1] == '\r'))
     151           0 :         destination[--length] = '\0';
     152             : 
     153           0 :     if (!echo)
     154             :     {
     155             :         /* restore previous echo behavior, then echo \n */
     156             : #if defined(HAVE_TERMIOS_H)
     157           0 :         tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
     158           0 :         fputs("\n", termout);
     159           0 :         fflush(termout);
     160             : #elif defined(WIN32)
     161             :         SetConsoleMode(t, t_orig);
     162             :         fputs("\n", termout);
     163             :         fflush(termout);
     164             : #endif
     165             :     }
     166             : 
     167           0 :     if (termin != stdin)
     168             :     {
     169           0 :         fclose(termin);
     170           0 :         fclose(termout);
     171             :     }
     172           0 : }

Generated by: LCOV version 1.13