Darwin: Combine launcher and server X11.app

This should hopefully eliminate confusion some people have over which X11.app is which.
Now BOTH are in /A/U/X11.app and we intelligently determine whether to execute our app_to_run
or launch the server.  If arguments are given, we launch the server.  Otherwise if we can
connect to an X DISPLAY, we execute app_to_run.  Otherwise, we launch the server.

(cherry picked from commit e7026216cc)
This commit is contained in:
Jeremy Huddleston 2007-12-03 20:20:05 -08:00
parent 678f786715
commit f8d7729df3
12 changed files with 995 additions and 1215 deletions

View File

@ -2172,7 +2172,6 @@ hw/xnest/Makefile
hw/xwin/Makefile
hw/darwin/Makefile
hw/darwin/apple/Makefile
hw/darwin/launcher/Makefile
hw/darwin/quartz/Makefile
hw/darwin/quartz/xpr/Makefile
hw/kdrive/Makefile

View File

@ -6,7 +6,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/miext/rootless
if X11APP
X11APP_SUBDIRS = apple launcher
X11APP_SUBDIRS = apple
endif
SUBDIRS = quartz utils $(X11APP_SUBDIRS)

View File

@ -6,15 +6,20 @@ x11app:
xcodebuild CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" ARCHS="$(X11APP_ARCHS)"
install-data-hook:
xcodebuild install DSTROOT=$(DESTDIR) INSTALL_PATH=$(prefix) DEPLOYMENT_LOCATION=YES SKIP_INSTALL=NO ARCHS="$(X11APP_ARCHS)"
xcodebuild install DSTROOT="/$(DESTDIR)" INSTALL_PATH="$(APPLE_APPLICATIONS_DIR)" DEPLOYMENT_LOCATION=YES SKIP_INSTALL=NO ARCHS="$(X11APP_ARCHS)"
$(MKDIR_P) "$(DESTDIR)/System/Library/LaunchAgents/"
$(INSTALL) org.x.X11.plist "$(DESTDIR)/System/Library/LaunchAgents/"
clean-local:
rm -rf build
EXTRA_DIST = \
org.x.X11.plist \
Info.plist \
X11.icns \
bundle-main.c \
launcher-main.c \
server-main.c \
English.lproj/InfoPlist.strings \
English.lproj/Localizable.strings \
English.lproj/main.nib/classes.nib \

View File

