/* * getenv / putenv via ESTEX ENVIRON ($46). * * ESTEX $46 subfn 1 (getenv): * in: HL = name (ASCIIZ), DE = output buffer (caller-owned) * out: CF=0 + A != 0 → variable found, value written into [DE..end-1] * CF=0 + A == 0 → variable not present (note: this is the * opposite of what DiskSyscalls.txt v1.6 docs * claim — verified empirically and against * solid-c's IO.ASM:763-766 implementation) * CF=1 → error, A = code * DE on exit points at one past the last byte written * * ESTEX $46 subfn 2 (putenv): * in: HL = "NAME=value" (NUL-terminated) * out: CF=1 / A = error code on failure * * We hand back a pointer into a private 128-byte buffer for getenv(). * Caller must copy the bytes before the next getenv() call if they * need to outlive it. */ #include #include static char env_buf[128]; char *getenv(const char *name) __naked { (void)name; __asm push ix ;; HL = name on entry; we need to also load DE = env_buf. ld de, #_env_buf ld bc, #0x0146 ; ESTEX ENVIRON; subfn: getenv rst #0x10 pop ix jr c, _getenv_err or a, a jr Z, _getenv_miss ld de, #_env_buf ret _getenv_err: call __errno_set _getenv_miss: ld de, #0 ret __endasm; } int putenv(const char *namevalue) __naked { (void)namevalue; __asm push ix ld bc, #0x0246 ; ESTEX ENVIRON; subfn: setenv rst #0x10 pop ix jr c, _putenv_err ld de, #0 ret _putenv_err: call __errno_set ld de, #-1 ret __endasm; } /* ESTEX $46 subfn 0 (sysenv): * in: HL = caller-owned buffer * out: caller's buffer is filled with one NUL-terminated "NAME=value" * per env var, then a trailing extra NUL marks the end: * "PATH=...\0SOLID=H\0\0" * return: buf on success, -1 on error (errno set). * Buffer must be large enough for the whole environment. */ char *sysenv(char *buf) __naked { (void)buf; __asm push ix push hl ; stash buffer pointer (= return value) ld bc, #0x0046 ; ESTEX ENVIRON; subfn 0 = sysenv rst #0x10 pop de ; DE = buffer pointer pop ix ret nc ; success: DE already has buf ;; CF=1 → A = ESTEX error code. call __errno_set ld de, #-1 ret __endasm; }