summaryrefslogtreecommitdiff
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-01-24 11:53:44 +0100
committerGitHub <noreply@github.com>2020-01-24 11:53:44 +0100
commit161e7b36b1ea871a1352ccfc1d4f4c1eda76830f (patch)
tree0f44995e5fadbd3cedb76688e71a06693dcd7270 /Modules/posixmodule.c
parent2d5097663d7f80921fb07cdcd26c9d59cf71f1a2 (diff)
downloadcpython-git-161e7b36b1ea871a1352ccfc1d4f4c1eda76830f.tar.gz
bpo-39413: Implement os.unsetenv() on Windows (GH-18163)
The os.unsetenv() function is now also available on Windows.
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c107
1 files changed, 69 insertions, 38 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 6a687529df..3a8e6aacb2 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -10083,23 +10083,9 @@ posix_putenv_dict_setitem(PyObject *name, PyObject *value)
#ifdef MS_WINDOWS
-/*[clinic input]
-os.putenv
-
- name: unicode
- value: unicode
- /
-
-Change or add an environment variable.
-[clinic start generated code]*/
-
-static PyObject *
-os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
-/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
+static PyObject*
+win32_putenv(PyObject *name, PyObject *value)
{
- const wchar_t *env;
- Py_ssize_t size;
-
/* Search from index 1 because on Windows starting '=' is allowed for
defining hidden environment variables. */
if (PyUnicode_GET_LENGTH(name) == 0 ||
@@ -10108,36 +10094,68 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
return NULL;
}
- PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
+ PyObject *unicode;
+ if (value != NULL) {
+ unicode = PyUnicode_FromFormat("%U=%U", name, value);
+ }
+ else {
+ unicode = PyUnicode_FromFormat("%U=", name);
+ }
if (unicode == NULL) {
return NULL;
}
- env = PyUnicode_AsUnicodeAndSize(unicode, &size);
- if (env == NULL)
- goto error;
+ Py_ssize_t size;
+ /* PyUnicode_AsWideCharString() rejects embedded null characters */
+ wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
+ Py_DECREF(unicode);
+
+ if (env == NULL) {
+ return NULL;
+ }
if (size > _MAX_ENV) {
PyErr_Format(PyExc_ValueError,
"the environment variable is longer than %u characters",
_MAX_ENV);
- goto error;
- }
- if (wcslen(env) != (size_t)size) {
- PyErr_SetString(PyExc_ValueError, "embedded null character");
- goto error;
+ PyMem_Free(env);
+ return NULL;
}
- if (_wputenv(env)) {
+ /* _wputenv() and SetEnvironmentVariableW() update the environment in the
+ Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
+ and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
+
+ Prefer _wputenv() to be compatible with C libraries using CRT
+ variables and CRT functions using these variables (ex: getenv()). */
+ int err = _wputenv(env);
+ PyMem_Free(env);
+
+ if (err) {
posix_error();
- goto error;
+ return NULL;
}
- Py_DECREF(unicode);
Py_RETURN_NONE;
+}
+#endif
-error:
- Py_DECREF(unicode);
- return NULL;
+
+#ifdef MS_WINDOWS
+/*[clinic input]
+os.putenv
+
+ name: unicode
+ value: unicode
+ /
+
+Change or add an environment variable.
+[clinic start generated code]*/
+
+static PyObject *
+os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
+/*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
+{
+ return win32_putenv(name, value);
}
/* repeat !defined(MS_WINDOWS) to workaround an Argument Clinic issue */
#elif (defined(HAVE_SETENV) || defined(HAVE_PUTENV)) && !defined(MS_WINDOWS)
@@ -10186,7 +10204,23 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
#endif /* defined(HAVE_SETENV) || defined(HAVE_PUTENV) */
-#ifdef HAVE_UNSETENV
+#ifdef MS_WINDOWS
+/*[clinic input]
+os.unsetenv
+ name: unicode
+ /
+
+Delete an environment variable.
+[clinic start generated code]*/
+
+static PyObject *
+os_unsetenv_impl(PyObject *module, PyObject *name)
+/*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
+{
+ return win32_putenv(name, NULL);
+}
+/* repeat !defined(MS_WINDOWS) to workaround an Argument Clinic issue */
+#elif defined(HAVE_UNSETENV) && !defined(MS_WINDOWS)
/*[clinic input]
os.unsetenv
name: FSConverter
@@ -10199,16 +10233,13 @@ static PyObject *
os_unsetenv_impl(PyObject *module, PyObject *name)
/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
{
-#ifndef HAVE_BROKEN_UNSETENV
- int err;
-#endif
-
#ifdef HAVE_BROKEN_UNSETENV
unsetenv(PyBytes_AS_STRING(name));
#else
- err = unsetenv(PyBytes_AS_STRING(name));
- if (err)
+ int err = unsetenv(PyBytes_AS_STRING(name));
+ if (err) {
return posix_error();
+ }
#endif
#ifdef PY_PUTENV_DICT