(root)/
Python-3.11.7/
Lib/
getpass.py
       1  """Utilities to get a password and/or the current user name.
       2  
       3  getpass(prompt[, stream]) - Prompt for a password, with echo turned off.
       4  getuser() - Get the user name from the environment or password database.
       5  
       6  GetPassWarning - This UserWarning is issued when getpass() cannot prevent
       7                   echoing of the password contents while reading.
       8  
       9  On Windows, the msvcrt module will be used.
      10  
      11  """
      12  
      13  # Authors: Piers Lauder (original)
      14  #          Guido van Rossum (Windows support and cleanup)
      15  #          Gregory P. Smith (tty support & GetPassWarning)
      16  
      17  import contextlib
      18  import io
      19  import os
      20  import sys
      21  import warnings
      22  
      23  __all__ = ["getpass","getuser","GetPassWarning"]
      24  
      25  
      26  class ESC[4;38;5;81mGetPassWarning(ESC[4;38;5;149mUserWarning): pass
      27  
      28  
      29  def unix_getpass(prompt='Password: ', stream=None):
      30      """Prompt for a password, with echo turned off.
      31  
      32      Args:
      33        prompt: Written on stream to ask for the input.  Default: 'Password: '
      34        stream: A writable file object to display the prompt.  Defaults to
      35                the tty.  If no tty is available defaults to sys.stderr.
      36      Returns:
      37        The seKr3t input.
      38      Raises:
      39        EOFError: If our input tty or stdin was closed.
      40        GetPassWarning: When we were unable to turn echo off on the input.
      41  
      42      Always restores terminal settings before returning.
      43      """
      44      passwd = None
      45      with contextlib.ExitStack() as stack:
      46          try:
      47              # Always try reading and writing directly on the tty first.
      48              fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY)
      49              tty = io.FileIO(fd, 'w+')
      50              stack.enter_context(tty)
      51              input = io.TextIOWrapper(tty)
      52              stack.enter_context(input)
      53              if not stream:
      54                  stream = input
      55          except OSError:
      56              # If that fails, see if stdin can be controlled.
      57              stack.close()
      58              try:
      59                  fd = sys.stdin.fileno()
      60              except (AttributeError, ValueError):
      61                  fd = None
      62                  passwd = fallback_getpass(prompt, stream)
      63              input = sys.stdin
      64              if not stream:
      65                  stream = sys.stderr
      66  
      67          if fd is not None:
      68              try:
      69                  old = termios.tcgetattr(fd)     # a copy to save
      70                  new = old[:]
      71                  new[3] &= ~termios.ECHO  # 3 == 'lflags'
      72                  tcsetattr_flags = termios.TCSAFLUSH
      73                  if hasattr(termios, 'TCSASOFT'):
      74                      tcsetattr_flags |= termios.TCSASOFT
      75                  try:
      76                      termios.tcsetattr(fd, tcsetattr_flags, new)
      77                      passwd = _raw_input(prompt, stream, input=input)
      78                  finally:
      79                      termios.tcsetattr(fd, tcsetattr_flags, old)
      80                      stream.flush()  # issue7208
      81              except termios.error:
      82                  if passwd is not None:
      83                      # _raw_input succeeded.  The final tcsetattr failed.  Reraise
      84                      # instead of leaving the terminal in an unknown state.
      85                      raise
      86                  # We can't control the tty or stdin.  Give up and use normal IO.
      87                  # fallback_getpass() raises an appropriate warning.
      88                  if stream is not input:
      89                      # clean up unused file objects before blocking
      90                      stack.close()
      91                  passwd = fallback_getpass(prompt, stream)
      92  
      93          stream.write('\n')
      94          return passwd
      95  
      96  
      97  def win_getpass(prompt='Password: ', stream=None):
      98      """Prompt for password with echo off, using Windows getwch()."""
      99      if sys.stdin is not sys.__stdin__:
     100          return fallback_getpass(prompt, stream)
     101  
     102      for c in prompt:
     103          msvcrt.putwch(c)
     104      pw = ""
     105      while 1:
     106          c = msvcrt.getwch()
     107          if c == '\r' or c == '\n':
     108              break
     109          if c == '\003':
     110              raise KeyboardInterrupt
     111          if c == '\b':
     112              pw = pw[:-1]
     113          else:
     114              pw = pw + c
     115      msvcrt.putwch('\r')
     116      msvcrt.putwch('\n')
     117      return pw
     118  
     119  
     120  def fallback_getpass(prompt='Password: ', stream=None):
     121      warnings.warn("Can not control echo on the terminal.", GetPassWarning,
     122                    stacklevel=2)
     123      if not stream:
     124          stream = sys.stderr
     125      print("Warning: Password input may be echoed.", file=stream)
     126      return _raw_input(prompt, stream)
     127  
     128  
     129  def _raw_input(prompt="", stream=None, input=None):
     130      # This doesn't save the string in the GNU readline history.
     131      if not stream:
     132          stream = sys.stderr
     133      if not input:
     134          input = sys.stdin
     135      prompt = str(prompt)
     136      if prompt:
     137          try:
     138              stream.write(prompt)
     139          except UnicodeEncodeError:
     140              # Use replace error handler to get as much as possible printed.
     141              prompt = prompt.encode(stream.encoding, 'replace')
     142              prompt = prompt.decode(stream.encoding)
     143              stream.write(prompt)
     144          stream.flush()
     145      # NOTE: The Python C API calls flockfile() (and unlock) during readline.
     146      line = input.readline()
     147      if not line:
     148          raise EOFError
     149      if line[-1] == '\n':
     150          line = line[:-1]
     151      return line
     152  
     153  
     154  def getuser():
     155      """Get the username from the environment or password database.
     156  
     157      First try various environment variables, then the password
     158      database.  This works on Windows as long as USERNAME is set.
     159  
     160      """
     161  
     162      for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
     163          user = os.environ.get(name)
     164          if user:
     165              return user
     166  
     167      # If this fails, the exception will "explain" why
     168      import pwd
     169      return pwd.getpwuid(os.getuid())[0]
     170  
     171  # Bind the name getpass to the appropriate function
     172  try:
     173      import termios
     174      # it's possible there is an incompatible termios from the
     175      # McMillan Installer, make sure we have a UNIX-compatible termios
     176      termios.tcgetattr, termios.tcsetattr
     177  except (ImportError, AttributeError):
     178      try:
     179          import msvcrt
     180      except ImportError:
     181          getpass = fallback_getpass
     182      else:
     183          getpass = win_getpass
     184  else:
     185      getpass = unix_getpass