blob: 07c89ff0b978d3b44e3ff9c6316d29f1162b7354 [file] [log] [blame]
Guido van Rossumb5903ac1998-04-09 20:37:16 +00001"""Utilities to get a password and/or the current user name.
2
3getpass(prompt) - prompt for a password, with echo turned off
4getuser() - get the user name from the environment or password database
5
Jeremy Hylton88d23301999-10-18 22:25:22 +00006On Windows, the msvcrt module will be used.
7On the Mac EasyDialogs.AskPassword is used, if available.
8
Guido van Rossumb5903ac1998-04-09 20:37:16 +00009"""
10
Guido van Rossum98d9fd32000-02-28 15:12:25 +000011# Authors: Piers Lauder (original)
12# Guido van Rossum (Windows support and cleanup)
13
Jeremy Hylton88d23301999-10-18 22:25:22 +000014import sys
Guido van Rossumb5903ac1998-04-09 20:37:16 +000015
Skip Montanaroeccd02a2001-01-20 23:34:12 +000016__all__ = ["getpass","getuser"]
17
Georg Brandl338ef7d2006-03-31 18:42:16 +000018def unix_getpass(prompt='Password: ', stream=None):
Tim Peters07e99cb2001-01-14 23:47:14 +000019 """Prompt for a password, with echo turned off.
Georg Brandl338ef7d2006-03-31 18:42:16 +000020 The prompt is written on stream, by default stdout.
Guido van Rossumb5903ac1998-04-09 20:37:16 +000021
Tim Peters07e99cb2001-01-14 23:47:14 +000022 Restore terminal settings at end.
23 """
Georg Brandl338ef7d2006-03-31 18:42:16 +000024 if stream is None:
25 stream = sys.stdout
Guido van Rossumb5903ac1998-04-09 20:37:16 +000026
Gregory P. Smith41e30182008-04-21 21:31:08 +000027 if not sys.stdin.isatty():
28 print >>sys.stderr, "Warning: sys.stdin is not a tty."
29 return default_getpass(prompt)
30
Tim Peters07e99cb2001-01-14 23:47:14 +000031 try:
32 fd = sys.stdin.fileno()
33 except:
34 return default_getpass(prompt)
Guido van Rossumb5903ac1998-04-09 20:37:16 +000035
Tim Peters07e99cb2001-01-14 23:47:14 +000036 old = termios.tcgetattr(fd) # a copy to save
37 new = old[:]
Guido van Rossumb5903ac1998-04-09 20:37:16 +000038
Fred Drake1191d012001-02-27 21:23:31 +000039 new[3] = new[3] & ~termios.ECHO # 3 == 'lflags'
Tim Peters07e99cb2001-01-14 23:47:14 +000040 try:
Fred Drake1191d012001-02-27 21:23:31 +000041 termios.tcsetattr(fd, termios.TCSADRAIN, new)
Georg Brandl338ef7d2006-03-31 18:42:16 +000042 passwd = _raw_input(prompt, stream)
Tim Peters07e99cb2001-01-14 23:47:14 +000043 finally:
Fred Drake1191d012001-02-27 21:23:31 +000044 termios.tcsetattr(fd, termios.TCSADRAIN, old)
Guido van Rossumb5903ac1998-04-09 20:37:16 +000045
Georg Brandl338ef7d2006-03-31 18:42:16 +000046 stream.write('\n')
Tim Peters07e99cb2001-01-14 23:47:14 +000047 return passwd
Guido van Rossumb5903ac1998-04-09 20:37:16 +000048
49
Georg Brandl338ef7d2006-03-31 18:42:16 +000050def win_getpass(prompt='Password: ', stream=None):
Tim Peters07e99cb2001-01-14 23:47:14 +000051 """Prompt for password with echo off, using Windows getch()."""
Guido van Rossum60250e22001-08-30 15:07:44 +000052 if sys.stdin is not sys.__stdin__:
Georg Brandl338ef7d2006-03-31 18:42:16 +000053 return default_getpass(prompt, stream)
Tim Peters07e99cb2001-01-14 23:47:14 +000054 import msvcrt
55 for c in prompt:
56 msvcrt.putch(c)
57 pw = ""
58 while 1:
59 c = msvcrt.getch()
60 if c == '\r' or c == '\n':
61 break
62 if c == '\003':
63 raise KeyboardInterrupt
64 if c == '\b':
65 pw = pw[:-1]
66 else:
67 pw = pw + c
68 msvcrt.putch('\r')
69 msvcrt.putch('\n')
70 return pw
Guido van Rossumb5903ac1998-04-09 20:37:16 +000071
72
Georg Brandl338ef7d2006-03-31 18:42:16 +000073def default_getpass(prompt='Password: ', stream=None):
74 print >>sys.stderr, "Warning: Problem with getpass. Passwords may be echoed."
75 return _raw_input(prompt, stream)
Guido van Rossum1a7bab01998-07-28 19:28:43 +000076
77
Georg Brandl338ef7d2006-03-31 18:42:16 +000078def _raw_input(prompt="", stream=None):
Tim Peters07e99cb2001-01-14 23:47:14 +000079 # A raw_input() replacement that doesn't save the string in the
80 # GNU readline history.
Georg Brandl338ef7d2006-03-31 18:42:16 +000081 if stream is None:
82 stream = sys.stdout
Tim Peters07e99cb2001-01-14 23:47:14 +000083 prompt = str(prompt)
84 if prompt:
Georg Brandl338ef7d2006-03-31 18:42:16 +000085 stream.write(prompt)
Tim Peters07e99cb2001-01-14 23:47:14 +000086 line = sys.stdin.readline()
87 if not line:
88 raise EOFError
89 if line[-1] == '\n':
90 line = line[:-1]
91 return line
Guido van Rossumfb9b7fd1998-04-13 20:22:21 +000092
93
Guido van Rossumb5903ac1998-04-09 20:37:16 +000094def getuser():
Tim Peters07e99cb2001-01-14 23:47:14 +000095 """Get the username from the environment or password database.
Guido van Rossumb5903ac1998-04-09 20:37:16 +000096
Tim Peters07e99cb2001-01-14 23:47:14 +000097 First try various environment variables, then the password
98 database. This works on Windows as long as USERNAME is set.
Guido van Rossumb5903ac1998-04-09 20:37:16 +000099
Tim Peters07e99cb2001-01-14 23:47:14 +0000100 """
Guido van Rossumb5903ac1998-04-09 20:37:16 +0000101
Tim Peters07e99cb2001-01-14 23:47:14 +0000102 import os
Guido van Rossumb5903ac1998-04-09 20:37:16 +0000103
Tim Peters07e99cb2001-01-14 23:47:14 +0000104 for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
105 user = os.environ.get(name)
106 if user:
107 return user
Guido van Rossumb5903ac1998-04-09 20:37:16 +0000108
Tim Peters07e99cb2001-01-14 23:47:14 +0000109 # If this fails, the exception will "explain" why
110 import pwd
111 return pwd.getpwuid(os.getuid())[0]
Jeremy Hylton88d23301999-10-18 22:25:22 +0000112
113# Bind the name getpass to the appropriate function
114try:
Fred Drake1191d012001-02-27 21:23:31 +0000115 import termios
Neal Norwitz201626e2002-11-20 23:15:54 +0000116 # it's possible there is an incompatible termios from the
117 # McMillan Installer, make sure we have a UNIX-compatible termios
118 termios.tcgetattr, termios.tcsetattr
119except (ImportError, AttributeError):
Tim Peters07e99cb2001-01-14 23:47:14 +0000120 try:
121 import msvcrt
122 except ImportError:
123 try:
124 from EasyDialogs import AskPassword
125 except ImportError:
126 getpass = default_getpass
127 else:
128 getpass = AskPassword
129 else:
130 getpass = win_getpass
Jeremy Hylton88d23301999-10-18 22:25:22 +0000131else:
Tim Peters07e99cb2001-01-14 23:47:14 +0000132 getpass = unix_getpass