1/************************************************************************************
2 Copyright (C) 2014 MariaDB Corporation AB
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this library; if not see <http://www.gnu.org/licenses>
16 or write to the Free Software Foundation, Inc.,
17 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
18*************************************************************************************/
19#include <ma_global.h>
20#include <ma_sys.h>
21#include "mysql.h"
22#include <ma_string.h>
23#include <mariadb_ctype.h>
24#include <stdio.h>
25#include <memory.h>
26
27#ifndef _WIN32
28#include <termios.h>
29#else
30#include <conio.h>
31#endif /* _WIN32 */
32
33/* {{{ static char *get_password() */
34/*
35 read password from device
36
37 SYNOPSIS
38 get_password
39 Hdl/file file handle
40 buffer input buffer
41 length buffer length
42
43 RETURN
44 buffer zero terminated input buffer
45*/
46#ifdef _WIN32
47static char *get_password(HANDLE Hdl, char *buffer, DWORD length)
48#else
49static char *get_password(FILE *file, char *buffer, int length)
50#endif
51{
52 char inChar;
53 int CharsProcessed= 1;
54#ifdef _WIN32
55 DWORD Offset= 0;
56#else
57 int Offset= 0;
58#endif
59 memset(buffer, 0, length);
60
61 do
62 {
63#ifdef _WIN32
64 if (!ReadConsole(Hdl, &inChar, 1, (DWORD *)&CharsProcessed, NULL) ||
65 !CharsProcessed)
66 break;
67#else
68 inChar= fgetc(file);
69#endif
70
71 switch(inChar) {
72 case '\b': /* backslash */
73 if (Offset)
74 {
75 /* cursor is always at the end */
76 Offset--;
77 buffer[Offset]= 0;
78#ifdef _WIN32
79 _cputs("\b \b");
80#endif
81 }
82 break;
83 case '\n':
84 case '\r':
85 break;
86 default:
87 buffer[Offset]= inChar;
88 if (Offset < length - 2)
89 Offset++;
90#ifdef _WIN32
91 _cputs("*");
92#endif
93 break;
94 }
95 } while (CharsProcessed && inChar != '\n' && inChar != '\r');
96 return buffer;
97}
98/* }}} */
99
100/* {{{ static char* get_tty_password */
101/*
102 reads password from tty/console
103
104 SYNOPSIS
105 get_tty_password()
106 buffer input buffer
107 length length of input buffer
108
109 DESCRIPTION
110 reads a password from console (Windows) or tty without echoing
111 it's characters. Input buffer must be allocated by calling function.
112
113 RETURNS
114 buffer pointer to input buffer
115*/
116char* get_tty_password(char *prompt, char *buffer, int length)
117{
118#ifdef _WIN32
119 DWORD SaveState;
120 HANDLE Hdl;
121
122 if (prompt)
123 fprintf(stderr, "%s", prompt);
124
125 if (!(Hdl= CreateFile("CONIN$",
126 GENERIC_READ | GENERIC_WRITE,
127 FILE_SHARE_READ,
128 NULL,
129 OPEN_EXISTING, 0, NULL)))
130 {
131 /* todo: provide a graphical dialog */
132 return buffer;
133 }
134 /* Save ConsoleMode and set ENABLE_PROCESSED_INPUT:
135 CTRL+C is processed by the system and is not placed in the input buffer */
136 GetConsoleMode(Hdl, &SaveState);
137 SetConsoleMode(Hdl, ENABLE_PROCESSED_INPUT);
138
139 buffer= get_password(Hdl, buffer, length);
140 SetConsoleMode(Hdl, SaveState);
141 CloseHandle(Hdl);
142 return buffer;
143#else
144 struct termios term_old,
145 term_new;
146 FILE *readfrom;
147
148 if (prompt && isatty(fileno(stderr)))
149 fputs(prompt, stderr);
150
151 if (!(readfrom= fopen("/dev/tty", "r")))
152 readfrom= stdin;
153
154 /* try to disable echo */
155 tcgetattr(fileno(readfrom), &term_old);
156 term_new= term_old;
157 term_new.c_cc[VMIN] = 1;
158 term_new.c_cc[VTIME]= 0;
159 term_new.c_lflag&= ~(ECHO | ISIG | ICANON | ECHONL);
160 tcsetattr(fileno(readfrom), TCSADRAIN, &term_new);
161
162 buffer= get_password(readfrom, buffer, length);
163
164 if (isatty(fileno(readfrom)))
165 tcsetattr(fileno(readfrom), TCSADRAIN, &term_old);
166
167 fclose(readfrom);
168
169 return buffer;
170#endif
171}
172/* }}} */
173