From fec320f1d3baec6169a8f9547398df16eef11888 Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Wed, 22 Jan 2025 14:51:34 +0100 Subject: Update hare version append can now throw an error -> panic if that's the case --- imp.ha | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imp.ha b/imp.ha index 632b2ac..3ac52c0 100644 --- a/imp.ha +++ b/imp.ha @@ -65,11 +65,11 @@ export fn main() void = { case 'g' => let spl = strings::split(opt.1, ","); defer free(spl); - append(accfilter.groups, spl...); + append(accfilter.groups, spl...)!; case 'm' => let spl = strings::split(opt.1, ","); defer free(spl); - append(accfilter.urls, spl...); + append(accfilter.urls, spl...)!; case 'n' => accfilter.notes = opt.1; case 'f' => @@ -80,7 +80,7 @@ export fn main() void = { for (let i = 0z; i < len(cmd.args); i += 1) { - append(accfilter.accnames, cmd.args[i]); + append(accfilter.accnames, cmd.args[i])!; }; if (verbose) { @@ -202,7 +202,7 @@ fn accs_filter(accounts: []account, accfilter: filter) []account = { for (let i = 0z; i < len(accounts); i += 1) { let acc = accounts[i]; if (isfiltered(acc, accfilter)) { - append(resaccs, acc); + append(resaccs, acc)!; }; }; return resaccs; @@ -259,7 +259,7 @@ fn parse(data: []u8) ([]account | format::ini::error) = { ... }; setfieldaccount(&acc, strings::dup(entry.1), strings::dup(entry.2)); - append(accounts, acc); + append(accounts, acc)!; case let acc: *account => setfieldaccount(acc, strings::dup(entry.1), strings::dup(entry.2)); }; -- cgit v1.2.3 From e34829a3f1c6c08b825681e2aa15d738fe075d14 Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Wed, 22 Jan 2025 16:29:21 +0100 Subject: Add -a and -c flags The a flag allows adding an account to the accounts list that will be output by imp. The c flag prints the list of requested accounts in ini format. This effectively allows a user to specify both flags in order to add an account to their existing imp accounts file or use the c flag and a filter to split their accounts file up. --- imp.ha | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/imp.ha b/imp.ha index 3ac52c0..470d568 100644 --- a/imp.ha +++ b/imp.ha @@ -5,7 +5,10 @@ use os::exec; use io; use strings; use memio; +use bufio; use format::ini; +use encoding::utf8; +use unix::tty; let verbose: bool = false; @@ -32,6 +35,8 @@ export fn main() void = { ('v', "Verbose mode"), ('l', "List the accounts"), ('p', "Display the account passwords"), + ('c', "Print ini config from parsed accounts"), + ('a', "Add an account"), ('f', "file", "The accounts file to use (IMP_FILE by default)"), ('g', "groups...", "Filters by a comma-separated list of groups"), ('m', "matches...", "Filters by a comma-separated list of matches"), @@ -53,11 +58,18 @@ export fn main() void = { let accfilter = filter {...}; + let add = false; + let printconf = false; + for (let i = 0z; i < len(cmd.opts); i += 1) { let opt = cmd.opts[i]; switch (opt.0) { case 'v' => verbose = true; + case 'a' => + add = true; + case 'c' => + printconf = true; case 'p' => displaypass = true; case 'l' => @@ -108,9 +120,25 @@ export fn main() void = { fmt::fatal(format::ini::strerror(e)); }; + if (add) { + const acc = account { + ... + }; + const n = getinput("name: ")!; + const u = getinput("user: ")!; + const p = getinput("pass: ")!; + acc.name = n; + acc.user = u; + acc.pass = p; + append(accounts, acc)!; + }; + accounts = accs_filter(accounts, accfilter); defer accounts_free(accounts); - if (list) { + + if (printconf) { + printaccs(os::stdout, accounts); + } else if (list) { for (let i = 0z; i < len(accounts); i += 1) { let acc = accounts[i]; fmt::println(acc.name)!; @@ -267,6 +295,24 @@ fn parse(data: []u8) ([]account | format::ini::error) = { return accounts; }; +// Returns the accounts as an ini string. The return value must be freed. +fn printaccs(h: io::handle, accs: []account) void = { + for (let i = 0z; i < len(accs); i += 1) { + const acc = accs[i]; + fmt::fprintf(h, "[{}]\nuser={}\npass={}\n", acc.name, acc.user, + acc.pass)!; + if (acc.notes != "") { + fmt::fprintf(h, "notes={}\n", acc.notes)!; + }; + if (acc.url != "") { + fmt::fprintf(h, "match={}\n", acc.url)!; + }; + if (i < len(accs) - 1) { + fmt::fprint(h, "\n")!; + }; + }; +}; + fn setfieldaccount(acc: *account, key: str, val: str) void = { key = strings::trim(key, ' '); defer free(key); @@ -325,3 +371,19 @@ fn decrypt(file: str) ([]u8 | os::exec::error | io::error) = { return out; }; + +// Gets user input from the tty (supports pipes) +fn getinput(text: str = "") (str | tty::error | io::error | utf8::invalid) = { + let termf = tty::open()?; + defer io::close(termf)!; + fmt::fprintf(termf, "{}", text)!; + const scanner = bufio::newscanner(termf); + defer bufio::finish(&scanner); + const line = match (bufio::scan_line(&scanner)?) { + case io::EOF => + yield ""; + case let line: const str => + yield line; + }; + return strings::dup(line); +}; -- cgit v1.2.3 From ebda2bb8ac64c57e253007568ce9791ace6e4eb0 Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Wed, 22 Jan 2025 16:51:13 +0100 Subject: Hide password output when adding an account --- imp.ha | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/imp.ha b/imp.ha index 470d568..2aef8ba 100644 --- a/imp.ha +++ b/imp.ha @@ -9,6 +9,7 @@ use bufio; use format::ini; use encoding::utf8; use unix::tty; +use errors; let verbose: bool = false; @@ -126,11 +127,17 @@ export fn main() void = { }; const n = getinput("name: ")!; const u = getinput("user: ")!; - const p = getinput("pass: ")!; - acc.name = n; - acc.user = u; - acc.pass = p; - append(accounts, acc)!; + const p = getinput("pass: ", true)!; + if (n == "" || u == "" || p == "") { + free(n); + free(u); + free(p); + } else { + acc.name = n; + acc.user = u; + acc.pass = p; + append(accounts, acc)!; + }; }; accounts = accs_filter(accounts, accfilter); @@ -372,11 +379,7 @@ fn decrypt(file: str) ([]u8 | os::exec::error | io::error) = { return out; }; -// Gets user input from the tty (supports pipes) -fn getinput(text: str = "") (str | tty::error | io::error | utf8::invalid) = { - let termf = tty::open()?; - defer io::close(termf)!; - fmt::fprintf(termf, "{}", text)!; +fn readin(termf: io::file) (str | io::error | utf8::invalid) = { const scanner = bufio::newscanner(termf); defer bufio::finish(&scanner); const line = match (bufio::scan_line(&scanner)?) { @@ -387,3 +390,21 @@ fn getinput(text: str = "") (str | tty::error | io::error | utf8::invalid) = { }; return strings::dup(line); }; + +// Gets user input from the tty (supports pipes) +fn getinput(text: str = "", noecho: bool = false) (str | tty::error | io::error + | utf8::invalid | errors::error) = { + + let termf = tty::open()?; + defer io::close(termf)!; + + fmt::fprintf(termf, "{}", text)!; + + if (noecho) { + const termios = tty::termios_query(termf)?; + tty::noecho(&termios)?; + defer tty::termios_restore(&termios); + return readin(termf)?; + }; + return readin(termf)?; +}; -- cgit v1.2.3 From d92eff17ca73ba9e61edd028de46dcbc078097c0 Mon Sep 17 00:00:00 2001 From: Julian Hurst Date: Wed, 22 Jan 2025 16:54:10 +0100 Subject: Add password confirmation --- imp.ha | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/imp.ha b/imp.ha index 2aef8ba..9c57ab8 100644 --- a/imp.ha +++ b/imp.ha @@ -128,6 +128,10 @@ export fn main() void = { const n = getinput("name: ")!; const u = getinput("user: ")!; const p = getinput("pass: ", true)!; + const cp = getinput("confirm pass: ", true)!; + if (p != cp) { + fmt::fatal("Passwords don't match"); + }; if (n == "" || u == "" || p == "") { free(n); free(u); @@ -404,6 +408,7 @@ fn getinput(text: str = "", noecho: bool = false) (str | tty::error | io::error const termios = tty::termios_query(termf)?; tty::noecho(&termios)?; defer tty::termios_restore(&termios); + defer fmt::fprintln(termf)!; return readin(termf)?; }; return readin(termf)?; -- cgit v1.2.3