summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Huddleston <jeremyhu@freedesktop.org>2008-05-09 16:44:31 -0700
committerJeremy Huddleston <jeremyhu@freedesktop.org>2008-05-12 10:42:12 -0700
commita7800d9355377ac02833613c2ffc2423beec9970 (patch)
treed159a40a035caf8b11dd079dff6deb2176dda477
parent04211c3532ca078420e3745a5eac3d9de120bc32 (diff)
XQuartz: Starting to work on the new Mach IPC startup stuff for better launchd, ApplicationServices, and Dock support
(cherry picked from commit 9b67fca9b7d3050d3d5582a5210270db7eb2ed05)
-rw-r--r--.gitignore4
-rw-r--r--hw/xquartz/mach-startup/Makefile.am28
-rw-r--r--hw/xquartz/mach-startup/bundle-main.c157
-rw-r--r--hw/xquartz/mach-startup/mach_startup.defs41
-rw-r--r--hw/xquartz/mach-startup/mach_startup_types.h8
5 files changed, 232 insertions, 6 deletions
diff --git a/.gitignore b/.gitignore
index d6d7adfd1..13d5de4fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -278,6 +278,10 @@ hw/xprint/doc/Xprt.1x
hw/xprint/doc/Xprt.man
hw/xprint/dpmsstubs-wrapper.c
hw/xprint/miinitext-wrapper.c
+hw/xquartz/mach-startup/mach_startup.h
+hw/xquartz/mach-startup/mach_startupServer.c
+hw/xquartz/mach-startup/mach_startupServer.h
+hw/xquartz/mach-startup/mach_startupUser.c
hw/xquartz/mach-startup/X11
hw/xquartz/mach-startup/Xquartz
hw/xquartz/doc/Xquartz.1
diff --git a/hw/xquartz/mach-startup/Makefile.am b/hw/xquartz/mach-startup/Makefile.am
index 966871126..ee2cbfe9e 100644
--- a/hw/xquartz/mach-startup/Makefile.am
+++ b/hw/xquartz/mach-startup/Makefile.am
@@ -5,9 +5,13 @@ AM_CPPFLAGS = \
x11appdir = $(APPLE_APPLICATIONS_DIR)/X11.app/Contents/MacOS
x11app_PROGRAMS = X11
-X11_SOURCES = \
+dist_X11_SOURCES = \
bundle-main.c
+nodist_X11_SOURCES = \
+ mach_startupServer.c \
+ mach_startupUser.c
+
X11_LDADD = \
$(top_builddir)/hw/xquartz/libXquartz.la \
$(top_builddir)/hw/xquartz/xpr/libXquartzXpr.la \
@@ -27,8 +31,28 @@ X11_LDFLAGS = \
bin_PROGRAMS = Xquartz
-Xquartz_SOURCES = \
+dist_Xquartz_SOURCES = \
stub.c
+nodist_Xquartz_SOURCES = \
+ mach_startupUser.c
+
Xquartz_LDFLAGS = \
-Wl,-framework,CoreServices
+
+BUILT_SOURCES = \
+ mach_startupServer.c \
+ mach_startupUser.c \
+ mach_startupServer.h \
+ mach_startup.h
+
+CLEANFILES = \
+ $(BUILT_SOURCES)
+
+$(BUILT_SOURCES): mach_startup.defs
+ mig -sheader mach_startupServer.h mach_startup.defs
+
+EXTRA_DIST = \
+ mach_startup.defs \
+ mach_startup_types.h
+
diff --git a/hw/xquartz/mach-startup/bundle-main.c b/hw/xquartz/mach-startup/bundle-main.c
index 042fa3ab8..24b67d871 100644
--- a/hw/xquartz/mach-startup/bundle-main.c
+++ b/hw/xquartz/mach-startup/bundle-main.c
@@ -33,9 +33,16 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <pthread.h>
#include <CoreFoundation/CoreFoundation.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+#include "mach_startup.h"
+#include "mach_startupServer.h"
+
#define DEFAULT_CLIENT "/usr/X11/bin/xterm"
#define DEFAULT_STARTX "/usr/X11/bin/startx"
#define DEFAULT_SHELL "/bin/sh"
@@ -43,12 +50,146 @@
static int execute(const char *command);
static char *command_from_prefs(const char *key, const char *default_value);
+/* This is in quartzStartup.c */
int server_main(int argc, char **argv, char **envp);
+struct arg {
+ int argc;
+ char **argv;
+ char **envp;
+};
+
+/*** Mach-O IPC Stuffs ***/
+
+union MaxMsgSize {
+ union __RequestUnion__mach_startup_subsystem req;
+ union __ReplyUnion__mach_startup_subsystem rep;
+};
+
+kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
+ mach_msg_type_number_t argvCnt,
+ string_array_t envp,
+ mach_msg_type_number_t envpCnt) {
+ if(server_main(argvCnt, argv, envp) == 0)
+ return KERN_SUCCESS;
+ else
+ return KERN_FAILURE;
+}
+
+kern_return_t do_exit(mach_port_t port, int value) {
+ exit(value);
+}
+
+static mach_port_t checkin_or_register(char *bname) {
+ kern_return_t kr;
+ mach_port_t mp;
+
+ /* If we're started by launchd or the old mach_init */
+ kr = bootstrap_check_in(bootstrap_port, bname, &mp);
+ if (kr == KERN_SUCCESS)
+ return mp;
+
+ /* We probably were not started by launchd or the old mach_init */
+ kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "mach_port_allocate(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "mach_port_insert_right(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ kr = bootstrap_register(bootstrap_port, bname, mp);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "bootstrap_register(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ return mp;
+}
+
+/*** Pthread Magics ***/
+static pthread_t create_thread(void *func, void *arg) {
+ pthread_attr_t attr;
+ pthread_t tid;
+
+ pthread_attr_init (&attr);
+ pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create (&tid, &attr, func, arg);
+ pthread_attr_destroy (&attr);
+
+ return tid;
+}
+
+/*** Main ***/
+static int execute(const char *command);
+static char *command_from_prefs(const char *key, const char *default_value);
+
+#ifdef NEW_LAUNCH_METHOD
+static void startup_trigger_thread(void *arg) {
+ struct arg args = *((struct arg *)arg);
+ free(arg);
+ startup_trigger(args.argc, args.argv, args.envp);
+}
+
int main(int argc, char **argv, char **envp) {
+ BOOL listenOnly = FALSE;
+ int i;
+
+ for(i=1; i < argc; i++) {
+ if(!strcmp(argv[i], "--listenonly")) {
+ listenOnly = TRUE;
+ break;
+ }
+ }
+
+ /* Check if we need to do something other than listen, and make another
+ * thread handle it.
+ */
+ if(!listenOnly) {
+ struct arg *args = (struct arg*)malloc(sizeof(struct arg));
+ if(!args)
+ FatalError("Could not allocate memory.\n");
+
+ args->argc = argc;
+ args->argv = argv;
+ args->envp = envp;
+
+ create_thread(startup_trigger_thread, args);
+ } else {
+ /* TODO: This should actually fall through rather than be the else
+ * case once we figure out how to get the stub to pass the
+ * file descriptor. For now, we only listen if we are explicitly
+ * told to.
+ */
+
+ mach_msg_size_t mxmsgsz = sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE;
+ mach_port_t mp = checkin_or_register(SERVER_BOOTSTRAP_NAME);
+ kern_return_t kr;
+
+ /* Main event loop */
+ kr = mach_msg_server(mach_startup_server, mxmsgsz, mp, 0);
+ if (kr != KERN_SUCCESS) {
+ asl_log(NULL, NULL, ASL_LEVEL_ERR,
+ "org.x.X11(mp): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int startup_trigger(int argc, char **argv, char **envp) {
+#else
+int main(int argc, char **argv, char **envp) {
+#endif
Display *display;
const char *s;
-
+
size_t i;
fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
for(i=0; i < argc; i++) {
@@ -57,7 +198,15 @@ int main(int argc, char **argv, char **envp) {
/* Take care of the case where we're called like a normal DDX */
if(argc > 1 && argv[1][0] == ':') {
- exit(server_main(argc, argv, envp));
+#ifdef NEW_LAUNCH_METHOD
+ /* We need to count envp */
+ int envpc;
+ for(envpc=0; envp[envpc]; envpc++);
+
+ return start_x11_server(argc, argv, envp, envpc);
+#else
+ return server_main(argc, argv, envp);
+#endif
}
/* If we have a process serial number and it's our only arg, act as if
@@ -70,7 +219,7 @@ int main(int argc, char **argv, char **envp) {
fprintf(stderr, "X11.app: Closing the display and sleeping for 2s to allow the X server to start up.\n");
/* Could open the display, start the launcher */
XCloseDisplay(display);
-
+
/* Give 2 seconds for the server to start...
* TODO: *Really* fix this race condition
*/
@@ -78,7 +227,7 @@ int main(int argc, char **argv, char **envp) {
return execute(command_from_prefs("app_to_run", DEFAULT_CLIENT));
}
}
-
+
/* Start the server */
if((s = getenv("DISPLAY"))) {
fprintf(stderr, "X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);
diff --git a/hw/xquartz/mach-startup/mach_startup.defs b/hw/xquartz/mach-startup/mach_startup.defs
new file mode 100644
index 000000000..83b31b7c0
--- /dev/null
+++ b/hw/xquartz/mach-startup/mach_startup.defs
@@ -0,0 +1,41 @@
+/* Copyright (c) 2008 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above
+ * copyright holders shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization.
+ */
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+import "mach_startup_types.h";
+
+subsystem mach_startup 1000;
+serverprefix do_;
+
+type string_array_t = array[] of c_string[1024];
+
+routine start_x11_server(
+ port : mach_port_t;
+ argv : string_array_t;
+ envp : string_array_t);
diff --git a/hw/xquartz/mach-startup/mach_startup_types.h b/hw/xquartz/mach-startup/mach_startup_types.h
new file mode 100644
index 000000000..03939af97
--- /dev/null
+++ b/hw/xquartz/mach-startup/mach_startup_types.h
@@ -0,0 +1,8 @@
+#ifndef _MACH_STARTUP_TYPES_H_
+#define _MACH_STARTUP_TYPES_H_
+
+#define SERVER_BOOTSTRAP_NAME "org.x.X11"
+
+typedef char ** string_array_t;
+
+#endif