Signed-off-by: Willow Barraco <contact@willowbarraco.fr>
---
cmd/hiq/main.ha | 68 +++++++++++++++++++++++++++++++++++++++++++++----
docs/hiq.1.scd | 7 ++++-
2 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/cmd/hiq/main.ha b/cmd/hiq/main.ha
index 6386423..6d9fa59 100644
--- a/cmd/hiq/main.ha
+++ b/cmd/hiq/main.ha
@@ -30,6 +30,7 @@ export fn main() void = {
('d', "decrypt private keys"),
('D', "delete matching keys"),
('F', "field", "select a field for output"),
+ ('M', "field", "multi-line field data"),
('l', "soft lock the keyring"),
('L', "hard lock the keyring"),
('Q', "terminate the daemon (if started with -D)"),
@@ -42,6 +43,7 @@ export fn main() void = {
let op = client::operation::QUERY;
let flags: client::flags = 0;
let field: (str | void) = void;
+ let multiline: (str | void) = void;
let one = false;
let lock = lockop::NONE;
@@ -57,6 +59,8 @@ export fn main() void = {
op = client::operation::DEL;
case 'F' =>
field = opt.1;
+ case 'M' =>
+ multiline = opt.1;
case 'l' =>
lock = lockop::SOFT;
case 'L' =>
@@ -97,7 +101,43 @@ export fn main() void = {
};
};
- if (op == client::operation::ADD && len(cmd.args) == 0) {
+ if (op == client::operation::ADD && len(cmd.args) != 0 && !(multiline is void)) {
+ if (tty::isatty(os::stderr_file) && tty::isatty(os::stdin_file)) {
+ fmt::errorln("Enter the content of the value then press ^d:")!;
+ };
+ const multiline = multiline as str;
+
+ let scan = bufio::newscanner(os::stdin);
+ defer bufio::finish(&scan);
+
+ let lines: []str = [];
+ defer strings::freeall(lines);
+ for (let line => bufio::scan_line(&scan)) {
+ let line = match (line) {
+ case let line: const str =>
+ yield line;
+ case let e: io::error =>
+ fmt::fatal("Error reading data", io::strerror(e));
+ case utf8::invalid =>
+ fmt::fatal("Error: Query is not valid UTF-8");
+ };
+ append(lines, strings::dup(line));
+ };
+ const secret = strings::join("\0", lines...);
+ defer free(secret);
+
+ const item = strings::concat(multiline, "=", secret);
+ append(cmd.args, item);
+
+ const query = match (query::parse_items(cmd.args)) {
+ case let q: query::query =>
+ yield q;
+ case let err: query::error =>
+ fmt::fatal(query::strerror(err));
+ };
+ defer query::finish(&query);
+ send(conn, op, &query, flags, field, multiline, one);
+ } else if (op == client::operation::ADD && len(cmd.args) == 0) {
if (tty::isatty(os::stderr_file) && tty::isatty(os::stdin_file)) {
fmt::errorln("Enter new keys, one per line, then press ^d:")!;
};
@@ -125,7 +165,7 @@ export fn main() void = {
strings::dup(line));
};
defer query::finish(&query);
- send(conn, client::operation::ADD, &query, flags, field, one);
+ send(conn, client::operation::ADD, &query, flags, field, multiline, one);
};
} else {
const query = match (query::parse_items(cmd.args)) {
@@ -135,7 +175,7 @@ export fn main() void = {
fmt::fatal(query::strerror(err));
};
defer query::finish(&query);
- send(conn, op, &query, flags, field, one);
+ send(conn, op, &query, flags, field, multiline, one);
};
};
@@ -145,6 +185,7 @@ fn send(
query: *query::query,
flags: client::flags,
field: (str | void),
+ multiline: (str | void),
one: bool,
) void = {
const keys = match (client::query(conn, op, query, flags)) {
@@ -168,6 +209,7 @@ fn send(
fmt::fatal("Error executing query:", client::strerror(err));
case done => break;
};
+
match (field) {
case let field: str =>
for (let item &.. key.items) {
@@ -175,9 +217,25 @@ fn send(
fmt::fprintln(&buf, item.value)!;
};
};
- case void =>
- query::unparse(&buf, &key)!;
+ continue;
+ case void => yield;
};
+
+ match (multiline) {
+ case let multiline: str =>
+ for (let item &.. key.items) {
+ if (item.key == multiline) {
+ let lines = strings::split(item.value, "\0");
+ for (const line .. lines) {
+ fmt::fprintln(&buf, line)!;
+ };
+ };
+ };
+ continue;
+ case void => yield;
+ };
+
+ query::unparse(&buf, &key)!;
};
fmt::print(memio::string(&buf)!)!;
diff --git a/docs/hiq.1.scd b/docs/hiq.1.scd
index 221ae35..ab54661 100644
--- a/docs/hiq.1.scd
+++ b/docs/hiq.1.scd
@@ -6,7 +6,7 @@ hiq - query the *himitsu*(7) key store
# SYNOPSIS
-*hiq* [-h1adDlLQs] [-F _field_] _query_...
+*hiq* [-h1adDlLQs] [-F _field_] [-M _field_] _query_...
# DESCRIPTION
@@ -47,6 +47,11 @@ have already been quoted properly.
Select a specific field to print. By default, the full key is printed in
the format described by *KEY FORMAT* in *himitsu*(7).
+*-M* _field_
+ Select a specific field to use as a multi-line value. It use the stdin
+ while adding, and the stdout when querying. The data is encoded using
+ NULL char as line return.
+
*-l*
Soft locks the keyring by removing the secret key from memory. Keeps
non-private data of entries in memory.
--
2.46.0