mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
139 lines
4.0 KiB
C
139 lines
4.0 KiB
C
#include <stdlib.h>
|
|
#include <strings.h>
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include <mach-o/dyld.h>
|
|
#include <Python.h>
|
|
|
|
static const char *ERR_UNKNOWNPYTHONEXCEPTION = "An uncaught exception was raised during execution of the main script, but its class or name could not be determined";
|
|
|
|
static int
|
|
report_error(const char *msg) {
|
|
fprintf(stderr, msg);
|
|
fprintf(stderr, "\n");
|
|
fflush(stderr);
|
|
return -1;
|
|
}
|
|
|
|
// These variable must be filled in before compiling
|
|
static const char *ENV_VARS[] = { /*ENV_VARS*/ NULL };
|
|
static const char *ENV_VAR_VALS[] = { /*ENV_VAR_VALS*/ NULL};
|
|
static char PROGRAM[] = "**PROGRAM**";
|
|
static const char MODULE[] = "**MODULE**";
|
|
|
|
#define EXE "@executable_path/.."
|
|
|
|
static void
|
|
set_env_vars(const char* exe_path, const char* rpath) {
|
|
int i = 0;
|
|
char buf[3*PATH_MAX];
|
|
const char *env_var, *val;
|
|
|
|
while(1) {
|
|
env_var = ENV_VARS[i];
|
|
if (env_var == NULL) break;
|
|
val = ENV_VAR_VALS[i++];
|
|
if (strstr(val, EXE) == val && strlen(val) >= strlen(EXE)+1) {
|
|
strncpy(buf, exe_path, 3*PATH_MAX-150);
|
|
strncpy(buf+strlen(exe_path), val+strlen(EXE), 150);
|
|
setenv(env_var, buf, 1);
|
|
} else
|
|
setenv(env_var, val, 1);
|
|
}
|
|
setenv("CALIBRE_LAUNCH_MODULE", MODULE, 1);
|
|
setenv("RESOURCEPATH", rpath, 1);
|
|
return;
|
|
}
|
|
|
|
int
|
|
main(int argc, char * const *argv, char * const *envp) {
|
|
char *pathPtr = NULL;
|
|
char buf[3*PATH_MAX];
|
|
int ret, i;
|
|
|
|
|
|
uint32_t buf_size = PATH_MAX+1;
|
|
char *ebuf = calloc(buf_size, sizeof(char));
|
|
ret = _NSGetExecutablePath(ebuf, &buf_size);
|
|
if (ret == -1) {
|
|
free(ebuf);
|
|
ebuf = calloc(buf_size, sizeof(char));
|
|
if (_NSGetExecutablePath(ebuf, &buf_size) != 0)
|
|
return report_error("Failed to find real path of executable.");
|
|
}
|
|
pathPtr = realpath(ebuf, buf);
|
|
if (pathPtr == NULL) {
|
|
return report_error(strerror(errno));
|
|
}
|
|
char *t;
|
|
for (i = 0; i < 3; i++) {
|
|
t = rindex(pathPtr, '/');
|
|
if (t == NULL) return report_error("Failed to determine bundle path.");
|
|
*t = '\0';
|
|
}
|
|
|
|
|
|
|
|
char rpath[PATH_MAX+1];
|
|
strncpy(rpath, pathPtr, strlen(pathPtr));
|
|
strncat(rpath, "/Contents/Resources", 50);
|
|
char exe_path[PATH_MAX+1];
|
|
strncpy(exe_path, pathPtr, strlen(pathPtr));
|
|
strncat(exe_path, "/Contents", 50);
|
|
|
|
set_env_vars(exe_path, rpath);
|
|
|
|
char main_script[PATH_MAX+1];
|
|
strncpy(main_script, rpath, strlen(rpath));
|
|
strncat(main_script, "/launcher.py", 20);
|
|
|
|
Py_SetProgramName(PROGRAM);
|
|
|
|
Py_Initialize();
|
|
|
|
char **argv_new = calloc(argc+1, sizeof(char *));
|
|
argv_new[argc] = NULL;
|
|
argv_new[0] = main_script;
|
|
memcpy(&argv_new[1], &argv[1], (argc - 1) * sizeof(char *));
|
|
PySys_SetArgv(argc, argv_new);
|
|
|
|
FILE *main_script_file = fopen(main_script, "r");
|
|
int rval = PyRun_SimpleFileEx(main_script_file, main_script, 1);
|
|
|
|
while (rval != 0) {
|
|
PyObject *exc, *exceptionClassName, *v, *exceptionName;
|
|
exc = PySys_GetObject("last_type");
|
|
|
|
if ( !exc ) {
|
|
rval = report_error(ERR_UNKNOWNPYTHONEXCEPTION);
|
|
break;
|
|
}
|
|
|
|
exceptionClassName = PyObject_GetAttrString(exc, "__name__");
|
|
if (!exceptionClassName) {
|
|
rval = report_error(ERR_UNKNOWNPYTHONEXCEPTION);
|
|
break;
|
|
}
|
|
|
|
v = PySys_GetObject("last_value");
|
|
exceptionName = (v ? PyObject_Str(v) : NULL);
|
|
|
|
char *class = PyString_AsString(exceptionClassName);
|
|
char *exception = "";
|
|
Py_DecRef(exceptionClassName);
|
|
if (exceptionName) {
|
|
exception = PyString_AsString(exceptionName);
|
|
Py_DecRef(exceptionName);
|
|
}
|
|
char msg[2000];
|
|
strncpy(msg, "An unexpected error occurred: ", 100);
|
|
strncpy(msg, class, 500);
|
|
strncpy(msg, " : ", 3);
|
|
strncpy(msg, exception, 500);
|
|
rval = report_error(msg);
|
|
break;
|
|
|
|
}
|
|
Py_Finalize();
|
|
return rval;
|
|
}
|