199 lines
5.5 KiB
Groff
199 lines
5.5 KiB
Groff
#include <stdio.h>
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <wchar.h>
|
|
#include <locale.h>
|
|
#include <stdlib.h>
|
|
|
|
#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;
|
|
}
|