Sam Nystrom: 1 hiq: use himitsu::client to run queries 1 files changed, 66 insertions(+), 87 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~sircmpwn/himitsu-devel/patches/41114/mbox | git am -3Learn more about email & git
Replace manual usage of the himitsud Unix socket with calls to the himitsu::client library. --- Since v1: - free the key items and query - improve a few error messages cmd/hiq/main.ha | 153 +++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 87 deletions(-) diff --git a/cmd/hiq/main.ha b/cmd/hiq/main.ha index ad0460e..7960ec6 100644 --- a/cmd/hiq/main.ha +++ b/cmd/hiq/main.ha @@ -15,32 +15,6 @@ use strings; use strio; use unix::tty; -type flag = enum uint { - ONE = 1 << 0, - DECRYPT = 1 << 1, -}; - -fn write_item( - out: io::handle, - items: str, - field: str -) (void | io::error) = { - if (field == "") { - fmt::fprintln(out, items)!; - return; - }; - let items = shlex::split(items)!; - defer strings::freeall(items); - let query = query::parse_items(items)!; - for (let i = 0z; i < len(query.items); i += 1) { - let item = query.items[i]; - if (item.key != field) { - continue; - }; - fmt::fprintln(out, item.value)?; - }; -}; - export fn main() void = { let usage: [_]getopt::help = [ "secure key store client", @@ -56,15 +30,17 @@ export fn main() void = { defer getopt::finish(&cmd); let op = client::operation::QUERY; - let flags: flag = 0, field = ""; + let flags: client::flags = 0; + let field: (str | void) = void; + let one = false; for (let i = 0z; i < len(cmd.opts); i += 1) { switch (cmd.opts[i].0) { case '1' => - flags |= flag::ONE; + one = true; case 'a' => op = client::operation::ADD; case 'd' => - flags |= flag::DECRYPT; + flags |= client::flags::DECRYPT; case 'D' => op = client::operation::DEL; case 'F' => @@ -74,16 +50,20 @@ export fn main() void = { }; }; - let buf = path::init(); - // TODO: Bubble up dirs::runtime errors - const sockpath = path::set(&buf, dirs::runtime()!, "himitsu")!; - let conn = match (unix::connect(sockpath)) { + let conn = match (client::connect()) { case let s: net::socket => yield s; - case errors::noentry => - fmt::fatal("error: himitsud connection failed (is it running?)"); + case let e: client::hierror => + fmt::fatal(e); + case let e: io::error => + fmt::fatal("error:", io::strerror(e)); case let e: net::error => - fmt::fatal("error:", net::strerror(e)); + match (e) { + case errors::noentry => + fmt::fatal("error: himitsud connection failed (is it running?)"); + case => + fmt::fatal("error:", net::strerror(e)); + }; }; defer io::close(conn)!; @@ -97,77 +77,76 @@ export fn main() void = { case let line: []u8 => // NB. Can't defer free(line), causes a // use-after-free in fmt::fatal - const line = strings::fromutf8(line)!; - const query = match (shlex::split(line)) { - case let q: []str => + const query = bufio::fixed(line, io::mode::READ); + const query = match (query::parse(&query)) { + case let q: query::query => yield q; - case => - fmt::fatal("Invalid query:", line); + case query::invalid => + fmt::fatal("Invalid query:", strings::fromutf8(line)!); + case let err: io::error => + abort(); // reading from a fixed buffer shouldn't fail }; - defer strings::freeall(query); + defer query::finish(&query); free(line); - - send(conn, client::operation::ADD, flags, field, query); + send(conn, client::operation::ADD, &query, flags, field, one); }; }; } else { - let query = alloc(cmd.args...); - defer free(query); - if (flags & flag::DECRYPT != 0) { - insert(query[0], "-d"); + const query = match (query::parse_items(cmd.args)) { + case let q: query::query => + yield q; + case query::invalid => + fmt::fatal("Invalid query"); }; - send(conn, op, flags, field, query); + defer query::finish(&query); + send(conn, op, &query, flags, field, one); }; }; fn send( - conn: io::file, + conn: net::socket, op: client::operation, - flags: flag, - field: str, - query: []str, + query: *query::query, + flags: client::flags, + field: (str | void), + one: bool, ) void = { - fmt::fprint(conn, switch (op) { - case client::operation::QUERY => - yield "query"; - case client::operation::ADD => - yield "add"; - case client::operation::DEL => - yield "del"; - case client::operation::QUIT => - yield "quit"; - })!; - for (let i = 0z; i < len(query); i += 1) { - fmt::fprint(conn, " ")!; - shlex::quote(conn, query[i])!; + const keys = match (client::query(conn, op, query, flags)) { + case let k: client::keyiter => + yield k; + case let err: client::error => + fmt::fatal("Error executing query:", client::strerror(err)); }; - fmt::fprintln(conn)!; let buf = strio::dynamic(); defer io::close(&buf)!; - for (let n = 0; true; n += 1) match (bufio::scanline(conn)!) { - case io::EOF => break; - case let line: []u8 => - // NB. Can't defer free(line), causes a use-after-free in - // fmt::fatal - let resp = strings::fromutf8(line)!; - let resp = strings::cut(resp, " "); - switch (resp.0) { - case "key" => - if (flags & flag::ONE != 0 && n > 0) { - fmt::fatal("error: Ambiguous match"); + for (let i = 0; true; i += 1) { + let key = match (client::next(&keys)) { + case let k: const str => + if (one && i > 0) { + fmt::fatal("Error: ambiguous match"); }; - write_item(&buf, resp.1, field)!; - case "error" => - fmt::fatal("error:", resp.1); - case "end" => - free(line); - break; - case => - break; + yield k; + case let err: client::error => + fmt::fatal("Error executing query:", client::strerror(err)); + case void => break; + }; + match (field) { + case let field: str => + const items = shlex::split(key)!; + defer strings::freeall(items); + const query = query::parse_items(items)!; + defer query::finish(&query); + for (let i = 0z; i < len(query.items); i += 1) { + let item = query.items[i]; + if (item.key == field) { + fmt::fprintln(&buf, item.value)!; + }; + }; + case void => + fmt::fprintln(&buf, key)!; }; - free(line); }; fmt::print(strio::string(&buf))!; -- 2.40.1
Applied to master. Thanks!