hautils

[hare] Set of POSIX utilities
Log | Files | Refs | README | LICENSE

env.ha (1531B)


      1 use errors;
      2 use fmt;
      3 use getopt;
      4 use main;
      5 use os::exec;
      6 use os;
      7 use strings;
      8 
      9 export fn utilmain() (main::error | void) = {
     10 	const help: []getopt::help = [
     11 		"set the environment for command invocation",
     12 		('i', "ignore the parent environment"),
     13 		"[command [arguments...]]",
     14 	];
     15 	const cmd = getopt::parse(os::args, help...);
     16 	defer getopt::finish(&cmd);
     17 
     18 	let clear = false;
     19 	for (let i = 0z; i < len(cmd.opts); i += 1) {
     20 		switch (cmd.opts[i].0) {
     21 		case 'i' =>
     22 			clear = true;
     23 		case => void;
     24 		};
     25 	};
     26 
     27 	let environ: []str = cmd.args, args: []str = [];
     28 	for (let i = 0z; i < len(cmd.args); i += 1) {
     29 		if (!strings::contains(cmd.args[i], '=')) {
     30 			environ = cmd.args[..i];
     31 			args = cmd.args[i..];
     32 			break;
     33 		};
     34 	};
     35 
     36 	if (len(args) == 0) {
     37 		return printenv(environ, clear);
     38 	};
     39 
     40 	let cmd = match (exec::cmd(args[0], args[1..]...)) {
     41 	case let cmd: exec::command =>
     42 		yield cmd;
     43 	case exec::nocmd =>
     44 		fmt::errorfln("{}: command not found", args[0])!;
     45 		os::exit(127);
     46 	case let err: exec::error =>
     47 		return err;
     48 	};
     49 	if (clear) {
     50 		exec::clearenv(&cmd);
     51 	};
     52 	for (let i = 0z; i < len(environ); i += 1) {
     53 		let env = strings::cut(environ[i], "=");
     54 		match (exec::setenv(&cmd, env.0, env.1)) {
     55 		case errors::invalid =>
     56 			fmt::fatalf("Error: Invalid key '{}'", env.0);
     57 		case void => void;
     58 		};
     59 	};
     60 	exec::exec(&cmd);
     61 };
     62 
     63 fn printenv(environ: []str, clear: bool) (void | main::error) = {
     64 	if (!clear) {
     65 		printenv(os::getenvs(), true)?;
     66 	};
     67 	for (let i = 0z; i < len(environ); i += 1) {
     68 		fmt::println(environ[i])?;
     69 	};
     70 };