~drizzle-trunk/drizzle/development

928.1.1 by Eric Day
Started client changes.
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
/*
21
** Ask for a password from tty
22
** This is an own file to avoid conflicts with curses
23
*/
24
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
25
#include <config.h>
26
#include <client/get_password.h>
928.1.1 by Eric Day
Started client changes.
27
1627.2.2 by Monty Taylor
Moved password parsing code into get_password.cc.
28
#include <string>
29
928.1.1 by Eric Day
Started client changes.
30
#include <string.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <ctype.h>
34
#include <unistd.h>
35
36
#include <sys/ioctl.h>
37
#ifdef HAVE_TERMIOS_H				/* For tty-password */
38
# include	<termios.h>
39
#  define TERMIO	struct termios
40
#else
41
#  ifdef HAVE_TERMIO_H				/* For tty-password */
42
#    include	<termio.h>
43
#    define TERMIO	struct termio
44
#  else
45
#    include	<sgtty.h>
46
#    define TERMIO	struct sgttyb
47
#  endif
48
#endif
49
1627.2.2 by Monty Taylor
Moved password parsing code into get_password.cc.
50
using namespace std;
51
52
bool tty_password= false;
53
const std::string PASSWORD_SENTINEL("\0\0\0\0\0", 5);
54
928.1.1 by Eric Day
Started client changes.
55
/*
56
  Can't use fgets, because readline will get confused
57
  length is max number of chars in to, not counting \0
58
  to will not include the eol characters.
59
*/
60
61
static void get_password(char *to, uint32_t length,int fd, bool echo)
62
{
63
  char *pos=to,*end=to+length;
64
65
  for (;;)
66
  {
67
    char tmp;
68
    if (read(fd,&tmp,1) != 1)
69
      break;
70
    if (tmp == '\b' || (int) tmp == 127)
71
    {
72
      if (pos != to)
73
      {
74
	if (echo)
75
	{
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
76
	  fputs("\b \b",stderr);
77
	  fflush(stderr);
928.1.1 by Eric Day
Started client changes.
78
	}
79
	pos--;
80
	continue;
81
      }
82
    }
83
    if (tmp == '\n' || tmp == '\r' || tmp == 3)
84
      break;
85
    if (iscntrl(tmp) || pos == end)
86
      continue;
87
    *(pos++) = tmp;
88
  }
89
  while (pos != to && isspace(pos[-1]) == ' ')
90
    pos--;					/* Allow dummy space at end */
91
  *pos=0;
92
  return;
93
}
94
95
96
char *client_get_tty_password(const char *opt_message)
97
{
98
  TERMIO org,tmp;
99
  char buff[80];
100
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
101
  if (isatty(fileno(stderr)))
928.1.1 by Eric Day
Started client changes.
102
  {
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
103
    fputs(opt_message ? opt_message : "Enter password: ",stderr);
104
    fflush(stderr);
928.1.1 by Eric Day
Started client changes.
105
  }
106
#  if defined(HAVE_TERMIOS_H)
107
  tcgetattr(fileno(stdin), &org);
108
  tmp = org;
109
  tmp.c_lflag &= ~(ECHO | ISIG | ICANON);
110
  tmp.c_cc[VMIN] = 1;
111
  tmp.c_cc[VTIME] = 0;
112
  tcsetattr(fileno(stdin), TCSADRAIN, &tmp);
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
113
  get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stderr)));
928.1.1 by Eric Day
Started client changes.
114
  tcsetattr(fileno(stdin), TCSADRAIN, &org);
115
#  elif defined(HAVE_TERMIO_H)
116
  ioctl(fileno(stdin), (int) TCGETA, &org);
117
  tmp=org;
118
  tmp.c_lflag &= ~(ECHO | ISIG | ICANON);
119
  tmp.c_cc[VMIN] = 1;
120
  tmp.c_cc[VTIME]= 0;
121
  ioctl(fileno(stdin),(int) TCSETA, &tmp);
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
122
  get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr)));
928.1.1 by Eric Day
Started client changes.
123
  ioctl(fileno(stdin),(int) TCSETA, &org);
124
#  else
125
  gtty(fileno(stdin), &org);
126
  tmp=org;
127
  tmp.sg_flags &= ~ECHO;
128
  tmp.sg_flags |= RAW;
129
  stty(fileno(stdin), &tmp);
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
130
  get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr)));
928.1.1 by Eric Day
Started client changes.
131
  stty(fileno(stdin), &org);
132
#  endif
1839.2.1 by Andrew Hutchings
Output password prompt on stderr
133
  if (isatty(fileno(stderr)))
134
    fputc('\n',stderr);
928.1.1 by Eric Day
Started client changes.
135
136
  return strdup(buff);
137
}
1627.2.2 by Monty Taylor
Moved password parsing code into get_password.cc.
138
139
pair<string, string> parse_password_arg(string s)
140
{
141
  if (s.find("--password") == 0)
142
  {
143
    if (s == "--password")
144
    {
145
      tty_password= true;
146
      //check if no argument is passed.
147
      return make_pair("password", PASSWORD_SENTINEL);
148
    }
149
150
    if (s.substr(10,3) == "=\"\"" || s.substr(10,3) == "=''")
151
    {
152
      // Check if --password="" or --password=''
153
      return make_pair("password", PASSWORD_SENTINEL);
154
    }
155
    
156
    if(s.substr(10) == "=" && s.length() == 11)
157
    {
158
      // check if --password= and return a default value
159
      return make_pair("password", PASSWORD_SENTINEL);
160
    }
161
  }
2254.2.1 by vjsamuel1990 at gmail
Merge fix for -P prompt
162
  
163
  else if (s.find("-P") == 0)
164
  {
165
    if (s == "-P")
166
    {
167
      tty_password= true;
168
      //check if no argument is passed.
169
      return make_pair("password", PASSWORD_SENTINEL);
170
    } 
171
    
172
    if (s.substr(2,2) == "\"\"" || s.substr(2,2) == "''")
173
    {
174
      // Check if -P"" or -P''
175
      return make_pair("password", PASSWORD_SENTINEL);
176
    }  
177
  }
1627.2.2 by Monty Taylor
Moved password parsing code into get_password.cc.
178
  return make_pair(string(""), string(""));
179
}
180