macOS: Fix PDF Output not working when running ebook-convert via symlink on the command line. Fixes #1857377 [ebook-convert hangs on rendering (possible packaging issue)](https://bugs.launchpad.net/calibre/+bug/1857377)

It really grinds my gears that this is necessary, but with macOS...
This commit is contained in:
Kovid Goyal 2019-12-24 19:55:20 +05:30
parent fb7154b67c
commit e24e4b0a58
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 40 additions and 32 deletions

View File

@ -1,5 +1,14 @@
#include "util.h" #include "util.h"
#include <stdlib.h> #include <stdlib.h>
#include <libproc.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#define fatal(...) { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); }
#define arraysz(x) (sizeof(x)/sizeof(x[0]))
// These variables must be filled in before compiling // These variables must be filled in before compiling
static const char *ENV_VARS[] = { /*ENV_VARS*/ NULL }; static const char *ENV_VARS[] = { /*ENV_VARS*/ NULL };
@ -11,7 +20,22 @@ static const char PYVER[] = "**PYVER**";
int int
main(int argc, const char **argv, const char **envp) { main(int argc, char* const *argv, const char **envp) {
return run(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, **IS_GUI**, argc, argv, envp); char pathbuf[PROC_PIDPATHINFO_MAXSIZE], realpath_buf[PROC_PIDPATHINFO_MAXSIZE * 5];
pid_t pid = getpid();
int ret = proc_pidpath(pid, pathbuf, arraysz(pathbuf));
if (ret <= 0) fatal("failed to get executable path for current pid with error: %s", strerror(errno));
char *path = realpath(pathbuf, realpath_buf);
if (path == NULL) fatal("failed to get realpath for executable path with error: %s", strerror(errno));
// We re-exec using an absolute path because the Qt WebEngine sandbox does not work
// when running via symlink
const int is_gui = **IS_GUI**;
if (!is_gui && strcmp(PROGRAM, "calibre-parallel") != 0 && strcmp(argv[0], path) != 0) {
char* new_argv[1024] = {0};
new_argv[0] = path;
for (int i = 1; i < argc && i < arraysz(new_argv) - 1; i++) new_argv[i] = argv[i];
execv(path, new_argv);
} }
return run(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, is_gui, argc, argv, envp, path);
}

View File

@ -47,7 +47,7 @@ set_env_vars(const char **ENV_VARS, const char **ENV_VAR_VALS, const char* exe_p
void initialize_interpreter(const char **ENV_VARS, const char **ENV_VAR_VALS, void initialize_interpreter(const char **ENV_VARS, const char **ENV_VAR_VALS,
char *PROGRAM, const char *MODULE, const char *FUNCTION, const char *PYVER, int IS_GUI, char *PROGRAM, const char *MODULE, const char *FUNCTION, const char *PYVER, int IS_GUI,
const char* exe_path, const char *rpath, int argc, const char **argv) { const char* exe_path, const char *rpath, int argc, char* const *argv) {
PyObject *pargv, *v; PyObject *pargv, *v;
int i; int i;
Py_OptimizeFlag = 2; Py_OptimizeFlag = 2;
@ -159,41 +159,28 @@ EXPORT
int int
run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM, run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
const char *MODULE, const char *FUNCTION, const char *PYVER, const char *MODULE, const char *FUNCTION, const char *PYVER,
int IS_GUI, int argc, const char **argv, const char **envp) { int IS_GUI, int argc, char * const *argv, const char **envp, char *full_exe_path) {
char *pathPtr = NULL, *t = NULL; char *t = NULL;
char buf[3*PATH_MAX];
int ret = 0, i; int ret = 0, i;
PyObject *site, *mainf, *res; PyObject *site, *mainf, *res;
uint32_t buf_size = PATH_MAX+1; 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));
}
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
t = rindex(pathPtr, '/'); t = rindex(full_exe_path, '/');
if (t == NULL) return report_error("Failed to determine bundle path."); if (t == NULL) return report_error("Failed to determine bundle path.");
*t = '\0'; *t = '\0';
} }
if (strstr(pathPtr, "/calibre.app/Contents/") != NULL) { if (strstr(full_exe_path, "/calibre.app/Contents/") != NULL) {
// We are one of the duplicate executables created to workaround codesign's limitations // We are one of the duplicate executables created to workaround codesign's limitations
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
t = rindex(pathPtr, '/'); t = rindex(full_exe_path, '/');
if (t == NULL) return report_error("Failed to resolve bundle path in dummy executable"); if (t == NULL) return report_error("Failed to resolve bundle path in dummy executable");
*t = '\0'; *t = '\0';
} }
} }
char rpath[PATH_MAX+1], exe_path[PATH_MAX+1]; char rpath[PATH_MAX+1], exe_path[PATH_MAX+1];
snprintf(exe_path, PATH_MAX+1, "%s/Contents", pathPtr); snprintf(exe_path, PATH_MAX+1, "%s/Contents", full_exe_path);
snprintf(rpath, PATH_MAX+1, "%s/Resources", exe_path); snprintf(rpath, PATH_MAX+1, "%s/Resources", exe_path);
initialize_interpreter(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, IS_GUI, initialize_interpreter(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, IS_GUI,
exe_path, rpath, argc, argv); exe_path, rpath, argc, argv);
@ -224,6 +211,3 @@ run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
//printf("11111 Returning: %d\r\n", ret); //printf("11111 Returning: %d\r\n", ret);
return ret; return ret;
} }

View File

@ -2,4 +2,4 @@
int run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM, int run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
const char *MODULE, const char *FUNCTION, const char *PYVER, int IS_GUI, const char *MODULE, const char *FUNCTION, const char *PYVER, int IS_GUI,
int argc, const char **argv, const char **envp); int argc, char *const *argv, const char **envp, char *full_exe_path);