Client.getpass: allow use on non-tty devices
[hcoop/domtool2.git] / src / client.sml
CommitLineData
21d921a5
AC
1(* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *)
18
19(* Code for receiving and executing configuration files *)
20
21structure Client :> CLIENT = struct
22
23datatype passwd_result =
24 Passwd of string
25 | Aborted
26 | Error
27
28fun getpass () =
29 let
30 val tty = Posix.FileSys.stdin
9b0be715
CE
31 val termios = SOME (Posix.TTY.TC.getattr tty)
32 handle OS.SysErr (reason, SOME syserr) =>
33 if syserr = Posix.Error.notty then
34 (print "Warning: no terminal found, not hiding password\n";
35 TextIO.flushOut TextIO.stdOut;
36 NONE)
37 else raise OS.SysErr (reason, SOME syserr)
38 val fields = case termios of SOME termios => SOME (Posix.TTY.fieldsOf termios)
39 | NONE => NONE
21d921a5 40
9b0be715
CE
41 val termios' = case fields of SOME fields =>
42 SOME (Posix.TTY.termios {iflag = #iflag fields,
43 oflag = #oflag fields,
44 cflag = #cflag fields,
45 lflag = Posix.TTY.L.flags [Posix.TTY.L.clear (Posix.TTY.L.echo, #lflag fields),
46 Posix.TTY.L.echonl,
47 Posix.TTY.L.icanon],
48 cc = #cc fields,
49 ispeed = #ispeed fields,
50 ospeed = #ospeed fields})
51 | NONE => NONE
21d921a5 52
9b0be715
CE
53 fun reset () = case termios of SOME termios => Posix.TTY.TC.setattr (tty, Posix.TTY.TC.sanow, termios)
54 | NONE => ()
21d921a5
AC
55 in
56 print " Password: ";
57 TextIO.flushOut TextIO.stdOut;
9b0be715
CE
58 case termios' of SOME termios' => Posix.TTY.TC.setattr (tty, Posix.TTY.TC.sanow, termios')
59 | NONE => ();
21d921a5
AC
60 case TextIO.inputLine TextIO.stdIn of
61 NONE => (reset ();
62 Aborted)
63 | SOME pass =>
64 (print "Confirm password: ";
65 TextIO.flushOut TextIO.stdOut;
66 case TextIO.inputLine TextIO.stdIn of
67 NONE => (reset ();
68 Aborted)
69 | SOME pass' =>
70 (reset ();
71 if pass = pass' then
72 Passwd (String.substring (pass, 0, size pass - 1))
73 else
74 (print "Passwords don't match!\n";
75 Error)))
76 end
77
78end