diff --git a/AppRun.c.patch b/AppRun.c.patch index d408b38..53dfc48 100644 --- a/AppRun.c.patch +++ b/AppRun.c.patch @@ -1,32 +1,225 @@ --- a/AppRun.c +++ b/AppRun.c -@@ -164,6 +164,10 @@ - char *old_env; - size_t length; - const char *format; -+ checkrt(usr_in_appdir); +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + #define die(...) \ + do { \ +@@ -102,118 +103,120 @@ + line[n] = '\0'; + } + +- // count arguments +- char* arg = exe; +- int argcount = 0; +- while ((arg += (strlen(arg)+1)) && *arg) +- argcount += 1; +- +- // merge args +- char* outargptrs[argcount + argc + 1]; +- outargptrs[0] = exe; +- int outargindex = 1; +- arg = exe; +- int argc_ = argc - 1; // argv[0] is the filename +- char** argv_ = argv + 1; +- while ((arg += (strlen(arg)+1)) && *arg) { +- if (arg[0] == '%' || (arg[0] == '"' && arg[1] == '%')) { // handle desktop file field codes +- char code = arg[arg[0] == '%' ? 1 : 2]; +- switch(code) { +- case 'f': +- case 'u': +- if (argc_ > 0) { +- outargptrs[outargindex++] = *argv_++; +- argc_--; +- } +- break; +- case 'F': +- case 'U': +- while (argc_ > 0) { +- outargptrs[outargindex++] = *argv_++; +- argc_--; +- } +- break; +- case 'i': +- case 'c': +- case 'k': +- fprintf(stderr, "WARNING: Desktop file field code %%%c is not currently supported\n", code); +- break; +- default: +- fprintf(stderr, "WARNING: Invalid desktop file field code %%%c\n", code); +- break; +- } +- } else { +- outargptrs[outargindex++] = arg; ++ int pid; ++ if ((pid = fork()) == -1) { ++ int error = errno; ++ die("fork() failed: %s\n", strerror(error)); ++ } else if (pid == 0) { ++ // count arguments ++ char* arg = exe; ++ int argcount = 0; ++ while ((arg += (strlen(arg)+1)) && *arg) ++ argcount += 1; ++ ++ // merge args ++ char* outargptrs[argcount + argc + 1]; ++ outargptrs[0] = exe; ++ int outargindex = 1; ++ int argc_ = argc - 1; // argv[0] is the filename ++ char** argv_ = argv + 1; ++ while (argc_ > 0) { ++ outargptrs[outargindex++] = *argv_++; ++ argc_--; + } +- } +- while (argc_ > 0) { +- outargptrs[outargindex++] = *argv_++; +- argc_--; +- } +- outargptrs[outargindex] = '\0'; // trailing null argument required by execvp() ++ outargptrs[outargindex] = '\0'; // trailing null argument required by execvp() ++ ++ // change directory ++ size_t appdir_s = strlen(appdir); ++ char *usr_in_appdir = malloc(appdir_s + 5); ++ snprintf(usr_in_appdir, appdir_s + 5, "%s/usr", appdir); ++ ret = chdir(usr_in_appdir); ++ if (ret != 0) ++ die("Could not cd into %s\n", usr_in_appdir); ++ ++ // set environment variables ++ char *old_env; ++ size_t length; ++ const char *format; + -+ if (optional_ld_preload) -+ putenv(optional_ld_preload); ++ checkrt(usr_in_appdir); - /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ - SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); -@@ -172,7 +176,7 @@ - SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); +- // change directory +- size_t appdir_s = strlen(appdir); +- char *usr_in_appdir = malloc(appdir_s + 5); +- snprintf(usr_in_appdir, appdir_s + 5, "%s/usr", appdir); +- ret = chdir(usr_in_appdir); +- if (ret != 0) +- die("Could not cd into %s\n", usr_in_appdir); ++ if (optional_ld_preload) ++ putenv(optional_ld_preload); - old_env = getenv("LD_LIBRARY_PATH") ?: ""; +- // set environment variables +- char *old_env; +- size_t length; +- const char *format; ++ /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ ++ SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); + +- /* https://docs.python.org/2/using/cmdline.html#envvar-PYTHONHOME */ +- SET_NEW_ENV(new_pythonhome, appdir_s, "PYTHONHOME=%s/usr/", appdir); ++ old_env = getenv("PATH") ?: ""; ++ SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); + +- old_env = getenv("PATH") ?: ""; +- SET_NEW_ENV(new_path, appdir_s*5 + strlen(old_env), "PATH=%s/usr/bin/:%s/usr/sbin/:%s/usr/games/:%s/bin/:%s/sbin/:%s", appdir, appdir, appdir, appdir, appdir, old_env); ++ old_env = getenv("LD_LIBRARY_PATH") ?: ""; ++ SET_NEW_ENV(new_ld_library_path, strlen(optional_ld_library_path) + appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", optional_ld_library_path, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); + +- old_env = getenv("LD_LIBRARY_PATH") ?: ""; - SET_NEW_ENV(new_ld_library_path, appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); -+ SET_NEW_ENV(new_ld_library_path, strlen(optional_ld_library_path) + appdir_s*10 + strlen(old_env), "LD_LIBRARY_PATH=%s%s/usr/lib/:%s/usr/lib/i386-linux-gnu/:%s/usr/lib/x86_64-linux-gnu/:%s/usr/lib32/:%s/usr/lib64/:%s/lib/:%s/lib/i386-linux-gnu/:%s/lib/x86_64-linux-gnu/:%s/lib32/:%s/lib64/:%s", optional_ld_library_path, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); - - old_env = getenv("PYTHONPATH") ?: ""; - SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); -@@ -201,6 +205,9 @@ - if (ret == -1) ++ old_env = getenv("PYTHONPATH") ?: ""; ++ SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); + +- old_env = getenv("PYTHONPATH") ?: ""; +- SET_NEW_ENV(new_pythonpath, appdir_s + strlen(old_env), "PYTHONPATH=%s/usr/share/pyshared/:%s", appdir, old_env); ++ old_env = getenv("XDG_DATA_DIRS") ?: "/usr/local/share/:/usr/share/"; ++ SET_NEW_ENV(new_xdg_data_dirs, appdir_s + strlen(old_env), "XDG_DATA_DIRS=%s/usr/share/:%s", appdir, old_env); + +- old_env = getenv("XDG_DATA_DIRS") ?: "/usr/local/share/:/usr/share/"; +- SET_NEW_ENV(new_xdg_data_dirs, appdir_s + strlen(old_env), "XDG_DATA_DIRS=%s/usr/share/:%s", appdir, old_env); ++ old_env = getenv("PERLLIB") ?: ""; ++ SET_NEW_ENV(new_perllib, appdir_s*2 + strlen(old_env), "PERLLIB=%s/usr/share/perl5/:%s/usr/lib/perl5/:%s", appdir, appdir, old_env); + +- old_env = getenv("PERLLIB") ?: ""; +- SET_NEW_ENV(new_perllib, appdir_s*2 + strlen(old_env), "PERLLIB=%s/usr/share/perl5/:%s/usr/lib/perl5/:%s", appdir, appdir, old_env); ++ /* http://askubuntu.com/questions/251712/how-can-i-install-a-gsettings-schema-without-root-privileges */ ++ old_env = getenv("GSETTINGS_SCHEMA_DIR") ?: ""; ++ SET_NEW_ENV(new_gsettings_schema_dir, appdir_s + strlen(old_env), "GSETTINGS_SCHEMA_DIR=%s/usr/share/glib-2.0/schemas/:%s", appdir, old_env); + +- /* http://askubuntu.com/questions/251712/how-can-i-install-a-gsettings-schema-without-root-privileges */ +- old_env = getenv("GSETTINGS_SCHEMA_DIR") ?: ""; +- SET_NEW_ENV(new_gsettings_schema_dir, appdir_s + strlen(old_env), "GSETTINGS_SCHEMA_DIR=%s/usr/share/glib-2.0/schemas/:%s", appdir, old_env); ++ old_env = getenv("QT_PLUGIN_PATH") ?: ""; ++ SET_NEW_ENV(new_qt_plugin_path, appdir_s*10 + strlen(old_env), "QT_PLUGIN_PATH=%s/usr/lib/qt4/plugins/:%s/usr/lib/i386-linux-gnu/qt4/plugins/:%s/usr/lib/x86_64-linux-gnu/qt4/plugins/:%s/usr/lib32/qt4/plugins/:%s/usr/lib64/qt4/plugins/:%s/usr/lib/qt5/plugins/:%s/usr/lib/i386-linux-gnu/qt5/plugins/:%s/usr/lib/x86_64-linux-gnu/qt5/plugins/:%s/usr/lib32/qt5/plugins/:%s/usr/lib64/qt5/plugins/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); + +- old_env = getenv("QT_PLUGIN_PATH") ?: ""; +- SET_NEW_ENV(new_qt_plugin_path, appdir_s*10 + strlen(old_env), "QT_PLUGIN_PATH=%s/usr/lib/qt4/plugins/:%s/usr/lib/i386-linux-gnu/qt4/plugins/:%s/usr/lib/x86_64-linux-gnu/qt4/plugins/:%s/usr/lib32/qt4/plugins/:%s/usr/lib64/qt4/plugins/:%s/usr/lib/qt5/plugins/:%s/usr/lib/i386-linux-gnu/qt5/plugins/:%s/usr/lib/x86_64-linux-gnu/qt5/plugins/:%s/usr/lib32/qt5/plugins/:%s/usr/lib64/qt5/plugins/:%s", appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, appdir, old_env); ++ SET_NEW_ENV(new_gspath, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH=%s/usr/lib/gstreamer:%s", appdir, old_env); ++ SET_NEW_ENV(new_gspath1, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH_1_0=%s/usr/lib/gstreamer-1.0:%s", appdir, old_env); ++ ++ /* Otherwise may get errors because Python cannot write __pycache__ bytecode cache */ ++ putenv("PYTHONDONTWRITEBYTECODE=1"); + +- SET_NEW_ENV(new_gspath, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH=%s/usr/lib/gstreamer:%s", appdir, old_env); +- SET_NEW_ENV(new_gspath1, appdir_s + strlen(old_env), "GST_PLUGIN_SYSTEM_PATH_1_0=%s/usr/lib/gstreamer-1.0:%s", appdir, old_env); ++ /* Set pid & ppid */ ++ pid_t pid = getpid(); ++ pid_t ppid = getppid(); + +- /* Otherwise may get errors because Python cannot write __pycache__ bytecode cache */ +- putenv("PYTHONDONTWRITEBYTECODE=1"); ++ int pid_len = snprintf(NULL, 0, "%d", pid); ++ int ppid_len = snprintf(NULL, 0, "%d", ppid); ++ ++ char *s_pid = malloc(pid_len + 1); ++ snprintf(s_pid, pid_len + 1, "%d", pid); ++ ++ char *s_ppid = malloc(ppid_len + 1); ++ snprintf(s_ppid, ppid_len + 1, "%d", ppid); ++ ++ setenv("PID", s_pid, 1); ++ setenv("PPID", s_ppid, 1); + +- /* Run */ +- ret = execvp(exe, outargptrs); ++ /* Run */ ++ execvp(exe, outargptrs); + +- int error = errno; ++ free(optional_ld_library_path); ++ if (optional_ld_preload) ++ free(optional_ld_preload); ++ ++ free(usr_in_appdir); ++ free(new_pythonhome); ++ free(new_path); ++ free(new_ld_library_path); ++ free(new_pythonpath); ++ free(new_xdg_data_dirs); ++ free(new_perllib); ++ free(new_gsettings_schema_dir); ++ free(new_qt_plugin_path); + +- if (ret == -1) ++ int error = errno; die("Error executing '%s': %s\n", exe, strerror(error)); - -+ free(optional_ld_library_path); -+ if (optional_ld_preload) -+ free(optional_ld_preload); ++ } ++ ++ int status = 0; ++ int rv = waitpid(pid, &status, 0); ++ status = rv > 0 && WIFEXITED (status) ? WEXITSTATUS (status) : 1; + free(line); free(desktop_file); - free(usr_in_appdir); +- free(usr_in_appdir); +- free(new_pythonhome); +- free(new_path); +- free(new_ld_library_path); +- free(new_pythonpath); +- free(new_xdg_data_dirs); +- free(new_perllib); +- free(new_gsettings_schema_dir); +- free(new_qt_plugin_path); +- return 0; ++ return status; + } diff --git a/Makefile b/Makefile index cd8fe34..dab0cff 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,6 @@ AppRun_patched.c: AppRun.c patch -p1 --output $@ < AppRun.c.patch AppRun.c: - wget -c "https://raw.githubusercontent.com/AppImage/AppImageKit/appimagetool/master/src/AppRun.c" + wget -c "https://raw.githubusercontent.com/AppImage/AppImageKit/master/src/AppRun.c" .PHONY: checkrt test run_tests all clean diff --git a/env.c b/env.c index 6776bff..9c1d476 100755 --- a/env.c +++ b/env.c @@ -43,6 +43,21 @@ void env_free(char* const *env) { free((char**)env); } +pid_t get_parent_pid() { + pid_t ppid = 0; + char *s_ppid = getenv("PPID"); + + if(s_ppid) { + ppid = atoi(s_ppid); + } + + if (!ppid) { + ppid = getppid(); + } + + return ppid; +} + static size_t get_number_of_variables(FILE *file, char **buffer, size_t *len) { size_t number = 0; @@ -103,7 +118,7 @@ static char* const* read_env_from_process(pid_t pid) { } char* const* read_parent_env() { - pid_t ppid = getppid(); + pid_t ppid = get_parent_pid(); return read_env_from_process(ppid); } diff --git a/env.h b/env.h index affc2d4..36f491c 100755 --- a/env.h +++ b/env.h @@ -3,6 +3,7 @@ #include +pid_t get_parent_pid(); char* const* read_parent_env(); void env_free(char* const *env); diff --git a/exec.c b/exec.c index ad0f489..29d04ec 100644 --- a/exec.c +++ b/exec.c @@ -79,12 +79,12 @@ static int exec_common(execve_func_t function, const char *filename, char* const DEBUG("filename %s, fullpath %s\n", filename, fullpath); char* const *env = envp; if (is_external_process(fullpath)) { - DEBUG("External process detected. Restoring env vars from parent %d\n", getppid()); + DEBUG("External process detected. Restoring env vars from parent %d\n", get_parent_pid()); env = read_parent_env(); - if (!env) + if (!env) { env = envp; - else DEBUG("Error restoring env vars from parent\n"); + } } int ret = function(filename, argv, env);