From fdf64256127b2661bd6aa81ac694350028d36c43 Mon Sep 17 00:00:00 2001 From: Jeremy Huddleston Date: Tue, 9 Dec 2008 23:47:32 -0800 Subject: XQuartz: Avoid using login /bin/sh blech. Just use a bash script to start the app, so it will inherit the right environment (cherry picked from commit f4b7ad9cc6b0c99fc7ee8516c4bf858ece938148) --- hw/xquartz/X11Controller.m | 122 +++++++++++++++++++--------------- hw/xquartz/bundle/X11.sh | 3 + hw/xquartz/bundle/mk_bundke.sh | 3 + hw/xquartz/mach-startup/bundle-main.c | 43 ++++++++---- 4 files changed, 104 insertions(+), 67 deletions(-) create mode 100755 hw/xquartz/bundle/X11.sh diff --git a/hw/xquartz/X11Controller.m b/hw/xquartz/X11Controller.m index 67a80d34c..7222f463b 100644 --- a/hw/xquartz/X11Controller.m +++ b/hw/xquartz/X11Controller.m @@ -314,65 +314,79 @@ BOOL xquartz_resetenv_display = NO; - (void) launch_client:(NSString *)filename { - const char *command = [filename UTF8String]; - const char *argv[7]; - int child1, child2 = 0; - int status; - - argv[0] = "/usr/bin/login"; - argv[1] = "-fp"; - argv[2] = getlogin(); - argv[3] = [X11App prefs_get_string:@PREFS_LOGIN_SHELL default:"/bin/sh"]; - argv[4] = "-c"; - argv[5] = command; - argv[6] = NULL; - - /* Do the fork-twice trick to avoid having to reap zombies */ + const char *command = [filename UTF8String]; + int child1, child2 = 0; + int status; + char newcommand[1024]; + char *newargv[1024]; + char buf[128]; + size_t newargc; + char *s; - child1 = fork(); + if(strlen(command) > 1023) { + fprintf(stderr, "Error: command is too long: %s\n", command); + return; + } + + strlcpy(newcommand, command, 1024); - switch (child1) { - case -1: /* error */ - break; + for(newargc=0, s=newcommand; *s; newargc++) { + for(; *s && *s == ' '; s++); + if(!*s) + break; + + newargv[newargc] = s; + for(; *s && *s != ' '; s++); + + if(*s) { + *s='\0'; + s++; + } + } + newargv[newargc] = NULL; + + s = getenv("DISPLAY"); + if (xquartz_resetenv_display || s == NULL || s[0] == 0) { + snprintf(buf, sizeof(buf), ":%s", display); + setenv("DISPLAY", buf, TRUE); + } + + /* Do the fork-twice trick to avoid having to reap zombies */ + child1 = fork(); + switch (child1) { + case -1: /* error */ + break; - case 0: /* child1 */ - child2 = fork(); + case 0: /* child1 */ + child2 = fork(); - switch (child2) { - int max_files, i; - char buf[1024], *temp; - - case -1: /* error */ - _exit(1); - - case 0: /* child2 */ - /* close all open files except for standard streams */ - max_files = sysconf(_SC_OPEN_MAX); - for (i = 3; i < max_files; i++) close(i); - - /* ensure stdin is on /dev/null */ - close(0); - open("/dev/null", O_RDONLY); - - /* Setup environment */ - temp = getenv("DISPLAY"); - if (xquartz_resetenv_display || temp == NULL || temp[0] == 0) { - snprintf(buf, sizeof(buf), ":%s", display); - setenv("DISPLAY", buf, TRUE); - } - - execvp(argv[0], (char **const) argv); - - _exit(2); - - default: /* parent (child1) */ - _exit(0); - } - break; + switch (child2) { + int max_files, i; + + case -1: /* error */ + _exit(1); + + case 0: /* child2 */ + /* close all open files except for standard streams */ + max_files = sysconf(_SC_OPEN_MAX); + for(i = 3; i < max_files; i++) + close(i); + + /* ensure stdin is on /dev/null */ + close(0); + open("/dev/null", O_RDONLY); + + execvp(newargv[0], (char **const) newargv); + _exit(2); + + default: /* parent (child1) */ + _exit(0); + } + break; - default: /* parent */ - waitpid(child1, &status, 0); - } + default: /* parent */ + waitpid(child1, &status, 0); + } } - (void) app_selected:sender diff --git a/hw/xquartz/bundle/X11.sh b/hw/xquartz/bundle/X11.sh new file mode 100755 index 000000000..5e00a8266 --- /dev/null +++ b/hw/xquartz/bundle/X11.sh @@ -0,0 +1,3 @@ +#!/bin/bash --login + +./X11 "${@}" diff --git a/hw/xquartz/bundle/mk_bundke.sh b/hw/xquartz/bundle/mk_bundke.sh index 0b2a14433..5c5733abf 100755 --- a/hw/xquartz/bundle/mk_bundke.sh +++ b/hw/xquartz/bundle/mk_bundke.sh @@ -20,6 +20,9 @@ install -m 644 Resources/X11.icns ${BUNDLE_ROOT}/Contents/Resources install -m 644 Info.plist ${BUNDLE_ROOT}/Contents install -m 644 PkgInfo ${BUNDLE_ROOT}/Contents +mkdir -p ${BUNDLE_ROOT}/Contents/MacOS +install -m 755 X11.sh ${BUNDLE_ROOT}/Contents/MacOS + if [[ $(id -u) == 0 ]] ; then chown -R root:admin ${BUNDLE_ROOT} fi diff --git a/hw/xquartz/mach-startup/bundle-main.c b/hw/xquartz/mach-startup/bundle-main.c index 6b48c132d..7677a9a93 100644 --- a/hw/xquartz/mach-startup/bundle-main.c +++ b/hw/xquartz/mach-startup/bundle-main.c @@ -529,22 +529,39 @@ int main(int argc, char **argv, char **envp) { return EXIT_SUCCESS; } - -static int execute(const char *command) { - const char *newargv[7]; - const char **s; - newargv[0] = "/usr/bin/login"; - newargv[1] = "-fp"; - newargv[2] = getlogin(); - newargv[3] = command_from_prefs("login_shell", DEFAULT_SHELL); - newargv[4] = "-c"; - newargv[5] = command; - newargv[6] = NULL; +static int execute(const char *command) { + char newcommand[1024]; + char *newargv[1024]; + size_t newargc; + char *s; + char **p; + + if(strlen(command) > 1023) { + fprintf(stderr, "Error: command is too long: %s\n", command); + return 1; + } + + strlcpy(newcommand, command, 1024); + + for(newargc=0, s=newcommand; *s; newargc++) { + for(; *s && *s == ' '; s++); + if(!*s) + break; + + newargv[newargc] = s; + for(; *s && *s != ' '; s++); + + if(*s) { + *s='\0'; + s++; + } + } + newargv[newargc] = NULL; fprintf(stderr, "X11.app: Launching %s:\n", command); - for(s=newargv; *s; s++) { - fprintf(stderr, "\targv[%ld] = %s\n", (long int)(s - newargv), *s); + for(p=newargv; *p; p++) { + fprintf(stderr, "\targv[%ld] = %s\n", (long int)(p - newargv), *p); } execvp (newargv[0], (char * const *) newargv); -- cgit v1.2.3