@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
3F5E1BE00D04BF110020CA24 /* launcher-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 3F5E1BDE0D04BF110020CA24 /* launcher-main.c */; };
3F5E1BE10D04BF110020CA24 /* server-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 3F5E1BDF0D04BF110020CA24 /* server-main.c */; };
527F24190B5D938C007840A7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
527F241A0B5D938C007840A7 /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = 02345980000FD03B11CA0E72 /* main.nib */; };
527F241B0B5D938C007840A7 /* X11.icns in Resources */ = {isa = PBXBuildFile; fileRef = 50459C5F038587C60ECA21EC /* X11.icns */; };
@ -20,6 +22,8 @@
/* Begin PBXFileReference section */
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1870340FFE93FCAF11CA0CD7 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/main.nib; sourceTree = "<group>"; };
3F5E1BDE0D04BF110020CA24 /* launcher-main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "launcher-main.c"; sourceTree = "<group>"; };
3F5E1BDF0D04BF110020CA24 /* server-main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "server-main.c"; sourceTree = "<group>"; };
50459C5F038587C60ECA21EC /* X11.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = X11.icns; sourceTree = "<group>"; };
50EE2AB703849F0B0ECA21EC /* bundle-main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "bundle-main.c"; sourceTree = "<group>"; };
50F4F0A7039D6ACA0E82C0CB /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
@ -65,6 +69,8 @@
20286C2AFDCF999611CA2CEA /* Sources */ = {
isa = PBXGroup;
children = (
3F5E1BDE0D04BF110020CA24 /* launcher-main.c */,
3F5E1BDF0D04BF110020CA24 /* server-main.c */,
50EE2AB703849F0B0ECA21EC /* bundle-main.c */,
);
name = Sources;
@ -133,7 +139,6 @@
mainGroup = 20286C29FDCF999611CA2CEA /* X11 */;
projectDirPath = "";
projectRoot = "";
shouldCheckCompatibility = 1;
targets = (
527F24160B5D938C007840A7 /* X11 */,
);
@ -171,6 +176,8 @@
buildActionMask = 2147483647;
files = (
527F241D0B5D938C007840A7 /* bundle-main.c in Sources */,
3F5E1BE00D04BF110020CA24 /* launcher-main.c in Sources */,
3F5E1BE10D04BF110020CA24 /* server-main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -1,6 +1,7 @@
/* bundle-main.c -- X server launcher
/* main.c -- X application launcher
Copyright (c) 2002-2007 Apple Inc. All rights reserved.
Copyright (c) 2007 Jeremy Huddleston
Copyright (c) 2007 Apple Inc
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
@ -25,880 +26,57 @@
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.
Parts of this file are derived from xdm, which has this copyright:
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear in
supporting documentation.
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 OPEN GROUP 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 of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group. */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <time.h>
#include <sys/wait.h>
#include <setjmp.h>
#include <sys/ioctl.h>
prior written authorization. */
#include <X11/Xlib.h>
#include <X11/Xauth.h>
#include <xcb/xcb.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
int launcher_main(int argc, char **argv);
int server_main(int argc, char **argv);
#define X_SERVER "/usr/X11/bin/Xquartz"
#define XTERM_PATH "/usr/X11/bin/xterm"
#define WM_PATH "/usr/bin/quartz-wm"
#define DEFAULT_XINITRC "/usr/X11/lib/X11/xinit/xinitrc"
#define DEFAULT_PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/X11/bin"
/* what xinit does */
#ifndef SHELL
# define SHELL "sh"
#endif
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE 1
#define MAX_DISPLAYS 64
static int server_pid = -1, client_pid = -1;
static int xinit_kills_server = FALSE;
static jmp_buf exit_continuation;
static const char *server_name = NULL;
static Display *server_dpy;
static char *auth_file;
typedef struct addr_list_struct addr_list;
struct addr_list_struct {
addr_list *next;
Xauth auth;
};
static addr_list *addresses;
/* Utility functions. */
/* Return the current host name. Matches what Xlib does. */
static char *
host_name (void)
{
#ifdef NEED_UTSNAME
static struct utsname name;
uname(&name);
return name.nodename;
#else
static char buf[100];
gethostname(buf, sizeof(buf));
return buf;
#endif
}
static int
read_boolean_pref (CFStringRef name, int default_)
{
int value;
Boolean ok;
value = CFPreferencesGetAppBooleanValue (name,
CFSTR ("com.apple.x11"), &ok);
return ok ? value : default_;
}
static inline int
binary_equal (const void *a, const void *b, int length)
{
return memcmp (a, b, length) == 0;
}
static inline void *
binary_dup (const void *a, int length)
{
void *b = malloc (length);
if (b != NULL)
memcpy (b, a, length);
return b;
}
static inline void
binary_free (void *data, int length)
{
if (data != NULL)
free (data);
}
/* Functions for managing the authentication entries. */
/* Returns true if something matching AUTH is in our list of auth items */
static int
check_auth_item (Xauth *auth)
{
addr_list *a;
for (a = addresses; a != NULL; a = a->next)
{
if (a->auth.family == auth->family
&& a->auth.address_length == auth->address_length
&& binary_equal (a->auth.address, auth->address, auth->address_length)
&& a->auth.number_length == auth->number_length
&& binary_equal (a->auth.number, auth->number, auth->number_length)
&& a->auth.name_length == auth->name_length
&& binary_equal (a->auth.name, auth->name, auth->name_length))
{
return TRUE;
}
int main(int argc, char **argv) {
Display *display;
fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
int i;
for(i=0; i < argc; i++) {
fprintf(stderr, "\targv[%d] = %s\n", i, argv[i]);
}
return FALSE;
}
/* Add one item to our list of auth items. */
static void
add_auth_item (Xauth *auth)
{
addr_list *a = malloc (sizeof (addr_list));
a->auth.family = auth->family;
a->auth.address_length = auth->address_length;
a->auth.address = binary_dup (auth->address, auth->address_length);
a->auth.number_length = auth->number_length;
a->auth.number = binary_dup (auth->number, auth->number_length);
a->auth.name_length = auth->name_length;
a->auth.name = binary_dup (auth->name, auth->name_length);
a->auth.data_length = auth->data_length;
a->auth.data = binary_dup (auth->data, auth->data_length);
a->next = addresses;
addresses = a;
}
/* Free all allocated auth items. */
static void
free_auth_items (void)
{
addr_list *a;
while ((a = addresses) != NULL)
{
addresses = a->next;
binary_free (a->auth.address, a->auth.address_length);
binary_free (a->auth.number, a->auth.number_length);
binary_free (a->auth.name, a->auth.name_length);
binary_free (a->auth.data, a->auth.data_length);
free (a);
}
}
/* Add the unix domain auth item. */
static void
define_local (Xauth *auth)
{
char *host = host_name ();
#ifdef DEBUG
fprintf (stderr, "x11: hostname is %s\n", host);
#endif
auth->family = FamilyLocal;
auth->address_length = strlen (host);
auth->address = host;
add_auth_item (auth);
}
/* Add the tcp auth item. */
static void
define_named (Xauth *auth, const char *name)
{
struct ifaddrs *addrs, *ptr;
if (getifaddrs (&addrs) != 0)
return;
for (ptr = addrs; ptr != NULL; ptr = ptr->ifa_next)
{
if (ptr->ifa_addr->sa_family != AF_INET)
continue;
auth->family = FamilyInternet;
auth->address_length = sizeof (struct in_addr);
auth->address = (char *) &(((struct sockaddr_in *) ptr->ifa_addr)->sin_addr);
#ifdef DEBUG
fprintf (stderr, "x11: ipaddr is %d.%d.%d.%d\n",
(unsigned char) auth->address[0],
(unsigned char) auth->address[1],
(unsigned char) auth->address[2],
(unsigned char) auth->address[3]);
#endif
add_auth_item (auth);
}
freeifaddrs (addrs);
}
/* Parse the display number from NAME and add it to AUTH. */
static void
set_auth_number (Xauth *auth, const char *name)
{
char *colon;
char *dot, *number;
colon = strrchr(name, ':');
if (colon != NULL)
{
colon++;
dot = strchr(colon, '.');
if (dot != NULL)
auth->number_length = dot - colon;
else
auth->number_length = strlen (colon);
number = malloc (auth->number_length + 1);
if (number != NULL)
{
strncpy (number, colon, auth->number_length);
number[auth->number_length] = '\0';
}
else
{
auth->number_length = 0;
}
auth->number = number;
}
}
/* Put 128 bits of random data into DATA. If possible, it will be "high
quality" */
static int
generate_mit_magic_cookie (char data[16])
{
int fd, ret, i;
long *ldata = (long *) data;
fd = open ("/dev/random", O_RDONLY);
if (fd > 0) {
ret = read (fd, data, 16);
close (fd);
if (ret == 16) return TRUE;
}
/* fall back to the usual crappy rng */
srand48 (getpid () ^ time (NULL));
for (i = 0; i < 4; i++)
ldata[i] = lrand48 ();
return TRUE;
}
/* Create the keys we'll be using for the display named NAME. */
static int
make_auth_keys (const char *name)
{
Xauth auth;
char key[16];
if (auth_file == NULL)
return FALSE;
auth.name = "MIT-MAGIC-COOKIE-1";
auth.name_length = strlen (auth.name);
if (!generate_mit_magic_cookie (key))
{
auth_file = NULL;
return FALSE;
}
auth.data = key;
auth.data_length = 16;
set_auth_number (&auth, name);
define_named (&auth, host_name ());
define_local (&auth);
free (auth.number);
return TRUE;
}
/* If ADD-ENTRIES is true, merge our auth entries into the existing
Xauthority file. If ADD-ENTRIES is false, remove our entries. */
static int
write_auth_file (int add_entries)
{
char *home, newname[1024];
int fd, ret;
FILE *new_fh, *old_fh;
addr_list *addr;
Xauth *auth;
if (auth_file == NULL)
return FALSE;
home = getenv ("HOME");
if (home == NULL)
{
auth_file = NULL;
return FALSE;
}
snprintf (newname, sizeof (newname), "%s/.XauthorityXXXXXX", home);
mktemp (newname);
if (XauLockAuth (auth_file, 1, 2, 10) != LOCK_SUCCESS)
{
/* FIXME: do something here? */
auth_file = NULL;
return FALSE;
}
fd = open (newname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd >= 0)
{
new_fh = fdopen (fd, "w");
if (new_fh != NULL)
{
if (add_entries)
{
for (addr = addresses; addr != NULL; addr = addr->next)
{
XauWriteAuth (new_fh, &addr->auth);
}
}
old_fh = fopen (auth_file, "r");
if (old_fh != NULL)
{
while ((auth = XauReadAuth (old_fh)) != NULL)
{
if (!check_auth_item (auth))
XauWriteAuth (new_fh, auth);
XauDisposeAuth (auth);
}
fclose (old_fh);
}
fclose (new_fh);
unlink (auth_file);
ret = rename (newname, auth_file);
if (ret != 0)
auth_file = NULL;
XauUnlockAuth (auth_file);
return ret == 0;
}
close (fd);
}
XauUnlockAuth (auth_file);
auth_file = NULL;
return FALSE;
}
/* Subprocess management functions. */
static int
start_server (char **xargv)
{
int child;
child = fork ();
switch (child)
{
case -1: /* error */
perror ("fork");
return FALSE;
case 0: /* child */
execv (X_SERVER, xargv);
perror ("Couldn't exec " X_SERVER);
_exit (1);
default: /* parent */
server_pid = child;
return TRUE;
}
}
static int
wait_for_server (void)
{
int count = 100;
while (count-- > 0)
{
int status;
server_dpy = XOpenDisplay (server_name);
if (server_dpy != NULL)
return TRUE;
if (waitpid (server_pid, &status, WNOHANG) == server_pid)
return FALSE;
sleep (1);
}
return FALSE;
}
static int
start_client (void)
{
int child;
child = fork();
switch (child) {
char *temp, buf[1024];
case -1: /* error */
perror("fork");
return FALSE;
case 0: /* child */
/* Setup environment */
temp = getenv("DISPLAY");
if (temp != NULL && temp[0] != 0)
setenv("DISPLAY", server_name, TRUE);
temp = getenv("PATH");
if (temp == NULL || temp[0] == 0)
setenv ("PATH", DEFAULT_PATH, TRUE);
else if (strnstr(temp, "/usr/X11/bin", sizeof(temp)) == NULL) {
snprintf(buf, sizeof(buf), "%s:/usr/X11/bin", temp);
setenv("PATH", buf, TRUE);
}
/* First try value of $XINITRC, if set. */
temp = getenv("XINITRC");
if (temp != NULL && temp[0] != 0 && access(temp, R_OK) == 0)
execlp (SHELL, SHELL, temp, NULL);
/* Then look for .xinitrc in user's home directory. */
temp = getenv("HOME");
if (temp != NULL && temp[0] != 0) {
chdir(temp);
snprintf (buf, sizeof (buf), "%s/.xinitrc", temp);
if (access(buf, R_OK) == 0)
execlp(SHELL, SHELL, buf, NULL);
}
/* Then try the default xinitrc in the lib directory. */
if (access(DEFAULT_XINITRC, R_OK) == 0)
execlp(SHELL, SHELL, DEFAULT_XINITRC, NULL);
/* Then fallback to hardcoding an xterm and the window manager. */
// system(XTERM_PATH " &");
execl(WM_PATH, WM_PATH, NULL);
perror("exec");
_exit(1);
default: /* parent */
client_pid = child;
return TRUE;
}
}
static void
sigchld_handler (int sig)
{
int pid, status;
again:
pid = waitpid (WAIT_ANY, &status, WNOHANG);
if (pid > 0)
{
if (pid == server_pid)
{
server_pid = -1;
if (client_pid >= 0)
kill (client_pid, SIGTERM);
}
else if (pid == client_pid)
{
client_pid = -1;
if (server_pid >= 0 && xinit_kills_server)
kill (server_pid, SIGTERM);
}
goto again;
}
if (server_pid == -1 && client_pid == -1)
longjmp (exit_continuation, 1);
signal (SIGCHLD, sigchld_handler);
}
/* Server utilities. */
static Boolean
display_exists_p (int number)
{
char buf[64];
xcb_connection_t *conn;
char *fullname = NULL;
int idisplay, iscreen;
char *conn_auth_name, *conn_auth_data;
int conn_auth_namelen, conn_auth_datalen;
// extern void *_X11TransConnectDisplay ();
// extern void _XDisconnectDisplay ();
/* Since connecting to the display waits for a few seconds if the
display doesn't exist, check for trivial non-existence - if the
socket in /tmp exists or not.. (note: if the socket exists, the
server may still not, so we need to try to connect in that case..) */
sprintf (buf, "/tmp/.X11-unix/X%d", number);
if (access (buf, F_OK) != 0)
return FALSE;
sprintf (buf, ":%d", number);
conn = xcb_connect(buf, NULL);
if (xcb_connection_has_error(conn)) return FALSE;
xcb_disconnect(conn);
return TRUE;
}
/* Monitoring when the system's ip addresses change. */
static Boolean pending_timer;
static void
timer_callback (CFRunLoopTimerRef timer, void *info)
{
pending_timer = FALSE;
/* Update authentication names. Need to write .Xauthority file first
without the existing entries, then again with the new entries.. */
write_auth_file (FALSE);
free_auth_items ();
make_auth_keys (server_name);
write_auth_file (TRUE);
}
/* This function is called when the system's ip addresses may have changed. */
static void
ipaddr_callback (SCDynamicStoreRef store, CFArrayRef changed_keys, void *info)
{
#if DEBUG
if (changed_keys != NULL) {
fprintf (stderr, "x11: changed sc keys: ");
CFShow (changed_keys);
}
#endif
if (auth_file != NULL && !pending_timer)
{
CFRunLoopTimerRef timer;
timer = CFRunLoopTimerCreate (NULL, CFAbsoluteTimeGetCurrent () + 1.0,
0.0, 0, 0, timer_callback, NULL);
CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer,
kCFRunLoopDefaultMode);
CFRelease (timer);
pending_timer = TRUE;
}
}
/* This code adapted from "Living in a Dynamic TCP/IP Environment" technote. */
static Boolean
install_ipaddr_source (void)
{
CFRunLoopSourceRef source = NULL;
SCDynamicStoreContext context = {0};
SCDynamicStoreRef ref;
ref = SCDynamicStoreCreate (NULL,
CFSTR ("AddIPAddressListChangeCallbackSCF"),
ipaddr_callback, &context);
if (ref != NULL)
{
const void *keys[4], *patterns[2];
int i;
keys[0] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
keys[1] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
keys[2] = SCDynamicStoreKeyCreateComputerName (NULL);
keys[3] = SCDynamicStoreKeyCreateHostNames (NULL);
patterns[0] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
patterns[1] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
if (keys[0] != NULL && keys[1] != NULL && keys[2] != NULL
&& keys[3] != NULL && patterns[0] != NULL && patterns[1] != NULL)
{
CFArrayRef key_array, pattern_array;
key_array = CFArrayCreate (NULL, keys, 4, &kCFTypeArrayCallBacks);
pattern_array = CFArrayCreate (NULL, patterns, 2, &kCFTypeArrayCallBacks);
if (key_array != NULL || pattern_array != NULL)
{
SCDynamicStoreSetNotificationKeys (ref, key_array, pattern_array);
source = SCDynamicStoreCreateRunLoopSource (NULL, ref, 0);
}
if (key_array != NULL)
CFRelease (key_array);
if (pattern_array != NULL)
CFRelease (pattern_array);
}
for (i = 0; i < 4; i++)
if (keys[i] != NULL)
CFRelease (keys[i]);
for (i = 0; i < 2; i++)
if (patterns[i] != NULL)
CFRelease (patterns[i]);
CFRelease (ref);
}
if (source != NULL)
{
CFRunLoopAddSource (CFRunLoopGetCurrent (),
source, kCFRunLoopDefaultMode);
CFRelease (source);
}
return source != NULL;
}
/* Entrypoint. */
void
termination_signal_handler (int unused_sig)
{
signal (SIGTERM, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
longjmp (exit_continuation, 1);
}
int
main (int argc, char **argv)
{
char **xargv;
int i, j;
int fd;
xargv = alloca (sizeof (char *) * (argc + 32));
if (!read_boolean_pref (CFSTR ("no_auth"), FALSE))
auth_file = XauFileName ();
/* The standard X11 behaviour is for the server to quit when the first
client exits. But it can be useful for debugging (and to mimic our
behaviour in the beta releases) to not do that. */
xinit_kills_server = read_boolean_pref (CFSTR ("xinit_kills_server"), TRUE);
for (i = 1; i < argc; i++)
{
if (argv[i][0] == ':')
server_name = argv[i];
}
if (server_name == NULL)
{
static char name[8];
/* No display number specified, so search for the first unused.
There's a big old race condition here if two servers start at
the same time, but that's fairly unlikely. We could create
lockfiles or something, but that's seems more likely to cause
problems than the race condition itself.. */
for (i = 0; i < MAX_DISPLAYS; i++)
{
if (!display_exists_p (i))
break;
}
if (i == MAX_DISPLAYS)
{
fprintf (stderr, "%s: couldn't allocate a display number", argv[0]);
exit (1);
}
sprintf (name, ":%d", i);
server_name = name;
}
if (auth_file != NULL)
{
/* Create new Xauth keys and add them to the .Xauthority file */
make_auth_keys (server_name);
write_auth_file (TRUE);
}
/* Construct our new argv */
i = j = 0;
xargv[i++] = argv[j++];
if (auth_file != NULL)
{
xargv[i++] = "-auth";
xargv[i++] = auth_file;
}
/* By default, don't listen on tcp sockets if Xauth is disabled. */
if (read_boolean_pref (CFSTR ("nolisten_tcp"), auth_file == NULL))
{
xargv[i++] = "-nolisten";
xargv[i++] = "tcp";
}
while (j < argc)
{
if (argv[j++][0] != ':')
xargv[i++] = argv[j-1];
}
xargv[i++] = (char *) server_name;
xargv[i++] = NULL;
/* Detach from any controlling terminal and connect stdin to /dev/null */
#ifdef TIOCNOTTY
fd = open ("/dev/tty", O_RDONLY);
if (fd != -1)
{
ioctl (fd, TIOCNOTTY, 0);
close (fd);
}
#endif
fd = open ("/dev/null", O_RDWR, 0);
if (fd >= 0)
{
dup2 (fd, 0);
if (fd > 0)
close (fd);
}
if (!start_server (xargv))
return 1;
if (!wait_for_server ())
{
kill (server_pid, SIGTERM);
return 1;
}
if (!start_client ())
{
kill (server_pid, SIGTERM);
return 1;
}
signal (SIGCHLD, sigchld_handler);
signal (SIGTERM, termination_signal_handler);
signal (SIGHUP, termination_signal_handler);
signal (SIGINT, termination_signal_handler);
signal (SIGQUIT, termination_signal_handler);
if (setjmp (exit_continuation) == 0)
{
if (install_ipaddr_source ())
CFRunLoopRun ();
else
while (1) pause ();
}
signal (SIGCHLD, SIG_IGN);
if (client_pid >= 0) kill (client_pid, SIGTERM);
if (server_pid >= 0) kill (server_pid, SIGTERM);
if (auth_file != NULL)
{
/* Remove our Xauth keys */
write_auth_file (FALSE);
}
free_auth_items ();
return 0;
/* First check if launchd started us */
if(argc == 2 && !strncmp(argv[1], "--launchd", 9)) {
argc--;
argv[1] = argv[0];
argv++;
fprintf(stderr, "X11.app: main(): launchd called us, running server_main()");
return server_main(argc, argv);
}
/* If we have a process serial number and it's our only arg, act as if
* the user double clicked the app bundle: launch app_to_run if possible
*/
if(argc == 1 || (argc == 2 && !strncmp(argv[1], "-psn_", 5))) {
/* Now, try to open a display, if so, run the launcher */
display = XOpenDisplay(NULL);
if(display) {
fprintf(stderr, "X11.app: main(): closing the display");
/* Could open the display, start the launcher */
XCloseDisplay(display);
/* Give 2 seconds for the server to start...
* TODO: *Really* fix this race condition
*/
usleep(2000);
fprintf(stderr, "X11.app: main(): running launcher_main()");
return launcher_main(argc, argv);
}
}
/* Couldn't open the display or we were called with arguments,
* just want to start a server.
*/
fprintf(stderr, "X11.app: main(): running server_main()");
return server_main(argc, argv);
}

View File

@ -35,7 +35,7 @@
#define DEFAULT_APP "/usr/X11/bin/xterm"
int main (int argc, char **argv) {
int launcher_main (int argc, char **argv) {
char *command = DEFAULT_APP;
const char *newargv[7];
int child;

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.x.X11</string>
<key>Program</key>
<string>/Applications/Utilities/X11.app/Contents/MacOS/X11</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Utilities/X11.app/Contents/MacOS/X11</string>
<string>--launchd</string>
</array>
<key>Sockets</key>
<dict>
<key>:0</key>
<dict>
<key>SecureSocketWithKey</key>
<string>DISPLAY</string>
</dict>
</dict>
<key>ServiceIPC</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,904 @@
/* bundle-main.c -- X server launcher
Copyright (c) 2002-2007 Apple Inc. All rights reserved.
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.
Parts of this file are derived from xdm, which has this copyright:
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear in
supporting documentation.
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 OPEN GROUP 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 of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group. */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <time.h>
#include <sys/wait.h>
#include <setjmp.h>
#include <sys/ioctl.h>
#include <X11/Xlib.h>
#include <X11/Xauth.h>
#include <xcb/xcb.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#define X_SERVER "/usr/X11/bin/Xquartz"
#define XTERM_PATH "/usr/X11/bin/xterm"
#define WM_PATH "/usr/bin/quartz-wm"
#define DEFAULT_XINITRC "/usr/X11/lib/X11/xinit/xinitrc"
#define DEFAULT_PATH "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/X11/bin"
/* what xinit does */
#ifndef SHELL
# define SHELL "sh"
#endif
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE 1
#define MAX_DISPLAYS 64
static int server_pid = -1, client_pid = -1;
static int xinit_kills_server = FALSE;
static jmp_buf exit_continuation;
static const char *server_name = NULL;
static Display *server_dpy;
static char *auth_file;
typedef struct addr_list_struct addr_list;
struct addr_list_struct {
addr_list *next;
Xauth auth;
};
static addr_list *addresses;
/* Utility functions. */
/* Return the current host name. Matches what Xlib does. */
static char *
host_name (void)
{
#ifdef NEED_UTSNAME
static struct utsname name;
uname(&name);
return name.nodename;
#else
static char buf[100];
gethostname(buf, sizeof(buf));
return buf;
#endif
}
static int
read_boolean_pref (CFStringRef name, int default_)
{
int value;
Boolean ok;
value = CFPreferencesGetAppBooleanValue (name,
CFSTR ("com.apple.x11"), &ok);
return ok ? value : default_;
}
static inline int
binary_equal (const void *a, const void *b, int length)
{
return memcmp (a, b, length) == 0;
}
static inline void *
binary_dup (const void *a, int length)
{
void *b = malloc (length);
if (b != NULL)
memcpy (b, a, length);
return b;
}
static inline void
binary_free (void *data, int length)
{
if (data != NULL)
free (data);
}
/* Functions for managing the authentication entries. */
/* Returns true if something matching AUTH is in our list of auth items */
static int
check_auth_item (Xauth *auth)
{
addr_list *a;
for (a = addresses; a != NULL; a = a->next)
{
if (a->auth.family == auth->family
&& a->auth.address_length == auth->address_length
&& binary_equal (a->auth.address, auth->address, auth->address_length)
&& a->auth.number_length == auth->number_length
&& binary_equal (a->auth.number, auth->number, auth->number_length)
&& a->auth.name_length == auth->name_length
&& binary_equal (a->auth.name, auth->name, auth->name_length))
{
return TRUE;
}
}
return FALSE;
}
/* Add one item to our list of auth items. */
static void
add_auth_item (Xauth *auth)
{
addr_list *a = malloc (sizeof (addr_list));
a->auth.family = auth->family;
a->auth.address_length = auth->address_length;
a->auth.address = binary_dup (auth->address, auth->address_length);
a->auth.number_length = auth->number_length;
a->auth.number = binary_dup (auth->number, auth->number_length);
a->auth.name_length = auth->name_length;
a->auth.name = binary_dup (auth->name, auth->name_length);
a->auth.data_length = auth->data_length;
a->auth.data = binary_dup (auth->data, auth->data_length);
a->next = addresses;
addresses = a;
}
/* Free all allocated auth items. */
static void
free_auth_items (void)
{
addr_list *a;
while ((a = addresses) != NULL)
{
addresses = a->next;
binary_free (a->auth.address, a->auth.address_length);
binary_free (a->auth.number, a->auth.number_length);
binary_free (a->auth.name, a->auth.name_length);
binary_free (a->auth.data, a->auth.data_length);
free (a);
}
}
/* Add the unix domain auth item. */
static void
define_local (Xauth *auth)
{
char *host = host_name ();
#ifdef DEBUG
fprintf (stderr, "x11: hostname is %s\n", host);
#endif
auth->family = FamilyLocal;
auth->address_length = strlen (host);
auth->address = host;
add_auth_item (auth);
}
/* Add the tcp auth item. */
static void
define_named (Xauth *auth, const char *name)
{
struct ifaddrs *addrs, *ptr;
if (getifaddrs (&addrs) != 0)
return;
for (ptr = addrs; ptr != NULL; ptr = ptr->ifa_next)
{
if (ptr->ifa_addr->sa_family != AF_INET)
continue;
auth->family = FamilyInternet;
auth->address_length = sizeof (struct in_addr);
auth->address = (char *) &(((struct sockaddr_in *) ptr->ifa_addr)->sin_addr);
#ifdef DEBUG
fprintf (stderr, "x11: ipaddr is %d.%d.%d.%d\n",
(unsigned char) auth->address[0],
(unsigned char) auth->address[1],
(unsigned char) auth->address[2],
(unsigned char) auth->address[3]);
#endif
add_auth_item (auth);
}
freeifaddrs (addrs);
}
/* Parse the display number from NAME and add it to AUTH. */
static void
set_auth_number (Xauth *auth, const char *name)
{
char *colon;
char *dot, *number;
colon = strrchr(name, ':');
if (colon != NULL)
{
colon++;
dot = strchr(colon, '.');
if (dot != NULL)
auth->number_length = dot - colon;
else
auth->number_length = strlen (colon);
number = malloc (auth->number_length + 1);
if (number != NULL)
{
strncpy (number, colon, auth->number_length);
number[auth->number_length] = '\0';
}
else
{
auth->number_length = 0;
}
auth->number = number;
}
}
/* Put 128 bits of random data into DATA. If possible, it will be "high
quality" */
static int
generate_mit_magic_cookie (char data[16])
{
int fd, ret, i;
long *ldata = (long *) data;
fd = open ("/dev/random", O_RDONLY);
if (fd > 0) {
ret = read (fd, data, 16);
close (fd);
if (ret == 16) return TRUE;
}
/* fall back to the usual crappy rng */
srand48 (getpid () ^ time (NULL));
for (i = 0; i < 4; i++)
ldata[i] = lrand48 ();
return TRUE;
}
/* Create the keys we'll be using for the display named NAME. */
static int
make_auth_keys (const char *name)
{
Xauth auth;
char key[16];
if (auth_file == NULL)
return FALSE;
auth.name = "MIT-MAGIC-COOKIE-1";
auth.name_length = strlen (auth.name);
if (!generate_mit_magic_cookie (key))
{
auth_file = NULL;
return FALSE;
}
auth.data = key;
auth.data_length = 16;
set_auth_number (&auth, name);
define_named (&auth, host_name ());
define_local (&auth);
free (auth.number);
return TRUE;
}
/* If ADD-ENTRIES is true, merge our auth entries into the existing
Xauthority file. If ADD-ENTRIES is false, remove our entries. */
static int
write_auth_file (int add_entries)
{
char *home, newname[1024];
int fd, ret;
FILE *new_fh, *old_fh;
addr_list *addr;
Xauth *auth;
if (auth_file == NULL)
return FALSE;
home = getenv ("HOME");
if (home == NULL)
{
auth_file = NULL;
return FALSE;
}
snprintf (newname, sizeof (newname), "%s/.XauthorityXXXXXX", home);
mktemp (newname);
if (XauLockAuth (auth_file, 1, 2, 10) != LOCK_SUCCESS)
{
/* FIXME: do something here? */
auth_file = NULL;
return FALSE;
}
fd = open (newname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd >= 0)
{
new_fh = fdopen (fd, "w");
if (new_fh != NULL)
{
if (add_entries)
{
for (addr = addresses; addr != NULL; addr = addr->next)
{
XauWriteAuth (new_fh, &addr->auth);
}
}
old_fh = fopen (auth_file, "r");
if (old_fh != NULL)
{
while ((auth = XauReadAuth (old_fh)) != NULL)
{
if (!check_auth_item (auth))
XauWriteAuth (new_fh, auth);
XauDisposeAuth (auth);
}
fclose (old_fh);
}
fclose (new_fh);
unlink (auth_file);
ret = rename (newname, auth_file);
if (ret != 0)
auth_file = NULL;
XauUnlockAuth (auth_file);
return ret == 0;
}
close (fd);
}
XauUnlockAuth (auth_file);
auth_file = NULL;
return FALSE;
}
/* Subprocess management functions. */
static int
start_server (char **xargv)
{
int child;
child = fork ();
switch (child)
{
case -1: /* error */
perror ("fork");
return FALSE;
case 0: /* child */
execv (X_SERVER, xargv);
perror ("Couldn't exec " X_SERVER);
_exit (1);
default: /* parent */
server_pid = child;
return TRUE;
}
}
static int
wait_for_server (void)
{
int count = 100;
while (count-- > 0)
{
int status;
server_dpy = XOpenDisplay (server_name);
if (server_dpy != NULL)
return TRUE;
if (waitpid (server_pid, &status, WNOHANG) == server_pid)
return FALSE;
sleep (1);
}
return FALSE;
}
static int
start_client (void)
{
int child;
child = fork();
switch (child) {
char *temp, buf[1024];
case -1: /* error */
perror("fork");
return FALSE;
case 0: /* child */
/* Setup environment */
temp = getenv("DISPLAY");
// if (temp == NULL && temp[0] != 0)
setenv("DISPLAY", server_name, TRUE);
temp = getenv("PATH");
if (temp == NULL || temp[0] == 0)
setenv ("PATH", DEFAULT_PATH, TRUE);
else if (strnstr(temp, "/usr/X11/bin", sizeof(temp)) == NULL) {
snprintf(buf, sizeof(buf), "%s:/usr/X11/bin", temp);
setenv("PATH", buf, TRUE);
}
/* First try value of $XINITRC, if set. */
temp = getenv("XINITRC");
if (temp != NULL && temp[0] != 0 && access(temp, R_OK) == 0)
execlp (SHELL, SHELL, temp, NULL);
/* Then look for .xinitrc in user's home directory. */
temp = getenv("HOME");
if (temp != NULL && temp[0] != 0) {
chdir(temp);
snprintf (buf, sizeof (buf), "%s/.xinitrc", temp);
if (access(buf, R_OK) == 0)
execlp(SHELL, SHELL, buf, NULL);
}
/* Then try the default xinitrc in the lib directory. */
if (access(DEFAULT_XINITRC, R_OK) == 0)
execlp(SHELL, SHELL, DEFAULT_XINITRC, NULL);
/* Then fallback to hardcoding an xterm and the window manager. */
// system(XTERM_PATH " &");
execl(WM_PATH, WM_PATH, NULL);
perror("exec");
_exit(1);
default: /* parent */
client_pid = child;
return TRUE;
}
}
static void
sigchld_handler (int sig)
{
int pid, status;
again:
pid = waitpid (WAIT_ANY, &status, WNOHANG);
if (pid > 0)
{
if (pid == server_pid)
{
server_pid = -1;
if (client_pid >= 0)
kill (client_pid, SIGTERM);
}
else if (pid == client_pid)
{
client_pid = -1;
if (server_pid >= 0 && xinit_kills_server)
kill (server_pid, SIGTERM);
}
goto again;
}
if (server_pid == -1 && client_pid == -1)
longjmp (exit_continuation, 1);
signal (SIGCHLD, sigchld_handler);
}
/* Server utilities. */
static Boolean
display_exists_p (int number)
{
char buf[64];
xcb_connection_t *conn;
char *fullname = NULL;
int idisplay, iscreen;
char *conn_auth_name, *conn_auth_data;
int conn_auth_namelen, conn_auth_datalen;
// extern void *_X11TransConnectDisplay ();
// extern void _XDisconnectDisplay ();
/* Since connecting to the display waits for a few seconds if the
display doesn't exist, check for trivial non-existence - if the
socket in /tmp exists or not.. (note: if the socket exists, the
server may still not, so we need to try to connect in that case..) */
sprintf (buf, "/tmp/.X11-unix/X%d", number);
if (access (buf, F_OK) != 0)
return FALSE;
sprintf (buf, ":%d", number);
conn = xcb_connect(buf, NULL);
if (xcb_connection_has_error(conn)) return FALSE;
xcb_disconnect(conn);
return TRUE;
}
/* Monitoring when the system's ip addresses change. */
static Boolean pending_timer;
static void
timer_callback (CFRunLoopTimerRef timer, void *info)
{
pending_timer = FALSE;
/* Update authentication names. Need to write .Xauthority file first
without the existing entries, then again with the new entries.. */
write_auth_file (FALSE);
free_auth_items ();
make_auth_keys (server_name);
write_auth_file (TRUE);
}
/* This function is called when the system's ip addresses may have changed. */
static void
ipaddr_callback (SCDynamicStoreRef store, CFArrayRef changed_keys, void *info)
{
#if DEBUG
if (changed_keys != NULL) {
fprintf (stderr, "x11: changed sc keys: ");
CFShow (changed_keys);
}
#endif
if (auth_file != NULL && !pending_timer)
{
CFRunLoopTimerRef timer;
timer = CFRunLoopTimerCreate (NULL, CFAbsoluteTimeGetCurrent () + 1.0,
0.0, 0, 0, timer_callback, NULL);
CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer,
kCFRunLoopDefaultMode);
CFRelease (timer);
pending_timer = TRUE;
}
}
/* This code adapted from "Living in a Dynamic TCP/IP Environment" technote. */
static Boolean
install_ipaddr_source (void)
{
CFRunLoopSourceRef source = NULL;
SCDynamicStoreContext context = {0};
SCDynamicStoreRef ref;
ref = SCDynamicStoreCreate (NULL,
CFSTR ("AddIPAddressListChangeCallbackSCF"),
ipaddr_callback, &context);
if (ref != NULL)
{
const void *keys[4], *patterns[2];
int i;
keys[0] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
keys[1] = SCDynamicStoreKeyCreateNetworkGlobalEntity (NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
keys[2] = SCDynamicStoreKeyCreateComputerName (NULL);
keys[3] = SCDynamicStoreKeyCreateHostNames (NULL);
patterns[0] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
patterns[1] = SCDynamicStoreKeyCreateNetworkInterfaceEntity (NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
if (keys[0] != NULL && keys[1] != NULL && keys[2] != NULL
&& keys[3] != NULL && patterns[0] != NULL && patterns[1] != NULL)
{
CFArrayRef key_array, pattern_array;
key_array = CFArrayCreate (NULL, keys, 4, &kCFTypeArrayCallBacks);
pattern_array = CFArrayCreate (NULL, patterns, 2, &kCFTypeArrayCallBacks);
if (key_array != NULL || pattern_array != NULL)
{
SCDynamicStoreSetNotificationKeys (ref, key_array, pattern_array);
source = SCDynamicStoreCreateRunLoopSource (NULL, ref, 0);
}
if (key_array != NULL)
CFRelease (key_array);
if (pattern_array != NULL)
CFRelease (pattern_array);
}
for (i = 0; i < 4; i++)
if (keys[i] != NULL)
CFRelease (keys[i]);
for (i = 0; i < 2; i++)
if (patterns[i] != NULL)
CFRelease (patterns[i]);
CFRelease (ref);
}
if (source != NULL)
{
CFRunLoopAddSource (CFRunLoopGetCurrent (),
source, kCFRunLoopDefaultMode);
CFRelease (source);
}
return source != NULL;
}
/* Entrypoint. */
void
termination_signal_handler (int unused_sig)
{
signal (SIGTERM, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
longjmp (exit_continuation, 1);
}
int
server_main (int argc, char **argv)
{
char **xargv;
int i, j;
int fd;
xargv = alloca (sizeof (char *) * (argc + 32));
if (!read_boolean_pref (CFSTR ("no_auth"), FALSE))
auth_file = XauFileName ();
/* The standard X11 behaviour is for the server to quit when the first
client exits. But it can be useful for debugging (and to mimic our
behaviour in the beta releases) to not do that. */
xinit_kills_server = read_boolean_pref (CFSTR ("xinit_kills_server"), TRUE);
for (i = 1; i < argc; i++)
{
if (argv[i][0] == ':')
server_name = argv[i];
}
if (server_name == NULL)
{
static char name[8];
/* No display number specified, so search for the first unused.
There's a big old race condition here if two servers start at
the same time, but that's fairly unlikely. We could create
lockfiles or something, but that's seems more likely to cause
problems than the race condition itself.. */
for (i = 0; i < MAX_DISPLAYS; i++)
{
if (!display_exists_p (i))
break;
}
if (i == MAX_DISPLAYS)
{
fprintf (stderr, "%s: couldn't allocate a display number", argv[0]);
exit (1);
}
sprintf (name, ":%d", i);
server_name = name;
}
if (auth_file != NULL)
{
/* Create new Xauth keys and add them to the .Xauthority file */
make_auth_keys (server_name);
write_auth_file (TRUE);
}
/* Construct our new argv */
i = j = 0;
xargv[i++] = argv[j++];
if (auth_file != NULL)
{
xargv[i++] = "-auth";
xargv[i++] = auth_file;
}
/* By default, don't listen on tcp sockets if Xauth is disabled. */
if (read_boolean_pref (CFSTR ("nolisten_tcp"), auth_file == NULL))
{
xargv[i++] = "-nolisten";
xargv[i++] = "tcp";
}
while (j < argc)
{
if (argv[j++][0] != ':')
xargv[i++] = argv[j-1];
}
xargv[i++] = (char *) server_name;
xargv[i++] = NULL;
/* Detach from any controlling terminal and connect stdin to /dev/null */
#ifdef TIOCNOTTY
fd = open ("/dev/tty", O_RDONLY);
if (fd != -1)
{
ioctl (fd, TIOCNOTTY, 0);
close (fd);
}
#endif
fd = open ("/dev/null", O_RDWR, 0);
if (fd >= 0)
{
dup2 (fd, 0);
if (fd > 0)
close (fd);
}
if (!start_server (xargv))
return 1;
if (!wait_for_server ())
{
kill (server_pid, SIGTERM);
return 1;
}
if (!start_client ())
{
kill (server_pid, SIGTERM);
return 1;
}
signal (SIGCHLD, sigchld_handler);
signal (SIGTERM, termination_signal_handler);
signal (SIGHUP, termination_signal_handler);
signal (SIGINT, termination_signal_handler);
signal (SIGQUIT, termination_signal_handler);
if (setjmp (exit_continuation) == 0)
{
if (install_ipaddr_source ())
CFRunLoopRun ();
else
while (1) pause ();
}
signal (SIGCHLD, SIG_IGN);
if (client_pid >= 0) kill (client_pid, SIGTERM);
if (server_pid >= 0) kill (server_pid, SIGTERM);
if (auth_file != NULL)
{
/* Remove our Xauth keys */
write_auth_file (FALSE);
}
free_auth_items ();
return 0;
}

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>X11</string>
<key>CFBundleGetInfoString</key>
<string>2.0, Copyright © 2003-2007, Apple Inc.</string>
<key>CFBundleIconFile</key>
<string>X11.icns</string>
<key>CFBundleIdentifier</key>
<string>org.x.X11_launcher</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>X11</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.0</string>
<key>CFBundleSignature</key>
<string>x11l</string>
<key>LSUIElement</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2007, Apple Inc.</string>
</dict>
</plist>

View File

@ -1,18 +0,0 @@
bin_SCRIPTS = x11launcher
.PHONY: x11launcher
x11launcher:
xcodebuild CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" ARCHS="$(X11APP_ARCHS)"
install-data-hook:
xcodebuild install DSTROOT=$(DESTDIR) INSTALL_PATH=$(APPLE_APPLICATIONS_DIR) DEPLOYMENT_LOCATION=YES SKIP_INSTALL=NO ARCHS="$(X11APP_ARCHS)"
clean-local:
rm -rf build
EXTRA_DIST = \
bundle-main.c \
Info.plist \
X11.icns \
X11.xcodeproj/project.pbxproj

Binary file not shown.

View File

@ -1,290 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
527F241B0B5D938C007840A7 /* X11.icns in Resources */ = {isa = PBXBuildFile; fileRef = 50459C5F038587C60ECA21EC /* X11.icns */; };
527F241D0B5D938C007840A7 /* bundle-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 50EE2AB703849F0B0ECA21EC /* bundle-main.c */; };
527F241F0B5D938C007840A7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50F4F0A7039D6ACA0E82C0CB /* CoreFoundation.framework */; };
527F24370B5D9D89007840A7 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 527F24260B5D938C007840A7 /* Info.plist */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
50459C5F038587C60ECA21EC /* X11.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = X11.icns; sourceTree = "<group>"; };
50EE2AB703849F0B0ECA21EC /* bundle-main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "bundle-main.c"; sourceTree = "<group>"; };
50F4F0A7039D6ACA0E82C0CB /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
527F24260B5D938C007840A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
527F24270B5D938C007840A7 /* X11.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = X11.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
527F241E0B5D938C007840A7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
527F241F0B5D938C007840A7 /* CoreFoundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
195DF8CFFE9D517E11CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
527F24270B5D938C007840A7 /* X11.app */,
);
name = Products;
sourceTree = "<group>";
};
20286C29FDCF999611CA2CEA /* X11 */ = {
isa = PBXGroup;
children = (
20286C2AFDCF999611CA2CEA /* Sources */,
20286C2CFDCF999611CA2CEA /* Resources */,
20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */,
195DF8CFFE9D517E11CA2CBB /* Products */,
527F24260B5D938C007840A7 /* Info.plist */,
);
name = X11;
sourceTree = "<group>";
};
20286C2AFDCF999611CA2CEA /* Sources */ = {
isa = PBXGroup;
children = (
50EE2AB703849F0B0ECA21EC /* bundle-main.c */,
);
name = Sources;
sourceTree = "<group>";
};
20286C2CFDCF999611CA2CEA /* Resources */ = {
isa = PBXGroup;
children = (
50459C5F038587C60ECA21EC /* X11.icns */,
);
name = Resources;
sourceTree = "<group>";
};
20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
50F4F0A7039D6ACA0E82C0CB /* CoreFoundation.framework */,
);
name = "External Frameworks and Libraries";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
527F24170B5D938C007840A7 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
527F24160B5D938C007840A7 /* X11 */ = {
isa = PBXNativeTarget;
buildConfigurationList = 527F24220B5D938C007840A7 /* Build configuration list for PBXNativeTarget "X11" */;
buildPhases = (
527F24170B5D938C007840A7 /* Headers */,
527F24180B5D938C007840A7 /* Resources */,
527F241C0B5D938C007840A7 /* Sources */,
527F241E0B5D938C007840A7 /* Frameworks */,
527F24210B5D938C007840A7 /* Rez */,
);
buildRules = (
);
dependencies = (
);
name = X11;
productName = X11;
productReference = 527F24270B5D938C007840A7 /* X11.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
20286C28FDCF999611CA2CEA /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 527F24080B5D8FFC007840A7 /* Build configuration list for PBXProject "X11" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 20286C29FDCF999611CA2CEA /* X11 */;
projectDirPath = "";
projectRoot = "";
shouldCheckCompatibility = 1;
targets = (
527F24160B5D938C007840A7 /* X11 */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
527F24180B5D938C007840A7 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
527F24370B5D9D89007840A7 /* Info.plist in Resources */,
527F241B0B5D938C007840A7 /* X11.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXRezBuildPhase section */
527F24210B5D938C007840A7 /* Rez */ = {
isa = PBXRezBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXRezBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
527F241C0B5D938C007840A7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
527F241D0B5D938C007840A7 /* bundle-main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
527F24090B5D8FFC007840A7 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
INSTALL_MODE_FLAG = "a+rX";
};
name = Development;
};
527F240A0B5D8FFC007840A7 /* Deployment */ = {
isa = XCBuildConfiguration;
buildSettings = {
INSTALL_MODE_FLAG = "a+rX";
};
name = Deployment;
};
527F240B0B5D8FFC007840A7 /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
INSTALL_MODE_FLAG = "a+rX";
};
name = Default;
};
527F24230B5D938C007840A7 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = "";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
HEADER_SEARCH_PATHS = /usr/X11/include;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = $DSTROOT/Applications/Utilties;
LIBRARY_SEARCH_PATHS = /usr/X11/lib;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = (
"-lXau",
"-lxcb",
"-lX11",
);
OTHER_REZFLAGS = "";
PRODUCT_NAME = X11;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
WRAPPER_EXTENSION = app;
};
name = Development;
};
527F24240B5D938C007840A7 /* Deployment */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
HEADER_SEARCH_PATHS = /usr/X11/include;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Applications/Utilties;
LIBRARY_SEARCH_PATHS = /usr/X11/lib;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = X11;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
WRAPPER_EXTENSION = app;
};
name = Deployment;
};
527F24250B5D938C007840A7 /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
HEADER_SEARCH_PATHS = /usr/X11/include;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Applications/Utilties;
LIBRARY_SEARCH_PATHS = /usr/X11/lib;
OTHER_CFLAGS = "";
OTHER_LDFLAGS = (
"-lXau",
"-lxcb",
"-lX11",
);
OTHER_REZFLAGS = "";
PRODUCT_NAME = X11;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
WRAPPER_EXTENSION = app;
};
name = Default;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
527F24080B5D8FFC007840A7 /* Build configuration list for PBXProject "X11" */ = {
isa = XCConfigurationList;
buildConfigurations = (
527F24090B5D8FFC007840A7 /* Development */,
527F240A0B5D8FFC007840A7 /* Deployment */,
527F240B0B5D8FFC007840A7 /* Default */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
527F24220B5D938C007840A7 /* Build configuration list for PBXNativeTarget "X11" */ = {
isa = XCConfigurationList;
buildConfigurations = (
527F24230B5D938C007840A7 /* Development */,
527F24240B5D938C007840A7 /* Deployment */,
527F24250B5D938C007840A7 /* Default */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
/* End XCConfigurationList section */
};
rootObject = 20286C28FDCF999611CA2CEA /* Project object */;
}