#include #include #include #include #include #include #include #include #define PYTHON3_STDLIB_REL_PATH "stdlib.zip" #define PYTHON3_MODULES_REL_PATH "modules" #define PYTHON3_DLL_REL_PATH "libpython3.9.so" #define SYS_PATH_BUFFER_SIZE (2*(PATH_MAX + 1)) static char NULL_PTR_STR[] = "NULL"; static void GetExecutablePath(char* path) { int size = readlink("/proc/self/exe", path, PATH_MAX); if (size < 0) size = 0; path[size] = 0; } static void GetRelativePathFormat(char* base, char* fmt) { unsigned idx; char *p, *end; end = strrchr(base, '/'); for (idx = 0, p = base; *p; ++p, ++idx) { fmt[idx] = *p; if (p == end) break; } fmt[++idx] = '%'; fmt[++idx] = 's'; fmt[++idx] = 0; } typedef void (*Py_SetProgramNamePtr)(wchar_t*); typedef void (*Py_SetPathPtr)(const wchar_t*); typedef int (*Py_MainPtr)(int, wchar_t**); typedef void* (*PyMem_RawMallocPtr)(size_t); typedef void (*PyMem_RawFreePtr)(void*); typedef wchar_t* (*Py_DecodeLocalePtr)(const char*, size_t*); int main(int argc, char** argv) { char executable[PATH_MAX + 1] = {0}; char pthfmt[PATH_MAX + 1] = {0}; char corepath[PATH_MAX + 1] = {0}; char stdlibpath[PATH_MAX + 1] = {0}; char modpath[PATH_MAX + 1] = {0}; char syspath[SYS_PATH_BUFFER_SIZE] = {0}; void* core = 0; int retcode = 126; int i; Py_SetProgramNamePtr Py_SetProgramName = 0; Py_SetPathPtr Py_SetPath = 0; Py_MainPtr Py_Main = 0; PyMem_RawMallocPtr PyMem_RawMalloc = 0; PyMem_RawFreePtr PyMem_RawFree = 0; Py_DecodeLocalePtr Py_DecodeLocale = 0; GetExecutablePath(executable); GetRelativePathFormat(executable, pthfmt); snprintf(corepath, PATH_MAX, pthfmt, PYTHON3_DLL_REL_PATH); snprintf(stdlibpath, PATH_MAX, pthfmt, PYTHON3_STDLIB_REL_PATH); snprintf(modpath, PATH_MAX, pthfmt, PYTHON3_MODULES_REL_PATH); snprintf(syspath, SYS_PATH_BUFFER_SIZE-1, "%s:%s", stdlibpath, modpath); core = dlopen(corepath, RTLD_LAZY); if (core == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load library: '%s', dlerror: %s\n", corepath, lasterr); goto exit; } Py_SetProgramName = (Py_SetProgramNamePtr)dlsym(core, "Py_SetProgramName"); if (Py_SetProgramName == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load symbol: '%s' from library '%s', dlerror: %s\n", "Py_SetProgramName", corepath, lasterr); goto exit; } Py_SetPath = (Py_SetPathPtr)dlsym(core, "Py_SetPath"); if (Py_SetPath == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load symbol: '%s' from library '%s', dlerror: %s\n", "Py_SetPath", corepath, lasterr); goto exit; } Py_Main = (Py_MainPtr)dlsym(core, "Py_Main"); if (Py_Main == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load symbol: '%s' from library '%s', dlerror: %s\n", "Py_Main", corepath, lasterr); goto exit; } PyMem_RawMalloc = (PyMem_RawMallocPtr)dlsym(core, "PyMem_RawMalloc"); if (PyMem_RawMalloc == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load symbol: '%s' from library '%s', dlerror: %s\n", "PyMem_RawMalloc", corepath, lasterr); goto exit; } PyMem_RawFree = (PyMem_RawFreePtr)dlsym(core, "PyMem_RawFree"); if (PyMem_RawFree == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load symbol: '%s' from library '%s', dlerror: %s\n", "PyMem_RawFree", corepath, lasterr); goto exit; } Py_DecodeLocale = (Py_DecodeLocalePtr)dlsym(core, "Py_DecodeLocale"); if (Py_DecodeLocale == 0) { const char* lasterr = dlerror(); if (lasterr == 0) lasterr = NULL_PTR_STR; fprintf(stderr, "Fatal Python error: cannot load symbol: '%s' from library '%s', dlerror: %s\n", "Py_DecodeLocale", corepath, lasterr); goto exit; } wchar_t* executable_w = Py_DecodeLocale(executable, 0); if (executable_w == 0) { fprintf(stderr, "Fatal Python error: unable to decode executable path: '%s'\n", executable); goto exit; } wchar_t* syspath_w = Py_DecodeLocale(syspath, 0); if (syspath_w == 0) { fprintf(stderr, "Fatal Python error: unable to decode syspath: '%s'\n", syspath); goto exit; } wchar_t** argv_copy = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*)*(argc+1)); wchar_t** argv_copy2 = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*)*(argc+1)); char* oldloc = strdup(setlocale(LC_ALL, 0)); setlocale(LC_ALL, ""); for (i = 0; i < argc; ++i) { argv_copy[i] = Py_DecodeLocale(argv[i], 0); if (argv_copy[i] == 0) { free(oldloc); fprintf(stderr, "Fatal Python error: unable to decode the command line argument #%i\n", i + 1); goto exit; } argv_copy2[i] = argv_copy[i]; } argv_copy2[argc] = argv_copy[argc] = 0; setlocale(LC_ALL, oldloc); free(oldloc); Py_SetProgramName(executable_w); Py_SetPath(syspath_w); retcode = Py_Main(argc, argv_copy); PyMem_RawFree(executable_w); PyMem_RawFree(syspath_w); for (i = 0; i < argc; i++) { PyMem_RawFree(argv_copy2[i]); } PyMem_RawFree(argv_copy); PyMem_RawFree(argv_copy2); exit: if (core != 0) dlclose(core); return retcode; }