hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

environ+libc.ha (3069B)


      1 // License: MPL-2.0
      2 // (c) 2022 Alexey Yerin <yyp@disroot.org>
      3 use bytes;
      4 use rt;
      5 use strings;
      6 use types::c;
      7 
      8 // The command line arguments provided to the program. By convention, the first
      9 // member is usually the name of the program.
     10 export let args: []str = [];
     11 
     12 // Statically allocate arg strings if there are few enough arguments, saves a
     13 // syscall if we don't need it.
     14 let args_static: [32]str = [""...];
     15 
     16 @init fn init_environ() void = {
     17 	rt::start_linux();
     18 	if (rt::argc < len(args_static)) {
     19 		args = args_static[..rt::argc];
     20 		for (let i = 0z; i < rt::argc; i += 1) {
     21 			args[i] = c::tostr(rt::argv[i]: *const c::char)!;
     22 		};
     23 	} else {
     24 		args = alloc([], rt::argc);
     25 		for (let i = 0z; i < rt::argc; i += 1) {
     26 			append(args, c::tostr(rt::argv[i]: *const c::char)!);
     27 		};
     28 	};
     29 
     30 };
     31 
     32 @fini fn fini_environ() void = {
     33 	if (rt::argc >= len(args_static)) {
     34 		free(args);
     35 	};
     36 	free(envp);
     37 };
     38 
     39 // Looks up an environment variable and returns its value, or void if unset.
     40 export fn getenv(name: const str) (str | void) = {
     41 	const name_b = strings::toutf8(name);
     42 	for (let i = 0z; rt::envp[i] != null; i += 1) {
     43 		const item = rt::envp[i]: *[*]u8;
     44 		const ln = c::strlen(item: *c::char);
     45 		const eq: size = match (bytes::index(item[..ln], '=')) {
     46 		case void =>
     47 			abort("Environment violates System-V invariants");
     48 		case let i: size =>
     49 			yield i;
     50 		};
     51 		if (bytes::equal(name_b, item[..eq])) {
     52 			const ln = c::strlen(item: *const c::char);
     53 			return strings::fromutf8(item[eq+1..ln])!;
     54 		};
     55 	};
     56 };
     57 
     58 // Looks up an environment variable and returns its value, or a default value if
     59 // unset.
     60 export fn tryenv(name: const str, default: str) str = match (getenv(name)) {
     61 case let s: str =>
     62 	yield s;
     63 case void =>
     64 	yield default;
     65 };
     66 
     67 let envp: []str = [];
     68 
     69 // Returns a slice of the environment strings in the form KEY=VALUE.
     70 export fn getenvs() []str = {
     71 	if (len(envp) != 0) {
     72 		return envp;
     73 	};
     74 	for (let i = 0z; rt::envp[i] != null; i += 1) {
     75 		append(envp, c::tostr(rt::envp[i]: *const c::char)!);
     76 	};
     77 	return envp;
     78 };
     79 
     80 let uts: rt::utsname = rt::utsname { ... };
     81 let uts_valid: bool = false;
     82 
     83 // Returns the host kernel name
     84 export fn sysname() const str = {
     85 	if (!uts_valid) {
     86 		rt::uname(&uts) as void;
     87 		uts_valid = true;
     88 	};
     89 	return c::tostr(&uts.sysname: *const c::char)!;
     90 };
     91 
     92 // Returns the host system hostname
     93 export fn hostname() const str = {
     94 	if (!uts_valid) {
     95 		rt::uname(&uts) as void;
     96 		uts_valid = true;
     97 	};
     98 	return c::tostr(&uts.nodename: *const c::char)!;
     99 };
    100 
    101 // Returns the host kernel version
    102 export fn release() const str = {
    103 	if (!uts_valid) {
    104 		rt::uname(&uts) as void;
    105 		uts_valid = true;
    106 	};
    107 	return c::tostr(&uts.release: *const c::char)!;
    108 };
    109 
    110 // Returns the host operating system version
    111 export fn version() const str = {
    112 	if (!uts_valid) {
    113 		rt::uname(&uts) as void;
    114 		uts_valid = true;
    115 	};
    116 	return c::tostr(&uts.version: *const c::char)!;
    117 };
    118 
    119 // Returns the host CPU architecture
    120 export fn machine() const str = {
    121 	if (!uts_valid) {
    122 		rt::uname(&uts) as void;
    123 		uts_valid = true;
    124 	};
    125 	return c::tostr(&uts.machine: *const c::char)!;
    126 };