#include "Python.h" #include "pycore_coreconfig.h" #include "pycore_getopt.h" #define DECODE_LOCALE_ERR(NAME, LEN) \ (((LEN) == -2) \ ? _Py_INIT_USER_ERR("cannot decode " NAME) \ : _Py_INIT_NO_MEMORY()) /* --- File system encoding/errors -------------------------------- */ /* The filesystem encoding is chosen by config_init_fs_encoding(), see also initfsencoding(). */ const char *Py_FileSystemDefaultEncoding = NULL; int Py_HasFileSystemDefaultEncoding = 0; const char *Py_FileSystemDefaultEncodeErrors = NULL; int _Py_HasFileSystemDefaultEncodeErrors = 0; void _Py_ClearFileSystemEncoding(void) { if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { PyMem_RawFree((char*)Py_FileSystemDefaultEncoding); Py_FileSystemDefaultEncoding = NULL; } if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) { PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors); Py_FileSystemDefaultEncodeErrors = NULL; } } /* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors global configuration variables. */ int _Py_SetFileSystemEncoding(const char *encoding, const char *errors) { char *encoding2 = _PyMem_RawStrdup(encoding); if (encoding2 == NULL) { return -1; } char *errors2 = _PyMem_RawStrdup(errors); if (errors2 == NULL) { PyMem_RawFree(encoding2); return -1; } _Py_ClearFileSystemEncoding(); Py_FileSystemDefaultEncoding = encoding2; Py_HasFileSystemDefaultEncoding = 0; Py_FileSystemDefaultEncodeErrors = errors2; _Py_HasFileSystemDefaultEncodeErrors = 0; return 0; } /* --- _PyArgv ---------------------------------------------------- */ _PyInitError _PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p) { wchar_t** argv; if (args->use_bytes_argv) { /* +1 for a the NULL terminator */ size_t size = sizeof(wchar_t*) * (args->argc + 1); argv = (wchar_t **)PyMem_RawMalloc(size); if (argv == NULL) { return _Py_INIT_NO_MEMORY(); } for (int i = 0; i < args->argc; i++) { size_t len; wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len); if (arg == NULL) { _Py_wstrlist_clear(i, argv); return DECODE_LOCALE_ERR("command line arguments", (Py_ssize_t)len); } argv[i] = arg; } argv[args->argc] = NULL; } else { argv = args->wchar_argv; } *argv_p = argv; return _Py_INIT_OK(); } /* --- _PyPreCmdline ------------------------------------------------- */ typedef struct { const _PyArgv *args; int argc; wchar_t **argv; } _PyPreCmdline; static void precmdline_clear(_PyPreCmdline *cmdline) { if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) { _Py_wstrlist_clear(cmdline->args->argc, cmdline->argv); } cmdline->argv = NULL; } /* --- _PyPreConfig ----------------------------------------------- */ void _PyPreConfig_Clear(_PyPreConfig *config) { } int _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2) { _PyPreConfig_Clear(config); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR COPY_ATTR(isolated); COPY_ATTR(use_environment); #undef COPY_ATTR return 0; } void _PyPreConfig_GetGlobalConfig(_PyPreConfig *config) { #define COPY_FLAG(ATTR, VALUE) \ if (config->ATTR == -1) { \ config->ATTR = VALUE; \ } #define COPY_NOT_FLAG(ATTR, VALUE) \ if (config->ATTR == -1) { \ config->ATTR = !(VALUE); \ } COPY_FLAG(isolated, Py_IsolatedFlag); COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); #undef COPY_FLAG #undef COPY_NOT_FLAG } void _PyPreConfig_SetGlobalConfig(const _PyPreConfig *config) { #define COPY_FLAG(ATTR, VAR) \ if (config->ATTR != -1) { \ VAR = config->ATTR; \ } #define COPY_NOT_FLAG(ATTR, VAR) \ if (config->ATTR != -1) { \ VAR = !config->ATTR; \ } COPY_FLAG(isolated, Py_IsolatedFlag); COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); #undef COPY_FLAG #undef COPY_NOT_FLAG } _PyInitError _PyPreConfig_Read(_PyPreConfig *config) { _PyPreConfig_GetGlobalConfig(config); if (config->isolated > 0) { config->use_environment = 0; } /* Default values */ if (config->use_environment < 0) { config->use_environment = 0; } assert(config->isolated >= 0); assert(config->use_environment >= 0); return _Py_INIT_OK(); } int _PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict) { #define SET_ITEM(KEY, EXPR) \ do { \ PyObject *obj = (EXPR); \ if (obj == NULL) { \ goto fail; \ } \ int res = PyDict_SetItemString(dict, (KEY), obj); \ Py_DECREF(obj); \ if (res < 0) { \ goto fail; \ } \ } while (0) #define SET_ITEM_INT(ATTR) \ SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) SET_ITEM_INT(isolated); SET_ITEM_INT(use_environment); return 0; fail: return -1; #undef SET_ITEM #undef SET_ITEM_INT } /* Parse the command line arguments */ static _PyInitError preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline) { _PyOS_ResetGetOpt(); /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv() is responsible for that */ _PyOS_opterr = 0; do { int longindex = -1; int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex); if (c == EOF || c == 'c' || c == 'm') { break; } switch (c) { case 'E': config->use_environment = 0; break; case 'I': config->isolated++; break; default: /* ignore other argument: handled by _PyCoreConfig_ReadFromArgv() */ break; } } while (1); return _Py_INIT_OK(); } _PyInitError _PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args) { _PyInitError err; _PyPreCmdline cmdline; memset(&cmdline, 0, sizeof(cmdline)); cmdline.args = args; err = _PyArgv_Decode(cmdline.args, &cmdline.argv); if (_Py_INIT_FAILED(err)) { goto done; } err = preconfig_parse_cmdline(config, &cmdline); if (_Py_INIT_FAILED(err)) { goto done; } err = _PyPreConfig_Read(config); if (_Py_INIT_FAILED(err)) { goto done; } err = _Py_INIT_OK(); done: precmdline_clear(&cmdline); return err; } void _PyPreConfig_Write(const _PyPreConfig *config) { }