* Update osenv.nim * Update win_setenv.nim * Update lib/pure/includes/osenv.nim * Update lib/pure/includes/osenv.nim * fixing cstring Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
parent
5ec8b60942
commit
c7d5b8c83d
2 changed files with 24 additions and 22 deletions
|
|
@ -45,7 +45,7 @@ when not defined(nimscript):
|
||||||
proc c_getenv(env: cstring): cstring {.
|
proc c_getenv(env: cstring): cstring {.
|
||||||
importc: "getenv", header: "<stdlib.h>".}
|
importc: "getenv", header: "<stdlib.h>".}
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
proc c_putenv_s(envname: cstring, envval: cstring): cint {.importc: "_putenv_s", header: "<stdlib.h>".}
|
proc c_putenv(envstring: cstring): cint {.importc: "_putenv", header: "<stdlib.h>".}
|
||||||
from std/private/win_setenv import setEnvImpl
|
from std/private/win_setenv import setEnvImpl
|
||||||
else:
|
else:
|
||||||
proc c_setenv(envname: cstring, envval: cstring, overwrite: cint): cint {.importc: "setenv", header: "<stdlib.h>".}
|
proc c_setenv(envname: cstring, envval: cstring, overwrite: cint): cint {.importc: "setenv", header: "<stdlib.h>".}
|
||||||
|
|
@ -121,7 +121,8 @@ when not defined(nimscript):
|
||||||
]#
|
]#
|
||||||
if key.len == 0 or '=' in key:
|
if key.len == 0 or '=' in key:
|
||||||
raise newException(OSError, "invalid key, got: " & key)
|
raise newException(OSError, "invalid key, got: " & key)
|
||||||
if c_putenv_s(key, "") != 0'i32: bail
|
let envToDel = key & "="
|
||||||
|
if c_putenv(cstring envToDel) != 0'i32: bail
|
||||||
else:
|
else:
|
||||||
if c_unsetenv(key) != 0'i32: bail
|
if c_unsetenv(key) != 0'i32: bail
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,44 +30,45 @@ else:
|
||||||
# same as winlean.setEnvironmentVariableA
|
# same as winlean.setEnvironmentVariableA
|
||||||
|
|
||||||
proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
|
proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
|
||||||
proc c_putenv_s(envname: cstring, envval: cstring): cint {.importc: "_putenv_s", header: "<stdlib.h>".}
|
proc c_putenv(envstring: cstring): cint {.importc: "_putenv", header: "<stdlib.h>".}
|
||||||
proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv", header: "<stdlib.h>".}
|
proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv", header: "<stdlib.h>".}
|
||||||
|
|
||||||
var errno {.importc, header: "<errno.h>".}: cint
|
var errno {.importc, header: "<errno.h>".}: cint
|
||||||
var gWenviron {.importc: "_wenviron".}: ptr ptr wchar_t
|
var gWenviron {.importc: "_wenviron".}: ptr ptr wchar_t
|
||||||
# xxx `ptr UncheckedArray[WideCString]` did not work
|
# xxx `ptr UncheckedArray[WideCString]` did not work
|
||||||
|
|
||||||
proc mbstowcs_s(pReturnValue: ptr csize_t, wcstr: ptr wchar_t, sizeInWords: csize_t, mbstr: cstring, count: csize_t): cint {.importc: "mbstowcs_s", header: "<stdlib.h>".}
|
proc mbstowcs(wcstr: ptr wchar_t, mbstr: cstring, count: csize_t): csize_t {.importc: "mbstowcs", header: "<stdlib.h>".}
|
||||||
# xxx cint vs errno_t?
|
# xxx cint vs errno_t?
|
||||||
|
|
||||||
proc setEnvImpl*(name: cstring, value: cstring, overwrite: cint): cint =
|
proc setEnvImpl*(name: string, value: string, overwrite: cint): cint =
|
||||||
const EINVAL = cint(22)
|
const EINVAL = cint(22)
|
||||||
const MAX_ENV = 32767
|
if overwrite == 0 and c_getenv(cstring(name)) != nil: return 0
|
||||||
# xxx get it from: `var MAX_ENV {.importc: "_MAX_ENV", header:"<stdlib.h>".}: cint`
|
if value != "":
|
||||||
if overwrite == 0 and c_getenv(name) != nil: return 0
|
let envstring = name & "=" & value
|
||||||
if value[0] != '\0':
|
let e = c_putenv(cstring(envstring))
|
||||||
let e = c_putenv_s(name, value)
|
|
||||||
if e != 0:
|
if e != 0:
|
||||||
errno = e
|
errno = EINVAL
|
||||||
return -1
|
return -1
|
||||||
return 0
|
return 0
|
||||||
#[
|
#[
|
||||||
We are trying to set the value to an empty string, but `_putenv_s` deletes
|
We are trying to set the value to an empty string, but `_putenv` deletes
|
||||||
entries if the value is an empty string, and just calling
|
entries if the value is an empty string, and just calling
|
||||||
SetEnvironmentVariableA doesn't update `_environ`,
|
SetEnvironmentVariableA doesn't update `_environ`,
|
||||||
so we have to do these terrible things.
|
so we have to do these terrible things.
|
||||||
]#
|
]#
|
||||||
if c_putenv_s(name, " ") != 0:
|
let envstring = name & "= "
|
||||||
|
if c_putenv(cstring(envstring)) != 0:
|
||||||
errno = EINVAL
|
errno = EINVAL
|
||||||
return -1
|
return -1
|
||||||
# Here lies the documentation we blatently ignore to make this work.
|
# Here lies the documentation we blatently ignore to make this work.
|
||||||
var s = c_getenv(name)
|
var s = c_getenv(cstring(name))
|
||||||
s[0] = '\0'
|
s[0] = '\0'
|
||||||
#[
|
#[
|
||||||
This would result in a double null termination, which normally signifies the
|
This would result in a double null termination, which normally signifies the
|
||||||
end of the environment variable list, so we stick a completely empty
|
end of the environment variable list, so we stick a completely empty
|
||||||
environment variable into the list instead.
|
environment variable into the list instead.
|
||||||
]#
|
]#
|
||||||
|
s = c_getenv(cstring(name))
|
||||||
s[1] = '='
|
s[1] = '='
|
||||||
#[
|
#[
|
||||||
If gWenviron is null, the wide environment has not been initialized
|
If gWenviron is null, the wide environment has not been initialized
|
||||||
|
|
@ -77,19 +78,19 @@ else:
|
||||||
]#
|
]#
|
||||||
if gWenviron != nil:
|
if gWenviron != nil:
|
||||||
# var buf: array[MAX_ENV + 1, WideCString]
|
# var buf: array[MAX_ENV + 1, WideCString]
|
||||||
var buf: array[MAX_ENV + 1, Utf16Char]
|
let requiredSize = mbstowcs(nil, cstring(name), 0).int
|
||||||
|
var buf = newSeq[Utf16Char](requiredSize + 1)
|
||||||
let buf2 = cast[ptr wchar_t](buf[0].addr)
|
let buf2 = cast[ptr wchar_t](buf[0].addr)
|
||||||
var len: csize_t
|
if mbstowcs(buf2, cstring(name), csize_t(requiredSize + 1)) == csize_t(high(uint)):
|
||||||
if mbstowcs_s(len.addr, buf2, buf.len.csize_t, name, MAX_ENV) != 0:
|
|
||||||
errno = EINVAL
|
errno = EINVAL
|
||||||
return -1
|
return -1
|
||||||
let ptrToEnv = cast[WideCString](c_wgetenv(buf2))
|
var ptrToEnv = cast[WideCString](c_wgetenv(buf2))
|
||||||
ptrToEnv[0] = '\0'.Utf16Char
|
ptrToEnv[0] = '\0'.Utf16Char
|
||||||
let ptrToEnv2 = cast[WideCString](c_wgetenv(buf2))
|
ptrToEnv = cast[WideCString](c_wgetenv(buf2))
|
||||||
ptrToEnv2[1] = '='.Utf16Char
|
ptrToEnv[1] = '='.Utf16Char
|
||||||
|
|
||||||
# And now, we have to update the outer environment to have a proper empty value.
|
# And now, we have to update the outer environment to have a proper empty value.
|
||||||
if setEnvironmentVariableA(name, value) == 0:
|
if setEnvironmentVariableA(cstring(name), cstring(value)) == 0:
|
||||||
errno = EINVAL
|
errno = EINVAL
|
||||||
return -1
|
return -1
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue