summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hurst <julian.hurst@digdash.com>2025-01-22 16:29:21 +0100
committerJulian Hurst <julian.hurst@digdash.com>2025-01-22 16:29:21 +0100
commite34829a3f1c6c08b825681e2aa15d738fe075d14 (patch)
tree60ad9470acd306f4a332fa646373a2ba65a897e3
parentfec320f1d3baec6169a8f9547398df16eef11888 (diff)
downloadimp-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.ha64
1 files changed, 63 insertions, 1 deletions
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);
+};