* fixes #19292; fixes 21122; fixes putEnv and setEnv with vcc * add a test
This commit is contained in:
parent
40b5c4c4c3
commit
0aec095b26
3 changed files with 25 additions and 15 deletions
|
|
@ -63,9 +63,13 @@ when not defined(nimscript):
|
||||||
import winlean
|
import winlean
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/widestrs
|
import std/widestrs
|
||||||
proc c_wgetenv(varname: WideCString): WideCString {.importc: "_wgetenv",
|
|
||||||
|
type wchar_t {.importc: "wchar_t", header: "<stdlib.h>".} = int16
|
||||||
|
proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv",
|
||||||
header: "<stdlib.h>".}
|
header: "<stdlib.h>".}
|
||||||
proc getEnvImpl(env: cstring): WideCString = c_wgetenv(env.newWideCString)
|
proc getEnvImpl(env: cstring): WideCString =
|
||||||
|
let r: WideCString = env.newWideCString
|
||||||
|
cast[WideCString](c_wgetenv(cast[ptr wchar_t](r)))
|
||||||
else:
|
else:
|
||||||
proc c_getenv(env: cstring): cstring {.
|
proc c_getenv(env: cstring): cstring {.
|
||||||
importc: "getenv", header: "<stdlib.h>".}
|
importc: "getenv", header: "<stdlib.h>".}
|
||||||
|
|
|
||||||
|
|
@ -33,25 +33,25 @@ else:
|
||||||
# same as winlean.setEnvironmentVariableA
|
# same as winlean.setEnvironmentVariableA
|
||||||
|
|
||||||
proc c_getenv(varname: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
|
proc c_getenv(varname: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
|
||||||
proc c_wputenv(envstring: WideCString): cint {.importc: "_wputenv", header: "<stdlib.h>".}
|
proc c_wputenv(envstring: ptr wchar_t): cint {.importc: "_wputenv", header: "<stdlib.h>".}
|
||||||
proc c_wgetenv(varname: WideCString): WideCString {.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 genviron {.importc: "_environ".}: ptr ptr char
|
var genviron {.importc: "_environ".}: ptr ptr char
|
||||||
# xxx `ptr UncheckedArray[WideCString]` did not work
|
# xxx `ptr UncheckedArray[WideCString]` did not work
|
||||||
|
|
||||||
proc wcstombs(wcstr: ptr char, mbstr: WideCString, count: csize_t): csize_t {.importc, header: "<stdlib.h>".}
|
proc wcstombs(wcstr: ptr char, mbstr: ptr wchar_t, count: csize_t): csize_t {.importc, header: "<stdlib.h>".}
|
||||||
# xxx cint vs errno_t?
|
# xxx cint vs errno_t?
|
||||||
|
|
||||||
proc setEnvImpl*(name: string, value: string, overwrite: cint): cint =
|
proc setEnvImpl*(name: string, value: string, overwrite: cint): cint =
|
||||||
const EINVAL = cint(22)
|
const EINVAL = cint(22)
|
||||||
let wideName = newWideCString(name)
|
let wideName: WideCString = newWideCString(name)
|
||||||
if overwrite == 0 and c_wgetenv(wideName) != nil:
|
if overwrite == 0 and c_wgetenv(cast[ptr wchar_t](wideName)) != nil:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if value != "":
|
if value != "":
|
||||||
let envstring = name & "=" & value
|
let envstring: WideCString = newWideCString(name & "=" & value)
|
||||||
let e = c_wputenv(newWideCString(envstring))
|
let e = c_wputenv(cast[ptr wchar_t](envstring))
|
||||||
if e != 0:
|
if e != 0:
|
||||||
errno = EINVAL
|
errno = EINVAL
|
||||||
return -1
|
return -1
|
||||||
|
|
@ -62,19 +62,19 @@ else:
|
||||||
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.
|
||||||
]#
|
]#
|
||||||
let envstring = name & "= "
|
let envstring: WideCString = newWideCString(name & "= ")
|
||||||
if c_wputenv(newWideCString(envstring)) != 0:
|
if c_wputenv(cast[ptr wchar_t](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_wgetenv(wideName)
|
var s = cast[WideCString](c_wgetenv(cast[ptr wchar_t](wideName)))
|
||||||
s[0] = Utf16Char('\0')
|
s[0] = Utf16Char('\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_wgetenv(wideName)
|
s = cast[WideCString](c_wgetenv(cast[ptr wchar_t](wideName)))
|
||||||
s[1] = Utf16Char('=')
|
s[1] = Utf16Char('=')
|
||||||
#[
|
#[
|
||||||
If genviron is null, the MBCS environment has not been initialized
|
If genviron is null, the MBCS environment has not been initialized
|
||||||
|
|
@ -88,12 +88,12 @@ else:
|
||||||
# in the current codepage. Skip updating MBCS environment in this case.
|
# in the current codepage. Skip updating MBCS environment in this case.
|
||||||
# For some reason, second `wcstombs` can find non-convertible characters
|
# For some reason, second `wcstombs` can find non-convertible characters
|
||||||
# that the first `wcstombs` cannot.
|
# that the first `wcstombs` cannot.
|
||||||
let requiredSizeS = wcstombs(nil, wideName, 0)
|
let requiredSizeS = wcstombs(nil, cast[ptr wchar_t](wideName), 0)
|
||||||
if requiredSizeS != high(csize_t):
|
if requiredSizeS != high(csize_t):
|
||||||
let requiredSize = requiredSizeS.int
|
let requiredSize = requiredSizeS.int
|
||||||
var buf = newSeq[char](requiredSize + 1)
|
var buf = newSeq[char](requiredSize + 1)
|
||||||
let buf2 = buf[0].addr
|
let buf2 = buf[0].addr
|
||||||
if wcstombs(buf2, wideName, csize_t(requiredSize + 1)) != high(csize_t):
|
if wcstombs(buf2, cast[ptr wchar_t](wideName), csize_t(requiredSize + 1)) != high(csize_t):
|
||||||
var ptrToEnv = c_getenv(cast[cstring](buf2))
|
var ptrToEnv = c_getenv(cast[cstring](buf2))
|
||||||
ptrToEnv[0] = '\0'
|
ptrToEnv[0] = '\0'
|
||||||
ptrToEnv = c_getenv(cast[cstring](buf2))
|
ptrToEnv = c_getenv(cast[cstring](buf2))
|
||||||
|
|
|
||||||
6
tests/misc/t21443.nim
Normal file
6
tests/misc/t21443.nim
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import std/envvars
|
||||||
|
|
||||||
|
# bug #19292
|
||||||
|
putEnv("NimPutEnvTest", "test")
|
||||||
|
# bug #21122
|
||||||
|
doAssert getEnv("NimPutEnvTest") == "test"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue