Issue #8622: Add PYTHONFSENCODING environment variable to override the
filesystem encoding.

initfsencoding() displays also a better error message if get_codeset() failed.
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 76a8eef..fd31974 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -134,18 +134,13 @@
     return flag;
 }
 
-#if defined(HAVE_LANGINFO_H) && defined(CODESET)
 static char*
-get_codeset(void)
+get_codec_name(const char *encoding)
 {
-    char* codeset, *name_str;
+    char *name_utf8, *name_str;
     PyObject *codec, *name = NULL;
 
-    codeset = nl_langinfo(CODESET);
-    if (!codeset || codeset[0] == '\0')
-        return NULL;
-
-    codec = _PyCodec_Lookup(codeset);
+    codec = _PyCodec_Lookup(encoding);
     if (!codec)
         goto error;
 
@@ -154,18 +149,34 @@
     if (!name)
         goto error;
 
-    name_str = _PyUnicode_AsString(name);
+    name_utf8 = _PyUnicode_AsString(name);
     if (name == NULL)
         goto error;
-    codeset = strdup(name_str);
+    name_str = strdup(name_utf8);
     Py_DECREF(name);
-    return codeset;
+    if (name_str == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+    return name_str;
 
 error:
     Py_XDECREF(codec);
     Py_XDECREF(name);
     return NULL;
 }
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+static char*
+get_codeset(void)
+{
+    char* codeset = nl_langinfo(CODESET);
+    if (!codeset || codeset[0] == '\0') {
+        PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty");
+        return NULL;
+    }
+    return get_codec_name(codeset);
+}
 #endif
 
 void
@@ -706,25 +717,35 @@
 {
     PyObject *codec;
 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
-    char *codeset;
+    char *codeset = NULL;
 
     if (Py_FileSystemDefaultEncoding == NULL) {
-        /* On Unix, set the file system encoding according to the
-           user's preference, if the CODESET names a well-known
-           Python codec, and Py_FileSystemDefaultEncoding isn't
-           initialized by other means. Also set the encoding of
-           stdin and stdout if these are terminals.  */
-        codeset = get_codeset();
+        const char *env_encoding = Py_GETENV("PYTHONFSENCODING");
+        if (env_encoding != NULL) {
+            codeset = get_codec_name(env_encoding);
+            if (!codeset) {
+                fprintf(stderr, "PYTHONFSENCODING is not a valid encoding:\n");
+                PyErr_Print();
+            }
+        }
+        if (!codeset) {
+            /* On Unix, set the file system encoding according to the
+               user's preference, if the CODESET names a well-known
+               Python codec, and Py_FileSystemDefaultEncoding isn't
+               initialized by other means. Also set the encoding of
+               stdin and stdout if these are terminals.  */
+            codeset = get_codeset();
+        }
         if (codeset != NULL) {
             Py_FileSystemDefaultEncoding = codeset;
             Py_HasFileSystemDefaultEncoding = 0;
             return;
+        } else {
+            fprintf(stderr, "Unable to get the locale encoding:\n");
+            PyErr_Print();
         }
 
-        PyErr_Clear();
-        fprintf(stderr,
-                "Unable to get the locale encoding: "
-                "fallback to utf-8\n");
+        fprintf(stderr, "Unable to get the filesystem encoding: fallback to utf-8\n");
         Py_FileSystemDefaultEncoding = "utf-8";
         Py_HasFileSystemDefaultEncoding = 1;
     }