8194750: Console.readPassword does not save/restore tty settings

Reviewed-by: martin, alanb
diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java
index 53a91a9..e18837f 100644
--- a/src/java.base/share/classes/java/io/Console.java
+++ b/src/java.base/share/classes/java/io/Console.java
@@ -311,8 +311,9 @@
         char[] passwd = null;
         synchronized (writeLock) {
             synchronized(readLock) {
+                boolean echoWasOn;
                 try {
-                    echoOff = echo(false);
+                    echoWasOn = echo(false);
                 } catch (IOException x) {
                     throw new IOError(x);
                 }
@@ -325,7 +326,7 @@
                     ioe = new IOError(x);
                 } finally {
                     try {
-                        echoOff = echo(true);
+                        echo(echoWasOn);
                     } catch (IOException x) {
                         if (ioe == null)
                             ioe = new IOError(x);
@@ -372,8 +373,20 @@
     private Charset cs;
     private char[] rcb;
     private static native String encoding();
+    /*
+     * Sets the console echo status to {@code on} and returns the previous
+     * console on/off status.
+     * @param on    the echo status to set to. {@code true} for echo on and
+     *              {@code false} for echo off
+     * @return true if the previous console echo status is on
+     */
     private static native boolean echo(boolean on) throws IOException;
-    private static boolean echoOff;
+    /*
+     * Returns the current console echo on/off status.
+     * @return true if the cosole echo is on
+     */
+    private static native boolean echo0() throws IOException;
+    private static boolean echoOn;
 
     private char[] readline(boolean zeroOut) throws IOException {
         int len = reader.read(rcb, 0, rcb.length);
@@ -527,9 +540,8 @@
                     new Runnable() {
                         public void run() {
                             try {
-                                if (echoOff) {
-                                    echo(true);
-                                }
+                                if (cons != null)
+                                    echo(echoOn);
                             } catch (IOException x) { }
                         }
                     });
@@ -579,5 +591,10 @@
                      readLock,
                      cs));
         rcb = new char[1024];
+        try {
+            echoOn = echo0();
+        } catch (IOException x) {
+            echoOn = true;
+        }
     }
 }
diff --git a/src/java.base/unix/native/libjava/Console_md.c b/src/java.base/unix/native/libjava/Console_md.c
index c8faa16..be0fcf1 100644
--- a/src/java.base/unix/native/libjava/Console_md.c
+++ b/src/java.base/unix/native/libjava/Console_md.c
@@ -67,3 +67,14 @@
     }
     return old;
 }
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_Console_echo0(JNIEnv *env, jclass cls) {
+    struct termios tio;
+    int tty = fileno(stdin);
+    if (tcgetattr(tty, &tio) == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "tcgetattr failed");
+        return JNI_TRUE;
+    }
+    return (tio.c_lflag & ECHO) != 0;
+}
diff --git a/src/java.base/windows/native/libjava/Console_md.c b/src/java.base/windows/native/libjava/Console_md.c
index 173b2ff..d3c7434 100644
--- a/src/java.base/windows/native/libjava/Console_md.c
+++ b/src/java.base/windows/native/libjava/Console_md.c
@@ -82,3 +82,14 @@
     }
     return old;
 }
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_Console_echo0(JNIEnv *env, jclass cls)
+{
+    DWORD fdwMode;
+    if (! GetConsoleMode(hStdIn, &fdwMode)) {
+        JNU_ThrowIOExceptionWithLastError(env, "GetConsoleMode failed");
+        return JNI_TRUE;
+    }
+    return (fdwMode & ENABLE_ECHO_INPUT) != 0;
+}