XQuartz: Starting to work on the new Mach IPC startup stuff for better launchd, ApplicationServices, and Dock support
(cherry picked from commit 9b67fca9b7d3050d3d5582a5210270db7eb2ed05)
This commit is contained in:
		
							parent
							
								
									04211c3532
								
							
						
					
					
						commit
						a7800d9355
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,9 +50,143 @@
 | 
			
		|||
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;
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
		Loading…
	
		Reference in New Issue