# # # Nim's Runtime Library # (c) Copyright 2022 Nim contributors # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## The `std/envvars` module implements environment variable handling. import std/oserrors type ReadEnvEffect* = object of ReadIOEffect ## Effect that denotes a read ## from an environment variable. WriteEnvEffect* = object of WriteIOEffect ## Effect that denotes a write ## to an environment variable. when not defined(nimscript): when defined(nodejs): proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} = var ret = default.cstring let key2 = key.cstring {.emit: "const value = process.env[`key2`];".} {.emit: "if (value !== undefined) { `ret` = value };".} result = $ret proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} = var key2 = key.cstring var ret: bool {.emit: "`ret` = `key2` in process.env;".} result = ret proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} = var key2 = key.cstring var val2 = val.cstring {.emit: "process.env[`key2`] = `val2`;".} proc delEnv*(key: string) {.tags: [WriteEnvEffect].} = var key2 = key.cstring {.emit: "delete process.env[`key2`];".} iterator envPairsImpl(): tuple[key, value: string] {.tags: [ReadEnvEffect].} = var num: int var keys: RootObj {.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".} for i in 0..".} from std/private/win_setenv import setEnvImpl import winlean when defined(nimPreviewSlimSystem): import std/widestrs type wchar_t {.importc: "wchar_t", header: "".} = int16 proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv", header: "".} proc getEnvImpl(env: cstring): WideCString = let r: WideCString = env.newWideCString cast[WideCString](c_wgetenv(cast[ptr wchar_t](r))) else: proc c_getenv(env: cstring): cstring {. importc: "getenv", header: "".} proc c_setenv(envname: cstring, envval: cstring, overwrite: cint): cint {.importc: "setenv", header: "".} proc c_unsetenv(env: cstring): cint {.importc: "unsetenv", header: "".} proc getEnvImpl(env: cstring): cstring = c_getenv(env) proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} = ## Returns the value of the `environment variable`:idx: named `key`. ## ## If the variable does not exist, `""` is returned. To distinguish ## whether a variable exists or it's value is just `""`, call ## `existsEnv(key) proc`_. ## ## See also: ## * `existsEnv proc`_ ## * `putEnv proc`_ ## * `delEnv proc`_ ## * `envPairs iterator`_ runnableExamples: assert getEnv("unknownEnv") == "" assert getEnv("unknownEnv", "doesn't exist") == "doesn't exist" let env = getEnvImpl(key) if env == nil: result = default else: result = $env proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} = ## Checks whether the environment variable named `key` exists. ## Returns true if it exists, false otherwise. ## ## See also: ## * `getEnv proc`_ ## * `putEnv proc`_ ## * `delEnv proc`_ ## * `envPairs iterator`_ runnableExamples: assert not existsEnv("unknownEnv") result = getEnvImpl(key) != nil proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} = ## Sets the value of the `environment variable`:idx: named `key` to `val`. ## If an error occurs, `OSError` is raised. ## ## See also: ## * `getEnv proc`_ ## * `existsEnv proc`_ ## * `delEnv proc`_ ## * `envPairs iterator`_ when defined(windows): if key.len == 0 or '=' in key: raise newException(OSError, "invalid key, got: " & $(key, val)) if setEnvImpl(key, val, 1'i32) != 0'i32: raiseOSError(osLastError(), $(key, val)) else: if c_setenv(key, val, 1'i32) != 0'i32: raiseOSError(osLastError(), $(key, val)) proc delEnv*(key: string) {.tags: [WriteEnvEffect].} = ## Deletes the `environment variable`:idx: named `key`. ## If an error occurs, `OSError` is raised. ## ## See also:ven ## * `getEnv proc`_