OSDN Git Service

Avoid trying to open /dev/tty on Win32. Some Win32 systems have
[pg-rex/syncrep.git] / src / port / sprompt.c
1 /*-------------------------------------------------------------------------
2  *
3  * sprompt.c
4  *        simple_prompt() routine
5  *
6  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/port/sprompt.c,v 1.13 2006/03/03 23:49:12 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16
17 /*
18  * simple_prompt
19  *
20  * Generalized function especially intended for reading in usernames and
21  * password interactively. Reads from /dev/tty or stdin/stderr.
22  *
23  * prompt:              The prompt to print
24  * maxlen:              How many characters to accept
25  * echo:                Set to false if you want to hide what is entered (for passwords)
26  *
27  * Returns a malloc()'ed string with the input (w/o trailing newline).
28  */
29 #include "c.h"
30
31 #ifdef HAVE_TERMIOS_H
32 #include <termios.h>
33 #endif
34
35 bool            prompt_state = false;
36 extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
37
38 char *
39 simple_prompt(const char *prompt, int maxlen, bool echo)
40 {
41         int                     length;
42         char       *destination;
43         FILE       *termin = NULL,
44                            *termout = NULL;
45
46 #ifdef HAVE_TERMIOS_H
47         struct termios t_orig,
48                                 t;
49 #else
50 #ifdef WIN32
51         HANDLE          t = NULL;
52         LPDWORD         t_orig = NULL;
53 #endif
54 #endif
55
56         destination = (char *) malloc(maxlen + 1);
57         if (!destination)
58                 return NULL;
59
60         prompt_state = true;            /* disable SIGINT */
61
62         /*
63          * Do not try to collapse these into one "w+" mode file. Doesn't work on
64          * some platforms (eg, HPUX 10.20).
65          */
66 #ifndef WIN32
67         /*
68          *      Some win32 platforms actually have a /dev/tty file, but it isn't
69          *      a device file, and it doesn't work as expected, so we avoid trying.
70          */
71         termin = fopen("/dev/tty", "r");
72         termout = fopen("/dev/tty", "w");
73 #endif
74         if (!termin || !termout)
75         {
76                 if (termin)
77                         fclose(termin);
78                 if (termout)
79                         fclose(termout);
80                 termin = stdin;
81                 termout = stderr;
82         }
83
84 #ifdef HAVE_TERMIOS_H
85         if (!echo)
86         {
87                 tcgetattr(fileno(termin), &t);
88                 t_orig = t;
89                 t.c_lflag &= ~ECHO;
90                 tcsetattr(fileno(termin), TCSAFLUSH, &t);
91         }
92 #else
93 #ifdef WIN32
94         if (!echo)
95         {
96                 /* get a new handle to turn echo off */
97                 t_orig = (LPDWORD) malloc(sizeof(DWORD));
98                 t = GetStdHandle(STD_INPUT_HANDLE);
99
100                 /* save the old configuration first */
101                 GetConsoleMode(t, t_orig);
102
103                 /* set to the new mode */
104                 SetConsoleMode(t, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
105         }
106 #endif
107 #endif
108
109         if (prompt)
110         {
111                 fputs(_(prompt), termout);
112                 fflush(termout);
113         }
114
115         if (fgets(destination, maxlen + 1, termin) == NULL)
116                 destination[0] = '\0';
117
118         length = strlen(destination);
119         if (length > 0 && destination[length - 1] != '\n')
120         {
121                 /* eat rest of the line */
122                 char            buf[128];
123                 int                     buflen;
124
125                 do
126                 {
127                         if (fgets(buf, sizeof(buf), termin) == NULL)
128                                 break;
129                         buflen = strlen(buf);
130                 } while (buflen > 0 && buf[buflen - 1] != '\n');
131         }
132
133         if (length > 0 && destination[length - 1] == '\n')
134                 /* remove trailing newline */
135                 destination[length - 1] = '\0';
136
137 #ifdef HAVE_TERMIOS_H
138         if (!echo)
139         {
140                 tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
141                 fputs("\n", termout);
142                 fflush(termout);
143         }
144 #else
145 #ifdef WIN32
146         if (!echo)
147         {
148                 /* reset to the original console mode */
149                 SetConsoleMode(t, *t_orig);
150                 fputs("\n", termout);
151                 fflush(termout);
152                 free(t_orig);
153         }
154 #endif
155 #endif
156
157         if (termin != stdin)
158         {
159                 fclose(termin);
160                 fclose(termout);
161         }
162
163         prompt_state = false;           /* SIGINT okay again */
164
165         return destination;
166 }