Client.getpass: allow use on non-tty devices
authorClinton Ebadi <clinton@unknownlamer.org>
Fri, 9 May 2014 08:41:29 +0000 (04:41 -0400)
committerClinton Ebadi <clinton@unknownlamer.org>
Fri, 9 May 2014 08:41:29 +0000 (04:41 -0400)
Warn user the password will be echoed just in case. This allows
getpass to be used with input piped to it (e.g. from the hcoop members
portal).

src/client.sml

index 863c0c0..00000e7 100644 (file)
@@ -28,24 +28,35 @@ datatype passwd_result =
 fun getpass () =
     let
        val tty = Posix.FileSys.stdin
-       val termios = Posix.TTY.TC.getattr tty
-       val fields = Posix.TTY.fieldsOf termios
+       val termios = SOME (Posix.TTY.TC.getattr tty)
+                     handle OS.SysErr (reason, SOME syserr) =>
+                            if syserr = Posix.Error.notty then
+                                (print "Warning: no terminal found, not hiding password\n";
+                                 TextIO.flushOut TextIO.stdOut;
+                                 NONE)
+                            else raise OS.SysErr (reason, SOME syserr)
+       val fields = case termios of SOME termios => SOME (Posix.TTY.fieldsOf termios)
+                                  | NONE => NONE
 
-       val termios' = Posix.TTY.termios {iflag = #iflag fields,
-                                         oflag = #oflag fields,
-                                         cflag = #cflag fields,
-                                         lflag = Posix.TTY.L.flags [Posix.TTY.L.clear (Posix.TTY.L.echo, #lflag fields),
-                                                                    Posix.TTY.L.echonl,
-                                                                    Posix.TTY.L.icanon],
-                                         cc = #cc fields,
-                                         ispeed = #ispeed fields,
-                                         ospeed = #ospeed fields}
+       val termios' = case fields of SOME fields =>
+                                     SOME (Posix.TTY.termios {iflag = #iflag fields,
+                                                              oflag = #oflag fields,
+                                                              cflag = #cflag fields,
+                                                              lflag = Posix.TTY.L.flags [Posix.TTY.L.clear (Posix.TTY.L.echo, #lflag fields),
+                                                                                         Posix.TTY.L.echonl,
+                                                                                         Posix.TTY.L.icanon],
+                                                              cc = #cc fields,
+                                                              ispeed = #ispeed fields,
+                                                              ospeed = #ospeed fields})
+                                   | NONE => NONE
 
-       fun reset () = Posix.TTY.TC.setattr (tty, Posix.TTY.TC.sanow, termios)
+       fun reset () = case termios of SOME termios => Posix.TTY.TC.setattr (tty, Posix.TTY.TC.sanow, termios)
+                                    | NONE => ()
     in
        print "        Password: ";
        TextIO.flushOut TextIO.stdOut;
-       Posix.TTY.TC.setattr (tty, Posix.TTY.TC.sanow, termios');
+       case termios' of SOME termios' => Posix.TTY.TC.setattr (tty, Posix.TTY.TC.sanow, termios')
+                      | NONE => ();
        case TextIO.inputLine TextIO.stdIn of
            NONE => (reset ();
                     Aborted)