diff options
| author | Julian Hurst <julian.hurst@digdash.com> | 2025-01-22 16:29:21 +0100 |
|---|---|---|
| committer | Julian Hurst <julian.hurst@digdash.com> | 2025-01-22 16:29:21 +0100 |
| commit | e34829a3f1c6c08b825681e2aa15d738fe075d14 (patch) | |
| tree | 60ad9470acd306f4a332fa646373a2ba65a897e3 | |
| parent | fec320f1d3baec6169a8f9547398df16eef11888 (diff) | |
| download | imp-e34829a3f1c6c08b825681e2aa15d738fe075d14.tar.gz | |
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.
| -rw-r--r-- | imp.ha | 64 |
1 files changed, 63 insertions, 1 deletions
@@ -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); +}; |
