--- /dev/null
+structure PassGen :> PASSGEN = struct
+
+open Config Sql
+structure C = PgClient
+
+val db = ref (NONE : C.conn option)
+fun getDb () = valOf (!db)
+
+fun begin () =
+ let
+ val c = C.conn dbstring
+ in
+ db := SOME c;
+ ignore (C.dml c "BEGIN")
+ end
+
+fun commit () =
+ let
+ val db = getDb ()
+ in
+ C.dml db "COMMIT";
+ C.close db
+ end
+
+fun gen () =
+ let
+ val db = getDb ()
+
+ val id = case C.oneRow db "SELECT nextval('PassSeq')" of
+ [id] => C.intFromSql id
+ | _ => raise Fail "Bad nextval() return"
+
+ val proc = Unix.execute ("/usr/bin/apg", ["/usr/bin/apg", "-d", "-n", "1"])
+ val inf = Unix.textInstreamOf proc
+
+ val pass = case TextIO.inputLine inf of
+ NONE => raise Fail "No apg output"
+ | SOME line => String.substring (line, 0, size line - 1)
+ in
+ ignore (Unix.reap proc);
+ ignore (C.dml db ($`INSERT INTO Pass (id, pass) VALUES (^(C.intToSql id), ^(C.stringToSql pass))`));
+ (id, pass)
+ end
+
+end