summaryrefslogtreecommitdiff
path: root/hw/xquartz/mach-startup/bundle-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xquartz/mach-startup/bundle-main.c')
-rw-r--r--hw/xquartz/mach-startup/bundle-main.c97
1 files changed, 83 insertions, 14 deletions
diff --git a/hw/xquartz/mach-startup/bundle-main.c b/hw/xquartz/mach-startup/bundle-main.c
index fd70f26ed..e887c469d 100644
--- a/hw/xquartz/mach-startup/bundle-main.c
+++ b/hw/xquartz/mach-startup/bundle-main.c
@@ -31,6 +31,10 @@
#include <CoreFoundation/CoreFoundation.h>
#include <AvailabilityMacros.h>
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
#include <X11/Xlib.h>
#include <unistd.h>
#include <stdio.h>
@@ -44,6 +48,7 @@
#include <sys/un.h>
#include <sys/time.h>
+#include <fcntl.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
@@ -75,7 +80,7 @@ const char *__crashreporter_info__base = "X.Org X Server " XSERVER_VERSION " Bui
char __crashreporter_info__buf[4096];
char *__crashreporter_info__ = __crashreporter_info__buf;
-static char *server_bootstrap_name = "org.x.X11";
+static char *server_bootstrap_name = LAUNCHD_ID_PREFIX".X11";
#define DEBUG 1
@@ -322,7 +327,7 @@ kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
char **_envp = alloca((envpCnt + 1) * sizeof(char *));
size_t i;
- /* If we didn't get handed a launchd DISPLAY socket, we shoul
+ /* If we didn't get handed a launchd DISPLAY socket, we should
* unset DISPLAY or we can run into problems with pbproxy
*/
if(!launchd_socket_handed_off)
@@ -350,7 +355,7 @@ kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
return KERN_FAILURE;
}
-int startup_trigger(int argc, char **argv, char **envp) {
+static int startup_trigger(int argc, char **argv, char **envp) {
Display *display;
const char *s;
@@ -387,9 +392,9 @@ int startup_trigger(int argc, char **argv, char **envp) {
kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp);
if (kr != KERN_SUCCESS) {
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- fprintf(stderr, "bootstrap_look_up(): %s\n", bootstrap_strerror(kr));
+ fprintf(stderr, "bootstrap_look_up(%s): %s\n", server_bootstrap_name, bootstrap_strerror(kr));
#else
- fprintf(stderr, "bootstrap_look_up(): %ul\n", (unsigned long)kr);
+ fprintf(stderr, "bootstrap_look_up(%s): %ul\n", server_bootstrap_name, (unsigned long)kr);
#endif
exit(EXIT_FAILURE);
}
@@ -444,9 +449,10 @@ static void ensure_path(const char *dir) {
}
}
-static void setup_env() {
+static void setup_env(void) {
char *temp;
const char *pds = NULL;
+ const char *disp = getenv("DISPLAY");
/* Pass on our prefs domain to startx and its inheritors (mainly for
* quartz-wm and the Xquartz stub's MachIPC)
@@ -463,12 +469,40 @@ static void setup_env() {
}
}
}
+ /* We need to unset DISPLAY if it is not our socket */
+ if(disp) {
+ if(!pds) {
+ /* If we can't detet our id, we are beyond hope and need to just
+ * revert to the non-launchd startup */
+ unsetenv("DISPLAY");
+ } else {
+ /* s = basename(disp) */
+ const char *d, *s;
+ for(s = NULL, d = disp; *d; d++) {
+ if(*d == '/')
+ s = d + 1;
+ }
- /* If we're not org.x.X11, we want to unset DISPLAY, so we don't
- * use the launchd DISPLAY socket.
- */
- if(pds == NULL || strcmp(pds, "org.x.X11") != 0)
- unsetenv("DISPLAY");
+ if(s && *s) {
+ size_t pds_len = strlen(pds);
+ temp = (char *)malloc(sizeof(char) * pds_len);
+ if(!temp) {
+ fprintf(stderr, "Memory allocation error creating space for socket name test.\n");
+ }
+ strlcpy(temp, pds, pds_len - 3);
+ strlcat(temp, ":0", pds_len);
+
+ if(strcmp(temp, s) != 0) {
+ /* If we don't have a match, unset it. */
+ unsetenv("DISPLAY");
+ }
+ free(temp);
+ } else {
+ /* The DISPLAY environment variable is not formatted like a launchd socket, so reset. */
+ unsetenv("DISPLAY");
+ }
+ }
+ }
/* Make sure PATH is right */
ensure_path(X11BINDIR);
@@ -514,8 +548,43 @@ int main(int argc, char **argv, char **envp) {
* thread handle it.
*/
if(!listenOnly) {
- if(fork() == 0) {
- return startup_trigger(argc, argv, envp);
+ pid_t child1, child2;
+ int status;
+
+ /* Do the fork-twice trick to avoid having to reap zombies */
+ child1 = fork();
+ switch (child1) {
+ case -1: /* error */
+ break;
+
+ case 0: /* child1 */
+ child2 = fork();
+
+ switch (child2) {
+ int max_files, i;
+
+ case -1: /* error */
+ break;
+
+ 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);
+
+ return startup_trigger(argc, argv, envp);
+
+ default: /* parent (child1) */
+ _exit(0);
+ }
+ break;
+
+ default: /* parent */
+ waitpid(child1, &status, 0);
}
}
@@ -523,7 +592,7 @@ int main(int argc, char **argv, char **envp) {
fprintf(stderr, "Waiting for startup parameters via Mach IPC.\n");
kr = mach_msg_server(mach_startup_server, mxmsgsz, mp, 0);
if (kr != KERN_SUCCESS) {
- fprintf(stderr, "org.x.X11(mp): %s\n", mach_error_string(kr));
+ fprintf(stderr, "%s.X11(mp): %s\n", LAUNCHD_ID_PREFIX, mach_error_string(kr));
return EXIT_FAILURE;
}