code wiki / (root) / nx_env.nx

nx_env.nx source

↩ module page · 116 lines · 4170 B

1// nx_env.nx -- environment variable lookup over the System V envp. 2// 3// At program entry the kernel hands us argc + argv + envp. envp is 4// a NULL-terminated array of "KEY=VALUE" strings. This module 5// searches envp for a given key and returns the value pointer (NUL- 6// terminated) or NULL. 7// 8// Callers (toolchain): NX_NXC_PATH, NX_DEBUG, HOME, PATH, etc. 9// 10// We don't mutate envp -- this is a pure read interface. Setenv 11// would require redirecting stdlib calls, which the off-C runtime 12// doesn't have anyway. 13 14// nx_safety_envelope: 15// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 16// sil_target: SIL1 17// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 18// verdict: NOT_YET_EVALUATED 19 20import "syscalls.nx" 21import "runtime.nx" 22 23// strlen canonical in runtime.nx. 24 25// Compare a NUL-terminated `key` against the prefix of `entry` up to 26// the '=' separator. Returns 1 on match, 0 otherwise. 27func nx_env_key_match(entry: *u8, key: *u8) -> i64 { 28 var i: i64 = 0 29 while key[i] != 0 { 30 if entry[i] != key[i] { return 0 } 31 i = i + 1 32 } 33 if entry[i] != 0x3D { return 0 } 34 return 1 35} 36 37// Look up `key` in the NULL-terminated `envp`. Returns a pointer 38// to the value (the byte AFTER '=') or NULL if not found. 39// 40// `envp` is the standard System V envp: an array of *u8 pointers 41// terminated by NULL. 42func nx_env_get(envp: *i64, key: *u8) -> *u8 { 43 var i: i64 = 0 44 while envp[i] != 0 { 45 let entry: *u8 = (envp[i]) as *u8 46 if nx_env_key_match(entry, key) == 1 { 47 let key_len: i64 = strlen(key) 48 return (((entry as i64) + key_len + 1) as *u8) 49 } 50 i = i + 1 51 } 52 return 0 as *u8 53} 54 55// Count entries in envp. 56func nx_env_count(envp: *i64) -> i64 { 57 var i: i64 = 0 58 while envp[i] != 0 { i = i + 1 } 59 return i 60} 61 62// ---- self-test --------------------------------------------------- 63 64func main() -> i64 { 65 // Build a mock envp: ["HOME=/h", "PATH=/u/b", "NX_OPT=1", NULL] 66 let entries_raw: *u8 = sys_mmap(64) 67 let entries: *i64 = entries_raw as *i64 68 69 let e0: *u8 = sys_mmap(16) 70 e0[0] = 0x48; e0[1] = 0x4F; e0[2] = 0x4D; e0[3] = 0x45; e0[4] = 0x3D 71 e0[5] = 0x2F; e0[6] = 0x68; e0[7] = 0 72 let e1: *u8 = sys_mmap(16) 73 e1[0] = 0x50; e1[1] = 0x41; e1[2] = 0x54; e1[3] = 0x48; e1[4] = 0x3D 74 e1[5] = 0x2F; e1[6] = 0x75; e1[7] = 0x2F; e1[8] = 0x62; e1[9] = 0 75 let e2: *u8 = sys_mmap(16) 76 e2[0] = 0x4E; e2[1] = 0x58; e2[2] = 0x5F; e2[3] = 0x4F; e2[4] = 0x50; e2[5] = 0x54 77 e2[6] = 0x3D; e2[7] = 0x31; e2[8] = 0 78 entries[0] = e0 as i64 79 entries[1] = e1 as i64 80 entries[2] = e2 as i64 81 entries[3] = 0 82 83 if nx_env_count(entries) != 3 { return __syscall(93, 1, 0, 0, 0, 0, 0) } 84 85 // Lookup HOME 86 let key1: *u8 = sys_mmap(8) 87 key1[0] = 0x48; key1[1] = 0x4F; key1[2] = 0x4D; key1[3] = 0x45; key1[4] = 0 88 let v1: *u8 = nx_env_get(entries, key1) 89 if v1 == (0 as *u8) { return __syscall(93, 2, 0, 0, 0, 0, 0) } 90 if v1[0] != 0x2F { return __syscall(93, 3, 0, 0, 0, 0, 0) } 91 if v1[1] != 0x68 { return __syscall(93, 4, 0, 0, 0, 0, 0) } 92 if v1[2] != 0 { return __syscall(93, 5, 0, 0, 0, 0, 0) } 93 94 // Lookup NX_OPT 95 let key2: *u8 = sys_mmap(8) 96 key2[0] = 0x4E; key2[1] = 0x58; key2[2] = 0x5F; key2[3] = 0x4F 97 key2[4] = 0x50; key2[5] = 0x54; key2[6] = 0 98 let v2: *u8 = nx_env_get(entries, key2) 99 if v2 == (0 as *u8) { return __syscall(93, 6, 0, 0, 0, 0, 0) } 100 if v2[0] != 0x31 { return __syscall(93, 7, 0, 0, 0, 0, 0) } 101 if v2[1] != 0 { return __syscall(93, 8, 0, 0, 0, 0, 0) } 102 103 // Lookup non-existent key 104 let key3: *u8 = sys_mmap(8) 105 key3[0] = 0x42; key3[1] = 0x41; key3[2] = 0x44; key3[3] = 0 106 let v3: *u8 = nx_env_get(entries, key3) 107 if v3 != (0 as *u8) { return __syscall(93, 9, 0, 0, 0, 0, 0) } 108 109 // Key is a prefix of an entry but no '=' boundary (HOM != HOME) 110 let key4: *u8 = sys_mmap(8) 111 key4[0] = 0x48; key4[1] = 0x4F; key4[2] = 0x4D; key4[3] = 0 112 let v4: *u8 = nx_env_get(entries, key4) 113 if v4 != (0 as *u8) { return __syscall(93, 10, 0, 0, 0, 0, 0) } 114 115 return 0 116}