[issue11466] getpass.getpass doesn't close tty file
Steffen Daode Nurpmeso
report at bugs.python.org
Thu Mar 24 15:54:15 CET 2011
Steffen Daode Nurpmeso <sdaoden at googlemail.com> added the comment:
On Thu, Mar 24, 2011 at 02:34:34PM +0000, Senthil Kumaran wrote:
> assignee: -> orsenthil
Here is yet another patch which only passes valid streams into
_user_input(), so that this does not need to take care about that
at all.
Would you please review that instead of all the others ;/?
(It's identical to .5. beside that.)
Thanks for looking at this issue!
----------
Added file: http://bugs.python.org/file21371/11466.6.patch
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue11466>
_______________________________________
-------------- next part --------------
diff --git a/Lib/getpass.py b/Lib/getpass.py
--- a/Lib/getpass.py
+++ b/Lib/getpass.py
@@ -38,27 +38,26 @@
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 as e:
- # If that fails, see if stdin can be controlled.
+ tty, exinst, passwd = None, None, None
+ # Something to break off if an error happens
+ while 1:
try:
- fd = sys.stdin.fileno()
- except (AttributeError, ValueError):
- passwd = fallback_getpass(prompt, stream)
- input = sys.stdin
- if not stream:
- stream = sys.stderr
+ # Always try reading and writing directly on the tty first.
+ fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY)
+ input = tty = os.fdopen(fd, 'w+', 1)
+ if not stream:
+ stream = tty
+ except EnvironmentError:
+ # If that fails, see if stdin can be controlled;
+ # use generic fallback implementation as last resort
+ try:
+ fd = sys.stdin.fileno()
+ except:
+ break
+ 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[:]
@@ -68,21 +67,29 @@
tcsetattr_flags |= termios.TCSASOFT
try:
termios.tcsetattr(fd, tcsetattr_flags, new)
- passwd = _raw_input(prompt, stream, input=input)
+ passwd = _user_input(prompt, stream, input, echooff=True)
+ except Exception as e:
+ exinst = e
finally:
termios.tcsetattr(fd, tcsetattr_flags, old)
- stream.flush() # issue7208
- except termios.error as e:
+ stream.flush() # issue7208 (7246)
+ except Exception as 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)
+ # _user_input succeeded, but the final tcsetattr failed.
+ # Reraise the termios.error instead of leaving the terminal
+ # in an unknown state.
+ exinst = e
+ break
- stream.write('\n')
+ if not exinst and passwd is None:
+ # We can't control the tty or stdin. Give up and use normal IO.
+ # fallback_getpass() raises an appropriate warning.
+ passwd = fallback_getpass(prompt, stream)
+
+ if tty:
+ tty.close()
+ if exinst:
+ raise exinst
return passwd
@@ -115,21 +122,19 @@
if not stream:
stream = sys.stderr
print("Warning: Password input may be echoed.", file=stream)
- return _raw_input(prompt, stream)
+ return _user_input(prompt, stream, sys.stdin, echooff=False)
-def _raw_input(prompt="", stream=None, input=None):
+def _user_input(prompt, stream, input, echooff=False):
# This 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 echooff:
+ stream.write('\n')
if not line:
raise EOFError
if line[-1] == '\n':
More information about the Python-bugs-list
mailing list