@@ 2,9 2,12 @@ use bufio;
use bytes;
use dirs;
use encoding::base64;
+use encoding::utf8;
use fmt;
use format::ssh;
use getopt;
+use himitsu::client;
+use himitsu::query;
use io;
use net::unix;
use net;
@@ 63,7 66,7 @@ export fn main() void = {
let buf = memio::dynamic();
defer io::close(&buf)!;
- fmt::fprintf(&buf, "add proto=ssh type={} pkey='", ssh::key_format(privkey))!;
+ fmt::fprintf(&buf, "proto=ssh type={} pkey='", ssh::key_format(privkey))!;
let b64 = base64::newencoder(&base64::std_encoding, &buf);
ssh::key_encoderawpub(privkey, &b64)!;
io::close(&b64)!;
@@ 77,31 80,40 @@ export fn main() void = {
shlex::quote(&buf, privkey.comment)!;
};
fmt::fprintln(&buf)!;
+ let q = match (query::parse_str(memio::string(&buf)!)) {
+ case let q: query::query =>
+ yield q;
+ case let e: query::error =>
+ fmt::fatal("Error preparing query:", query::strerror(e));
+ };
+ defer query::finish(&q);
- // TODO: It would be nice if himitsu (library) provided some tools for
- // connecting to and interacting with a Himitsu socket
- let path = path::init()!;
- const sockpath = path::set(&path, dirs::runtime()!, "himitsu")!;
- let conn = match (unix::connect(sockpath)) {
+ let conn = match (client::connect()) {
case let s: net::socket =>
yield s;
- case let e: net::error =>
- fmt::fatal("Error connecting to Himitsu:", net::strerror(e));
+ case let e: client::error =>
+ fmt::fatal("Error connecting to Himitsu:", client::strerror(e));
};
defer io::close(conn)!;
- io::writeall(conn, memio::buffer(&buf))!;
+ match (client::query(conn, client::operation::ADD, &q, 0)) {
+ case let i: client::keyiter =>
+ let k = match (client::next(&i)) {
+ case let k: query::query =>
+ yield k;
+ case done =>
+ fmt::fatal("Error adding key: empty result");
+ case let e: client::error =>
+ fmt::fatal("Error adding key:", client::strerror(e));
+ };
+ query::unparse(os::stdout, &k)!;
- match (bufio::read_line(conn)) {
- case io::EOF =>
- fmt::fatal("Unexpected EOF from Himitsu");
- case let err: io::error =>
- fmt::fatal("Error reading from Himitsu:", io::strerror(err));
- case let line: []u8 =>
- defer free(line);
- io::writeall(os::stdout, line)!;
+ if (!(client::next(&i) is done)) {
+ fmt::fatal("Internal error: End not received");
+ };
+ case let e: client::error =>
+ fmt::fatal("Error adding key:", client::strerror(e));
};
- fmt::println()!;
};
fn decrypt(key: *ssh::sshprivkey) void = {
@@ 112,29 124,36 @@ fn decrypt(key: *ssh::sshprivkey) void = {
fmt::fatal("Error opening tty:", tty::strerror(err));
};
+ let scan = &bufio::newscanner(tty);
+ defer bufio::finish(scan);
+
const termios = tty::termios_query(tty)!;
- tty::noecho(&termios)!;
-
- fmt::errorf("Enter SSH key passphrase: ")!;
- const pass = bufio::read_line(tty)!;
- tty::termios_restore(&termios);
- fmt::errorln()!;
-
- const pass = match (pass) {
- case io::EOF =>
- fmt::fatal("Unexpected EOF");
- case let buf: []u8 =>
- yield buf;
- };
- defer {
- bytes::zero(pass);
- free(pass);
- };
- match (ssh::decrypt(key, pass)) {
- case void =>
- return;
- case let err: ssh::error =>
- fmt::fatal("Decryption failed:", ssh::strerror(err));
+ for (true) {
+ tty::noecho(&termios)!;
+
+ fmt::errorf("Enter SSH key passphrase: ")!;
+ const pass = bufio::scan_line(scan)!;
+ tty::termios_restore(&termios);
+ fmt::errorln()!;
+
+ const pass = match (pass) {
+ case io::EOF =>
+ fmt::fatal("Unexpected EOF");
+ case let buf: const str =>
+ yield strings::toutf8(buf);
+ };
+ defer {
+ bytes::zero(pass);
+ };
+
+ match (ssh::decrypt(key, pass)) {
+ case void =>
+ return;
+ case ssh::badpass =>
+ fmt::println("Wrong password")!;
+ case let err: ssh::error =>
+ fmt::fatal("Decryption failed:", ssh::strerror(err));
+ };
};
};