bpo-39395: putenv() and unsetenv() always available (GH-18135)

The os.putenv() and os.unsetenv() functions are now always available.

On non-Windows platforms, Python now requires setenv() and unsetenv()
functions to build.

Remove putenv_dict from posixmodule.c: it's not longer needed.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 3a8e6aa..b71eddf 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -819,22 +819,8 @@
     }
 }
 
-/* Windows _wputenv() and setenv() copy the arguments and so don't require
-   the caller to manage the variable memory. Only Unix putenv() requires
-   putenv_dict. */
-#if defined(HAVE_PUTENV) && !defined(MS_WINDOWS) && !defined(HAVE_SETENV)
-#  define PY_PUTENV_DICT
-#endif
-
 typedef struct {
     PyObject *billion;
-#ifdef PY_PUTENV_DICT
-    /* putenv() requires that the caller manages the environment variable
-       memory. Use a Python dictionary for that: name => env, where env is a
-       string like "name=value". On Windows, dict keys and values are Unicode
-       strings. On Unix, they are bytes strings. */
-    PyObject *putenv_dict;
-#endif
     PyObject *DirEntryType;
     PyObject *ScandirIteratorType;
 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
@@ -2118,9 +2104,6 @@
 _posix_clear(PyObject *module)
 {
     Py_CLEAR(_posixstate(module)->billion);
-#ifdef PY_PUTENV_DICT
-    Py_CLEAR(_posixstate(module)->putenv_dict);
-#endif
     Py_CLEAR(_posixstate(module)->DirEntryType);
     Py_CLEAR(_posixstate(module)->ScandirIteratorType);
 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
@@ -2145,9 +2128,6 @@
 _posix_traverse(PyObject *module, visitproc visit, void *arg)
 {
     Py_VISIT(_posixstate(module)->billion);
-#ifdef PY_PUTENV_DICT
-    Py_VISIT(_posixstate(module)->putenv_dict);
-#endif
     Py_VISIT(_posixstate(module)->DirEntryType);
     Py_VISIT(_posixstate(module)->ScandirIteratorType);
 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
@@ -10065,23 +10045,6 @@
 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
 
 
-#ifdef PY_PUTENV_DICT
-static void
-posix_putenv_dict_setitem(PyObject *name, PyObject *value)
-{
-    /* Install the first arg and newstr in putenv_dict;
-     * this will cause previous value to be collected.  This has to
-     * happen after the real putenv() call because the old value
-     * was still accessible until then. */
-    if (PyDict_SetItem(_posixstate_global->putenv_dict, name, value))
-        /* really not much we can do; just leak */
-        PyErr_Clear();
-    else
-        Py_DECREF(value);
-}
-#endif  /* PY_PUTENV_DICT */
-
-
 #ifdef MS_WINDOWS
 static PyObject*
 win32_putenv(PyObject *name, PyObject *value)
@@ -10157,8 +10120,7 @@
 {
     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)
+#else
 /*[clinic input]
 os.putenv
 
@@ -10181,27 +10143,12 @@
         return NULL;
     }
 
-#ifdef HAVE_SETENV
     if (setenv(name_string, value_string, 1)) {
         return posix_error();
     }
-#else
-    PyObject *bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
-    if (bytes == NULL) {
-        return NULL;
-    }
-
-    char *env = PyBytes_AS_STRING(bytes);
-    if (putenv(env)) {
-        Py_DECREF(bytes);
-        return posix_error();
-    }
-
-    posix_putenv_dict_setitem(name, bytes);
-#endif
     Py_RETURN_NONE;
 }
-#endif  /* defined(HAVE_SETENV) || defined(HAVE_PUTENV) */
+#endif  /* !defined(MS_WINDOWS) */
 
 
 #ifdef MS_WINDOWS
@@ -10219,8 +10166,7 @@
 {
     return win32_putenv(name, NULL);
 }
-/* repeat !defined(MS_WINDOWS) to workaround an Argument Clinic issue */
-#elif defined(HAVE_UNSETENV) && !defined(MS_WINDOWS)
+#else
 /*[clinic input]
 os.unsetenv
     name: FSConverter
@@ -10242,24 +10188,9 @@
     }
 #endif
 
-#ifdef PY_PUTENV_DICT
-    /* Remove the key from putenv_dict;
-     * this will cause it to be collected.  This has to
-     * happen after the real unsetenv() call because the
-     * old value was still accessible until then.
-     */
-    if (PyDict_DelItem(_posixstate(module)->putenv_dict, name)) {
-        /* really not much we can do; just leak */
-        if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
-            return NULL;
-        }
-        PyErr_Clear();
-    }
-#endif
-
     Py_RETURN_NONE;
 }
-#endif /* HAVE_UNSETENV */
+#endif /* !MS_WINDOWS */
 
 
 /*[clinic input]
@@ -14553,12 +14484,6 @@
     Py_INCREF(PyExc_OSError);
     PyModule_AddObject(m, "error", PyExc_OSError);
 
-#ifdef PY_PUTENV_DICT
-    /* Save putenv() parameters as values here, so we can collect them when they
-     * get re-set with another call for the same key. */
-    _posixstate(m)->putenv_dict = PyDict_New();
-#endif
-
 #if defined(HAVE_WAITID) && !defined(__APPLE__)
     waitid_result_desc.name = MODNAME ".waitid_result";
     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);