| """Utilities to get a password and/or the current user name. | |
| getpass(prompt[, stream]) - Prompt for a password, with echo turned off. | |
| getuser() - Get the user name from the environment or password database. | |
| GetPassWarning - This UserWarning is issued when getpass() cannot prevent | |
| echoing of the password contents while reading. | |
| On Windows, the msvcrt module will be used. | |
| On the Mac EasyDialogs.AskPassword is used, if available. | |
| """ | |
| # Authors: Piers Lauder (original) | |
| # Guido van Rossum (Windows support and cleanup) | |
| # Gregory P. Smith (tty support & GetPassWarning) | |
| import os, sys, warnings | |
| __all__ = ["getpass","getuser","GetPassWarning"] | |
| class GetPassWarning(UserWarning): pass | |
| def unix_getpass(prompt='Password: ', stream=None): | |
| """Prompt for a password, with echo turned off. | |
| Args: | |
| prompt: Written on stream to ask for the input. Default: 'Password: ' | |
| stream: A writable file object to display the prompt. Defaults to | |
| the tty. If no tty is available defaults to sys.stderr. | |
| Returns: | |
| The seKr3t input. | |
| Raises: | |
| EOFError: If our input tty or stdin was closed. | |
| GetPassWarning: When we were unable to turn echo off on the input. | |
| Always restores terminal settings before returning. | |
| """ | |
| fd = None | |
| tty = None | |
| try: | |
| # Always try reading and writing directly on the tty first. | |
| fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY) | |
| tty = os.fdopen(fd, 'w+', 1) | |
| input = tty | |
| if not stream: | |
| stream = tty | |
| except EnvironmentError, e: | |
| # If that fails, see if stdin can be controlled. | |
| try: | |
| fd = sys.stdin.fileno() | |
| except (AttributeError, ValueError): | |
| passwd = fallback_getpass(prompt, stream) | |
| input = sys.stdin | |
| if not stream: | |
| stream = sys.stderr | |
| if fd is not None: | |
| passwd = None | |
| try: | |
| old = termios.tcgetattr(fd) # a copy to save | |
| new = old[:] | |
| new[3] &= ~termios.ECHO # 3 == 'lflags' | |
| tcsetattr_flags = termios.TCSAFLUSH | |
| if hasattr(termios, 'TCSASOFT'): | |
| tcsetattr_flags |= termios.TCSASOFT | |
| try: | |
| termios.tcsetattr(fd, tcsetattr_flags, new) | |
| passwd = _raw_input(prompt, stream, input=input) | |
| finally: | |
| termios.tcsetattr(fd, tcsetattr_flags, old) | |
| stream.flush() # issue7208 | |
| except termios.error, e: | |
| if passwd is not None: | |
| # _raw_input succeeded. The final tcsetattr failed. Reraise | |
| # instead of leaving the terminal in an unknown state. | |
| raise | |
| # We can't control the tty or stdin. Give up and use normal IO. | |
| # fallback_getpass() raises an appropriate warning. | |
| del input, tty # clean up unused file objects before blocking | |
| passwd = fallback_getpass(prompt, stream) | |
| stream.write('\n') | |
| return passwd | |
| def win_getpass(prompt='Password: ', stream=None): | |
| """Prompt for password with echo off, using Windows getch().""" | |
| if sys.stdin is not sys.__stdin__: | |
| return fallback_getpass(prompt, stream) | |
| import msvcrt | |
| for c in prompt: | |
| msvcrt.putch(c) | |
| pw = "" | |
| while 1: | |
| c = msvcrt.getch() | |
| if c == '\r' or c == '\n': | |
| break | |
| if c == '\003': | |
| raise KeyboardInterrupt | |
| if c == '\b': | |
| pw = pw[:-1] | |
| else: | |
| pw = pw + c | |
| msvcrt.putch('\r') | |
| msvcrt.putch('\n') | |
| return pw | |
| def fallback_getpass(prompt='Password: ', stream=None): | |
| warnings.warn("Can not control echo on the terminal.", GetPassWarning, | |
| stacklevel=2) | |
| if not stream: | |
| stream = sys.stderr | |
| print >>stream, "Warning: Password input may be echoed." | |
| return _raw_input(prompt, stream) | |
| def _raw_input(prompt="", stream=None, input=None): | |
| # A raw_input() replacement that doesn't save the string in the | |
| # GNU readline history. | |
| if not stream: | |
| stream = sys.stderr | |
| if not input: | |
| input = sys.stdin | |
| prompt = str(prompt) | |
| if prompt: | |
| stream.write(prompt) | |
| stream.flush() | |
| # NOTE: The Python C API calls flockfile() (and unlock) during readline. | |
| line = input.readline() | |
| if not line: | |
| raise EOFError | |
| if line[-1] == '\n': | |
| line = line[:-1] | |
| return line | |
| def getuser(): | |
| """Get the username from the environment or password database. | |
| First try various environment variables, then the password | |
| database. This works on Windows as long as USERNAME is set. | |
| """ | |
| import os | |
| for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'): | |
| user = os.environ.get(name) | |
| if user: | |
| return user | |
| # If this fails, the exception will "explain" why | |
| import pwd | |
| return pwd.getpwuid(os.getuid())[0] | |
| # Bind the name getpass to the appropriate function | |
| try: | |
| import termios | |
| # it's possible there is an incompatible termios from the | |
| # McMillan Installer, make sure we have a UNIX-compatible termios | |
| termios.tcgetattr, termios.tcsetattr | |
| except (ImportError, AttributeError): | |
| try: | |
| import msvcrt | |
| except ImportError: | |
| try: | |
| from EasyDialogs import AskPassword | |
| except ImportError: | |
| getpass = fallback_getpass | |
| else: | |
| getpass = AskPassword | |
| else: | |
| getpass = win_getpass | |
| else: | |
| getpass = unix_getpass |