[weston,v2,05/17] compositor: move the main() to a new weston.c file

Submitted by Giulio Camuffo on Dec. 4, 2014, 9:01 p.m.

Details

Message ID 1417726883-8305-6-git-send-email-giuliocamuffo@gmail.com
State Superseded
Headers show

Not browsing as part of any series.

Commit Message

Giulio Camuffo Dec. 4, 2014, 9:01 p.m.
---
 Makefile.am      |   1 +
 src/compositor.c | 764 ----------------------------------------------------
 src/weston.c     | 804 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 805 insertions(+), 764 deletions(-)
 create mode 100644 src/weston.c

Patch hide | download patch | download mbox

diff --git a/Makefile.am b/Makefile.am
index 4f4bb28..acb7d1f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -69,6 +69,7 @@  weston_SOURCES =					\
 	src/noop-renderer.c				\
 	src/pixman-renderer.c				\
 	src/pixman-renderer.h				\
+	src/weston.c					\
 	shared/matrix.c					\
 	shared/matrix.h					\
 	shared/zalloc.h					\
diff --git a/src/compositor.c b/src/compositor.c
index 237f2dc..211766f 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -48,11 +48,6 @@ 
 #include <time.h>
 #include <errno.h>
 
-#ifdef HAVE_LIBUNWIND
-#define UNW_LOCAL_ONLY
-#include <libunwind.h>
-#endif
-
 #include "compositor.h"
 #include "scaler-server-protocol.h"
 #include "presentation_timing-server-protocol.h"
@@ -60,37 +55,6 @@ 
 #include "git-version.h"
 #include "version.h"
 
-static struct wl_list child_process_list;
-static struct weston_compositor *segv_compositor;
-
-static int
-sigchld_handler(int signal_number, void *data)
-{
-	struct weston_process *p;
-	int status;
-	pid_t pid;
-
-	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-		wl_list_for_each(p, &child_process_list, link) {
-			if (p->pid == pid)
-				break;
-		}
-
-		if (&p->link == &child_process_list) {
-			weston_log("unknown child process exited\n");
-			continue;
-		}
-
-		wl_list_remove(&p->link);
-		p->cleanup(p, status);
-	}
-
-	if (pid < 0 && errno != ECHILD)
-		weston_log("waitpid error %m\n");
-
-	return 1;
-}
-
 static void
 weston_output_transform_scale_init(struct weston_output *output,
 				   uint32_t transform, uint32_t scale);
@@ -262,12 +226,6 @@  weston_output_mode_switch_to_temporary(struct weston_output *output,
 	return 0;
 }
 
-WL_EXPORT void
-weston_watch_process(struct weston_process *process)
-{
-	wl_list_insert(&child_process_list, &process->link);
-}
-
 static void
 child_client_exec(int sockfd, const char *path)
 {
@@ -3974,17 +3932,6 @@  compositor_bind(struct wl_client *client,
 				       compositor, NULL);
 }
 
-static void
-log_uname(void)
-{
-	struct utsname usys;
-
-	uname(&usys);
-
-	weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
-						usys.version, usys.machine);
-}
-
 WL_EXPORT int
 weston_environment_get_fd(const char *env)
 {
@@ -4081,38 +4028,6 @@  weston_compositor_init(struct weston_compositor *ec)
 	return 0;
 }
 
-static int
-weston_compositor_init_config(struct weston_compositor *ec,
-			      struct weston_config *config)
-{
-	struct xkb_rule_names xkb_names;
-	struct weston_config_section *s;
-
-	s = weston_config_get_section(config, "keyboard", NULL, NULL);
-	weston_config_section_get_string(s, "keymap_rules",
-					 (char **) &xkb_names.rules, NULL);
-	weston_config_section_get_string(s, "keymap_model",
-					 (char **) &xkb_names.model, NULL);
-	weston_config_section_get_string(s, "keymap_layout",
-					 (char **) &xkb_names.layout, NULL);
-	weston_config_section_get_string(s, "keymap_variant",
-					 (char **) &xkb_names.variant, NULL);
-	weston_config_section_get_string(s, "keymap_options",
-					 (char **) &xkb_names.options, NULL);
-
-	if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
-		return -1;
-
-	weston_config_section_get_int(s, "repeat-rate",
-				      &ec->kb_repeat_rate, 40);
-	weston_config_section_get_int(s, "repeat-delay",
-				      &ec->kb_repeat_delay, 400);
-
-	text_backend_init(ec, config);
-
-	return 0;
-}
-
 WL_EXPORT void
 weston_compositor_shutdown(struct weston_compositor *ec)
 {
@@ -4215,160 +4130,6 @@  weston_version(int *major, int *minor, int *micro)
 	*micro = WESTON_VERSION_MICRO;
 }
 
-static const char *
-clock_name(clockid_t clk_id)
-{
-	static const char *names[] = {
-		[CLOCK_REALTIME] =		"CLOCK_REALTIME",
-		[CLOCK_MONOTONIC] =		"CLOCK_MONOTONIC",
-		[CLOCK_MONOTONIC_RAW] =		"CLOCK_MONOTONIC_RAW",
-		[CLOCK_REALTIME_COARSE] =	"CLOCK_REALTIME_COARSE",
-		[CLOCK_MONOTONIC_COARSE] =	"CLOCK_MONOTONIC_COARSE",
-		[CLOCK_BOOTTIME] =		"CLOCK_BOOTTIME",
-	};
-
-	if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
-		return "unknown";
-
-	return names[clk_id];
-}
-
-static const struct {
-	uint32_t bit; /* enum weston_capability */
-	const char *desc;
-} capability_strings[] = {
-	{ WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
-	{ WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
-};
-
-static void
-weston_compositor_log_capabilities(struct weston_compositor *compositor)
-{
-	unsigned i;
-	int yes;
-
-	weston_log("Compositor capabilities:\n");
-	for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
-		yes = compositor->capabilities & capability_strings[i].bit;
-		weston_log_continue(STAMP_SPACE "%s %s\n",
-				    capability_strings[i].desc,
-				    yes ? "yes" : "no");
-	}
-
-	weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
-			    clock_name(compositor->presentation_clock),
-			    compositor->presentation_clock);
-}
-
-static int on_term_signal(int signal_number, void *data)
-{
-	struct wl_display *display = data;
-
-	weston_log("caught signal %d\n", signal_number);
-	wl_display_terminate(display);
-
-	return 1;
-}
-
-#ifdef HAVE_LIBUNWIND
-
-static void
-print_backtrace(void)
-{
-	unw_cursor_t cursor;
-	unw_context_t context;
-	unw_word_t off;
-	unw_proc_info_t pip;
-	int ret, i = 0;
-	char procname[256];
-	const char *filename;
-	Dl_info dlinfo;
-
-	pip.unwind_info = NULL;
-	ret = unw_getcontext(&context);
-	if (ret) {
-		weston_log("unw_getcontext: %d\n", ret);
-		return;
-	}
-
-	ret = unw_init_local(&cursor, &context);
-	if (ret) {
-		weston_log("unw_init_local: %d\n", ret);
-		return;
-	}
-
-	ret = unw_step(&cursor);
-	while (ret > 0) {
-		ret = unw_get_proc_info(&cursor, &pip);
-		if (ret) {
-			weston_log("unw_get_proc_info: %d\n", ret);
-			break;
-		}
-
-		ret = unw_get_proc_name(&cursor, procname, 256, &off);
-		if (ret && ret != -UNW_ENOMEM) {
-			if (ret != -UNW_EUNSPEC)
-				weston_log("unw_get_proc_name: %d\n", ret);
-			procname[0] = '?';
-			procname[1] = 0;
-		}
-
-		if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
-		    *dlinfo.dli_fname)
-			filename = dlinfo.dli_fname;
-		else
-			filename = "?";
-
-		weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
-			   ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
-
-		ret = unw_step(&cursor);
-		if (ret < 0)
-			weston_log("unw_step: %d\n", ret);
-	}
-}
-
-#else
-
-static void
-print_backtrace(void)
-{
-	void *buffer[32];
-	int i, count;
-	Dl_info info;
-
-	count = backtrace(buffer, ARRAY_LENGTH(buffer));
-	for (i = 0; i < count; i++) {
-		dladdr(buffer[i], &info);
-		weston_log("  [%016lx]  %s  (%s)\n",
-			(long) buffer[i],
-			info.dli_sname ? info.dli_sname : "--",
-			info.dli_fname);
-	}
-}
-
-#endif
-
-static void
-on_caught_signal(int s, siginfo_t *siginfo, void *context)
-{
-	/* This signal handler will do a best-effort backtrace, and
-	 * then call the backend restore function, which will switch
-	 * back to the vt we launched from or ungrab X etc and then
-	 * raise SIGTRAP.  If we run weston under gdb from X or a
-	 * different vt, and tell gdb "handle *s* nostop", this
-	 * will allow weston to switch back to gdb on crash and then
-	 * gdb will catch the crash with SIGTRAP.*/
-
-	weston_log("caught signal: %d\n", s);
-
-	print_backtrace();
-
-	segv_compositor->backend->restore(segv_compositor);
-
-	raise(SIGTRAP);
-}
-
 WL_EXPORT void *
 weston_load_module(const char *name, const char *entrypoint)
 {
@@ -4407,531 +4168,6 @@  weston_load_module(const char *name, const char *entrypoint)
 	return init;
 }
 
-static int
-load_modules(struct weston_compositor *ec, const char *modules,
-	     int *argc, char *argv[], struct weston_config *config)
-{
-	const char *p, *end;
-	char buffer[256];
-	int (*module_init)(struct weston_compositor *ec,
-			   int *argc, char *argv[],
-			   struct weston_config *config);
-
-	if (modules == NULL)
-		return 0;
-
-	p = modules;
-	while (*p) {
-		end = strchrnul(p, ',');
-		snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
-		module_init = weston_load_module(buffer, "module_init");
-		if (module_init)
-			module_init(ec, argc, argv, config);
-		p = end;
-		while (*p == ',')
-			p++;
-
-	}
-
-	return 0;
-}
-
-static const char xdg_error_message[] =
-	"fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
-
-static const char xdg_wrong_message[] =
-	"fatal: environment variable XDG_RUNTIME_DIR\n"
-	"is set to \"%s\", which is not a directory.\n";
-
-static const char xdg_wrong_mode_message[] =
-	"warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
-	"correctly.  Unix access mode must be 0700 (current mode is %o),\n"
-	"and must be owned by the user (current owner is UID %d).\n";
-
-static const char xdg_detail_message[] =
-	"Refer to your distribution on how to get it, or\n"
-	"http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
-	"on how to implement it.\n";
-
-static void
-verify_xdg_runtime_dir(void)
-{
-	char *dir = getenv("XDG_RUNTIME_DIR");
-	struct stat s;
-
-	if (!dir) {
-		weston_log(xdg_error_message);
-		weston_log_continue(xdg_detail_message);
-		exit(EXIT_FAILURE);
-	}
-
-	if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
-		weston_log(xdg_wrong_message, dir);
-		weston_log_continue(xdg_detail_message);
-		exit(EXIT_FAILURE);
-	}
-
-	if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
-		weston_log(xdg_wrong_mode_message,
-			   dir, s.st_mode & 0777, s.st_uid);
-		weston_log_continue(xdg_detail_message);
-	}
-}
-
-static int
-usage(int error_code)
-{
-	fprintf(stderr,
-		"Usage: weston [OPTIONS]\n\n"
-		"This is weston version " VERSION ", the Wayland reference compositor.\n"
-		"Weston supports multiple backends, and depending on which backend is in use\n"
-		"different options will be accepted.\n\n"
-
-
-		"Core options:\n\n"
-		"  --version\t\tPrint weston version\n"
-		"  -B, --backend=MODULE\tBackend module, one of\n"
-#if defined(BUILD_DRM_COMPOSITOR)
-			"\t\t\t\tdrm-backend.so\n"
-#endif
-#if defined(BUILD_FBDEV_COMPOSITOR)
-			"\t\t\t\tfbdev-backend.so\n"
-#endif
-#if defined(BUILD_X11_COMPOSITOR)
-			"\t\t\t\tx11-backend.so\n"
-#endif
-#if defined(BUILD_WAYLAND_COMPOSITOR)
-			"\t\t\t\twayland-backend.so\n"
-#endif
-#if defined(BUILD_RDP_COMPOSITOR)
-			"\t\t\t\trdp-backend.so\n"
-#endif
-#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
-			"\t\t\t\trpi-backend.so\n"
-#endif
-		"  --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
-		"  -S, --socket=NAME\tName of socket to listen on\n"
-		"  -i, --idle-time=SECS\tIdle time in seconds\n"
-		"  --modules\t\tLoad the comma-separated list of modules\n"
-		"  --log=FILE\t\tLog to the given file\n"
-		"  --no-config\t\tDo not read weston.ini\n"
-		"  -h, --help\t\tThis help message\n\n");
-
-#if defined(BUILD_DRM_COMPOSITOR)
-	fprintf(stderr,
-		"Options for drm-backend.so:\n\n"
-		"  --connector=ID\tBring up only this connector\n"
-		"  --seat=SEAT\t\tThe seat that weston should run on\n"
-		"  --tty=TTY\t\tThe tty to use\n"
-		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
-		"  --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
-#endif
-
-#if defined(BUILD_FBDEV_COMPOSITOR)
-	fprintf(stderr,
-		"Options for fbdev-backend.so:\n\n"
-		"  --tty=TTY\t\tThe tty to use\n"
-		"  --device=DEVICE\tThe framebuffer device to use\n\n");
-#endif
-
-#if defined(BUILD_X11_COMPOSITOR)
-	fprintf(stderr,
-		"Options for x11-backend.so:\n\n"
-		"  --width=WIDTH\t\tWidth of X window\n"
-		"  --height=HEIGHT\tHeight of X window\n"
-		"  --fullscreen\t\tRun in fullscreen mode\n"
-		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
-		"  --output-count=COUNT\tCreate multiple outputs\n"
-		"  --no-input\t\tDont create input devices\n\n");
-#endif
-
-#if defined(BUILD_WAYLAND_COMPOSITOR)
-	fprintf(stderr,
-		"Options for wayland-backend.so:\n\n"
-		"  --width=WIDTH\t\tWidth of Wayland surface\n"
-		"  --height=HEIGHT\tHeight of Wayland surface\n"
-		"  --scale=SCALE\t\tScale factor of output\n"
-		"  --fullscreen\t\tRun in fullscreen mode\n"
-		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
-		"  --output-count=COUNT\tCreate multiple outputs\n"
-		"  --sprawl\t\tCreate one fullscreen output for every parent output\n"
-		"  --display=DISPLAY\tWayland display to connect to\n\n");
-#endif
-
-#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
-	fprintf(stderr,
-		"Options for rpi-backend.so:\n\n"
-		"  --tty=TTY\t\tThe tty to use\n"
-		"  --single-buffer\tUse single-buffered Dispmanx elements.\n"
-		"  --transform=TR\tThe output transformation, TR is one of:\n"
-		"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
-		"  --opaque-regions\tEnable support for opaque regions, can be "
-		"very slow without support in the GPU firmware.\n"
-		"\n");
-#endif
-
-#if defined(BUILD_RDP_COMPOSITOR)
-	fprintf(stderr,
-		"Options for rdp-backend.so:\n\n"
-		"  --width=WIDTH\t\tWidth of desktop\n"
-		"  --height=HEIGHT\tHeight of desktop\n"
-		"  --env-socket=SOCKET\tUse that socket as peer connection\n"
-		"  --address=ADDR\tThe address to bind\n"
-		"  --port=PORT\t\tThe port to listen on\n"
-		"  --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
-		"  --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
-		"  --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
-		"  --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
-		"\n");
-#endif
-
-#if defined(BUILD_HEADLESS_COMPOSITOR)
-	fprintf(stderr,
-		"Options for headless-backend.so:\n\n"
-		"  --width=WIDTH\t\tWidth of memory surface\n"
-		"  --height=HEIGHT\tHeight of memory surface\n"
-		"  --transform=TR\tThe output transformation, TR is one of:\n"
-		"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
-		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n\n");
-#endif
-
-	exit(error_code);
-}
-
-static void
-catch_signals(void)
-{
-	struct sigaction action;
-
-	action.sa_flags = SA_SIGINFO | SA_RESETHAND;
-	action.sa_sigaction = on_caught_signal;
-	sigemptyset(&action.sa_mask);
-	sigaction(SIGSEGV, &action, NULL);
-	sigaction(SIGABRT, &action, NULL);
-}
-
-static void
-handle_primary_client_destroyed(struct wl_listener *listener, void *data)
-{
-	struct wl_client *client = data;
-
-	weston_log("Primary client died.  Closing...\n");
-
-	wl_display_terminate(wl_client_get_display(client));
-}
-
-static char *
-weston_choose_default_backend(void)
-{
-	char *backend = NULL;
-
-	if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
-		backend = strdup("wayland-backend.so");
-	else if (getenv("DISPLAY"))
-		backend = strdup("x11-backend.so");
-	else
-		backend = strdup(WESTON_NATIVE_BACKEND);
-
-	return backend;
-}
-
-static int
-weston_create_listening_socket(struct wl_display *display, const char *socket_name)
-{
-	if (socket_name) {
-		if (wl_display_add_socket(display, socket_name)) {
-			weston_log("fatal: failed to add socket: %m\n");
-			return -1;
-		}
-	} else {
-		socket_name = wl_display_add_socket_auto(display);
-		if (!socket_name) {
-			weston_log("fatal: failed to add socket: %m\n");
-			return -1;
-		}
-	}
-
-	setenv("WAYLAND_DISPLAY", socket_name, 1);
-
-	return 0;
-}
-
-static const struct { const char *name; uint32_t token; } transforms[] = {
-	{ "normal",     WL_OUTPUT_TRANSFORM_NORMAL },
-	{ "90",         WL_OUTPUT_TRANSFORM_90 },
-	{ "180",        WL_OUTPUT_TRANSFORM_180 },
-	{ "270",        WL_OUTPUT_TRANSFORM_270 },
-	{ "flipped",    WL_OUTPUT_TRANSFORM_FLIPPED },
-	{ "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
-	{ "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
-	{ "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
-};
-
-WL_EXPORT int
-weston_parse_transform(const char *transform, uint32_t *out)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_LENGTH(transforms); i++)
-		if (strcmp(transforms[i].name, transform) == 0) {
-			*out = transforms[i].token;
-			return 0;
-		}
-
-	*out = WL_OUTPUT_TRANSFORM_NORMAL;
-	return -1;
-}
-
-WL_EXPORT const char *
-weston_transform_to_string(uint32_t output_transform)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_LENGTH(transforms); i++)
-		if (transforms[i].token == output_transform)
-			return transforms[i].name;
-
-	return "<illegal value>";
-}
-
-static void
-handle_terminate(struct weston_compositor *c)
-{
-	wl_display_terminate(c->wl_display);
-}
-
-int main(int argc, char *argv[])
-{
-	int ret = EXIT_SUCCESS;
-	struct wl_display *display;
-	struct weston_compositor *ec;
-	struct wl_event_source *signals[4];
-	struct wl_event_loop *loop;
-	int (*backend_init)(struct weston_compositor *c,
-			    int *argc, char *argv[],
-			    struct weston_config *config);
-	int i, fd;
-	char *backend = NULL;
-	char *shell = NULL;
-	char *modules = NULL;
-	char *option_modules = NULL;
-	char *log = NULL;
-	char *server_socket = NULL, *end;
-	int32_t idle_time = -1;
-	int32_t help = 0;
-	char *socket_name = NULL;
-	int32_t version = 0;
-	int32_t noconfig = 0;
-	int32_t numlock_on;
-	struct weston_config *config = NULL;
-	struct weston_config_section *section;
-	struct wl_client *primary_client;
-	struct wl_listener primary_client_destroyed;
-	struct weston_seat *seat;
-
-	const struct weston_option core_options[] = {
-		{ WESTON_OPTION_STRING, "backend", 'B', &backend },
-		{ WESTON_OPTION_STRING, "shell", 0, &shell },
-		{ WESTON_OPTION_STRING, "socket", 'S', &socket_name },
-		{ WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
-		{ WESTON_OPTION_STRING, "modules", 0, &option_modules },
-		{ WESTON_OPTION_STRING, "log", 0, &log },
-		{ WESTON_OPTION_BOOLEAN, "help", 'h', &help },
-		{ WESTON_OPTION_BOOLEAN, "version", 0, &version },
-		{ WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
-	};
-
-	parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
-
-	if (help)
-		usage(EXIT_SUCCESS);
-
-	if (version) {
-		printf(PACKAGE_STRING "\n");
-		return EXIT_SUCCESS;
-	}
-
-	weston_log_file_open(log);
-
-	weston_log("%s\n"
-		   STAMP_SPACE "%s\n"
-		   STAMP_SPACE "Bug reports to: %s\n"
-		   STAMP_SPACE "Build: %s\n",
-		   PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
-		   BUILD_ID);
-	log_uname();
-
-	verify_xdg_runtime_dir();
-
-	display = wl_display_create();
-
-	loop = wl_display_get_event_loop(display);
-	signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
-					      display);
-	signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
-					      display);
-	signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
-					      display);
-
-	wl_list_init(&child_process_list);
-	signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
-					      NULL);
-
-	if (!signals[0] || !signals[1] || !signals[2] || !signals[3]) {
-		ret = EXIT_FAILURE;
-		goto out_signals;
-	}
-
-	if (noconfig == 0)
-		config = weston_config_parse("weston.ini");
-	if (config != NULL) {
-		weston_log("Using config file '%s'\n",
-			   weston_config_get_full_path(config));
-	} else {
-		weston_log("Starting with no config file.\n");
-	}
-	section = weston_config_get_section(config, "core", NULL, NULL);
-
-	if (!backend) {
-		weston_config_section_get_string(section, "backend", &backend,
-						 NULL);
-		if (!backend)
-			backend = weston_choose_default_backend();
-	}
-
-	backend_init = weston_load_module(backend, "backend_init");
-	if (!backend_init) {
-		ret = EXIT_FAILURE;
-		goto out_signals;
-	}
-
-	ec = zalloc(sizeof *ec);
-	if (ec == NULL) {
-		weston_log("fatal: failed to create compositor\n");
-		ret = EXIT_FAILURE;
-		goto out_signals;
-	}
-
-	ec->wl_display = display;
-	if (weston_compositor_init(ec) < 0 ||
-	    weston_compositor_init_config(ec, config) < 0) {
-		ret = EXIT_FAILURE;
-		goto out_signals;
-	}
-
-	if (backend_init(ec, &argc, argv, config) < 0) {
-		weston_log("fatal: failed to create compositor backend\n");
-		ret = EXIT_FAILURE;
-		goto out_signals;
-	}
-
-	catch_signals();
-	segv_compositor = ec;
-
-	if (idle_time < 0)
-		weston_config_section_get_int(section, "idle-time", &idle_time, -1);
-	if (idle_time < 0)
-		idle_time = 300; /* default idle timeout, in seconds */
-	ec->idle_time = idle_time;
-	ec->default_pointer_grab = NULL;
-	ec->exit_code = EXIT_SUCCESS;
-	ec->terminate = handle_terminate;
-
-	for (i = 1; i < argc; i++)
-		weston_log("fatal: unhandled option: %s\n", argv[i]);
-	if (argc > 1) {
-		ret = EXIT_FAILURE;
-		goto out;
-	}
-
-	weston_compositor_log_capabilities(ec);
-
-	server_socket = getenv("WAYLAND_SERVER_SOCKET");
-	if (server_socket) {
-		weston_log("Running with single client\n");
-		fd = strtol(server_socket, &end, 0);
-		if (*end != '\0')
-			fd = -1;
-	} else {
-		fd = -1;
-	}
-
-	if (fd != -1) {
-		primary_client = wl_client_create(display, fd);
-		if (!primary_client) {
-			weston_log("fatal: failed to add client: %m\n");
-			ret = EXIT_FAILURE;
-			goto out;
-		}
-		primary_client_destroyed.notify =
-			handle_primary_client_destroyed;
-		wl_client_add_destroy_listener(primary_client,
-					       &primary_client_destroyed);
-	} else if (weston_create_listening_socket(display, socket_name)) {
-		ret = EXIT_FAILURE;
-		goto out;
-	}
-
-	if (!shell)
-		weston_config_section_get_string(section, "shell", &shell,
-						 "desktop-shell.so");
-
-	if (load_modules(ec, shell, &argc, argv, config) < 0)
-		goto out;
-
-	weston_config_section_get_string(section, "modules", &modules, "");
-	if (load_modules(ec, modules, &argc, argv, config) < 0)
-		goto out;
-
-	if (load_modules(ec, option_modules, &argc, argv, config) < 0)
-		goto out;
-
-	section = weston_config_get_section(config, "keyboard", NULL, NULL);
-	weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
-	if (numlock_on) {
-		wl_list_for_each(seat, &ec->seat_list, link) {
-			if (seat->keyboard)
-				weston_keyboard_set_locks(seat->keyboard,
-							  WESTON_NUM_LOCK,
-							  WESTON_NUM_LOCK);
-		}
-	}
-
-	weston_compositor_wake(ec);
-
-	wl_display_run(display);
-
-	/* Allow for setting return exit code after
-	 * wl_display_run returns normally. This is
-	 * useful for devs/testers and automated tests
-	 * that want to indicate failure status to
-	 * testing infrastructure above
-	 */
-	ret = ec->exit_code;
-
-out:
-	weston_compositor_destroy(ec);
-
-out_signals:
-	for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
-		if (signals[i])
-			wl_event_source_remove(signals[i]);
-
-	wl_display_destroy(display);
-
-	weston_log_file_close();
-	weston_config_destroy(config);
-
-	free(backend);
-	free(shell);
-	free(socket_name);
-	free(option_modules);
-	free(log);
-	free(modules);
-
-	return ret;
-}
-
 WL_EXPORT void
 weston_compositor_destroy(struct weston_compositor *ec)
 {
diff --git a/src/weston.c b/src/weston.c
new file mode 100644
index 0000000..e678212
--- /dev/null
+++ b/src/weston.c
@@ -0,0 +1,804 @@ 
+/*
+ * Copyright © 2010-2011 Intel Corporation
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2012-2014 Collabora, Ltd.
+ *
+ * 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, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_LIBUNWIND
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#endif
+
+#include "compositor.h"
+#include "../shared/os-compatibility.h"
+#include "git-version.h"
+#include "version.h"
+
+static struct wl_list child_process_list;
+static struct weston_compositor *segv_compositor;
+
+static int
+sigchld_handler(int signal_number, void *data)
+{
+	struct weston_process *p;
+	int status;
+	pid_t pid;
+
+	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+		wl_list_for_each(p, &child_process_list, link) {
+			if (p->pid == pid)
+				break;
+		}
+
+		if (&p->link == &child_process_list) {
+			weston_log("unknown child process exited\n");
+			continue;
+		}
+
+		wl_list_remove(&p->link);
+		p->cleanup(p, status);
+	}
+
+	if (pid < 0 && errno != ECHILD)
+		weston_log("waitpid error %m\n");
+
+	return 1;
+}
+
+#ifdef HAVE_LIBUNWIND
+
+static void
+print_backtrace(void)
+{
+	unw_cursor_t cursor;
+	unw_context_t context;
+	unw_word_t off;
+	unw_proc_info_t pip;
+	int ret, i = 0;
+	char procname[256];
+	const char *filename;
+	Dl_info dlinfo;
+
+	pip.unwind_info = NULL;
+	ret = unw_getcontext(&context);
+	if (ret) {
+		weston_log("unw_getcontext: %d\n", ret);
+		return;
+	}
+
+	ret = unw_init_local(&cursor, &context);
+	if (ret) {
+		weston_log("unw_init_local: %d\n", ret);
+		return;
+	}
+
+	ret = unw_step(&cursor);
+	while (ret > 0) {
+		ret = unw_get_proc_info(&cursor, &pip);
+		if (ret) {
+			weston_log("unw_get_proc_info: %d\n", ret);
+			break;
+		}
+
+		ret = unw_get_proc_name(&cursor, procname, 256, &off);
+		if (ret && ret != -UNW_ENOMEM) {
+			if (ret != -UNW_EUNSPEC)
+				weston_log("unw_get_proc_name: %d\n", ret);
+			procname[0] = '?';
+			procname[1] = 0;
+		}
+
+		if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
+		    *dlinfo.dli_fname)
+			filename = dlinfo.dli_fname;
+		else
+			filename = "?";
+
+		weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
+			   ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
+
+		ret = unw_step(&cursor);
+		if (ret < 0)
+			weston_log("unw_step: %d\n", ret);
+	}
+}
+
+#else
+
+static void
+print_backtrace(void)
+{
+	void *buffer[32];
+	int i, count;
+	Dl_info info;
+
+	count = backtrace(buffer, ARRAY_LENGTH(buffer));
+	for (i = 0; i < count; i++) {
+		dladdr(buffer[i], &info);
+		weston_log("  [%016lx]  %s  (%s)\n",
+			(long) buffer[i],
+			info.dli_sname ? info.dli_sname : "--",
+			info.dli_fname);
+	}
+}
+
+#endif
+
+WL_EXPORT void
+weston_watch_process(struct weston_process *process)
+{
+	wl_list_insert(&child_process_list, &process->link);
+}
+
+static void
+log_uname(void)
+{
+	struct utsname usys;
+
+	uname(&usys);
+
+	weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
+						usys.version, usys.machine);
+}
+
+static const char xdg_error_message[] =
+	"fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
+
+static const char xdg_wrong_message[] =
+	"fatal: environment variable XDG_RUNTIME_DIR\n"
+	"is set to \"%s\", which is not a directory.\n";
+
+static const char xdg_wrong_mode_message[] =
+	"warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
+	"correctly.  Unix access mode must be 0700 (current mode is %o),\n"
+	"and must be owned by the user (current owner is UID %d).\n";
+
+static const char xdg_detail_message[] =
+	"Refer to your distribution on how to get it, or\n"
+	"http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
+	"on how to implement it.\n";
+
+static void
+verify_xdg_runtime_dir(void)
+{
+	char *dir = getenv("XDG_RUNTIME_DIR");
+	struct stat s;
+
+	if (!dir) {
+		weston_log(xdg_error_message);
+		weston_log_continue(xdg_detail_message);
+		exit(EXIT_FAILURE);
+	}
+
+	if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
+		weston_log(xdg_wrong_message, dir);
+		weston_log_continue(xdg_detail_message);
+		exit(EXIT_FAILURE);
+	}
+
+	if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
+		weston_log(xdg_wrong_mode_message,
+			   dir, s.st_mode & 0777, s.st_uid);
+		weston_log_continue(xdg_detail_message);
+	}
+}
+
+static int
+usage(int error_code)
+{
+	fprintf(stderr,
+		"Usage: weston [OPTIONS]\n\n"
+		"This is weston version " VERSION ", the Wayland reference compositor.\n"
+		"Weston supports multiple backends, and depending on which backend is in use\n"
+		"different options will be accepted.\n\n"
+
+
+		"Core options:\n\n"
+		"  --version\t\tPrint weston version\n"
+		"  -B, --backend=MODULE\tBackend module, one of\n"
+#if defined(BUILD_DRM_COMPOSITOR)
+			"\t\t\t\tdrm-backend.so\n"
+#endif
+#if defined(BUILD_FBDEV_COMPOSITOR)
+			"\t\t\t\tfbdev-backend.so\n"
+#endif
+#if defined(BUILD_X11_COMPOSITOR)
+			"\t\t\t\tx11-backend.so\n"
+#endif
+#if defined(BUILD_WAYLAND_COMPOSITOR)
+			"\t\t\t\twayland-backend.so\n"
+#endif
+#if defined(BUILD_RDP_COMPOSITOR)
+			"\t\t\t\trdp-backend.so\n"
+#endif
+#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
+			"\t\t\t\trpi-backend.so\n"
+#endif
+		"  --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
+		"  -S, --socket=NAME\tName of socket to listen on\n"
+		"  -i, --idle-time=SECS\tIdle time in seconds\n"
+		"  --modules\t\tLoad the comma-separated list of modules\n"
+		"  --log=FILE\t\tLog to the given file\n"
+		"  --no-config\t\tDo not read weston.ini\n"
+		"  -h, --help\t\tThis help message\n\n");
+
+#if defined(BUILD_DRM_COMPOSITOR)
+	fprintf(stderr,
+		"Options for drm-backend.so:\n\n"
+		"  --connector=ID\tBring up only this connector\n"
+		"  --seat=SEAT\t\tThe seat that weston should run on\n"
+		"  --tty=TTY\t\tThe tty to use\n"
+		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
+		"  --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
+#endif
+
+#if defined(BUILD_FBDEV_COMPOSITOR)
+	fprintf(stderr,
+		"Options for fbdev-backend.so:\n\n"
+		"  --tty=TTY\t\tThe tty to use\n"
+		"  --device=DEVICE\tThe framebuffer device to use\n\n");
+#endif
+
+#if defined(BUILD_X11_COMPOSITOR)
+	fprintf(stderr,
+		"Options for x11-backend.so:\n\n"
+		"  --width=WIDTH\t\tWidth of X window\n"
+		"  --height=HEIGHT\tHeight of X window\n"
+		"  --fullscreen\t\tRun in fullscreen mode\n"
+		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
+		"  --output-count=COUNT\tCreate multiple outputs\n"
+		"  --no-input\t\tDont create input devices\n\n");
+#endif
+
+#if defined(BUILD_WAYLAND_COMPOSITOR)
+	fprintf(stderr,
+		"Options for wayland-backend.so:\n\n"
+		"  --width=WIDTH\t\tWidth of Wayland surface\n"
+		"  --height=HEIGHT\tHeight of Wayland surface\n"
+		"  --scale=SCALE\t\tScale factor of output\n"
+		"  --fullscreen\t\tRun in fullscreen mode\n"
+		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
+		"  --output-count=COUNT\tCreate multiple outputs\n"
+		"  --sprawl\t\tCreate one fullscreen output for every parent output\n"
+		"  --display=DISPLAY\tWayland display to connect to\n\n");
+#endif
+
+#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
+	fprintf(stderr,
+		"Options for rpi-backend.so:\n\n"
+		"  --tty=TTY\t\tThe tty to use\n"
+		"  --single-buffer\tUse single-buffered Dispmanx elements.\n"
+		"  --transform=TR\tThe output transformation, TR is one of:\n"
+		"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
+		"  --opaque-regions\tEnable support for opaque regions, can be "
+		"very slow without support in the GPU firmware.\n"
+		"\n");
+#endif
+
+#if defined(BUILD_RDP_COMPOSITOR)
+	fprintf(stderr,
+		"Options for rdp-backend.so:\n\n"
+		"  --width=WIDTH\t\tWidth of desktop\n"
+		"  --height=HEIGHT\tHeight of desktop\n"
+		"  --env-socket=SOCKET\tUse that socket as peer connection\n"
+		"  --address=ADDR\tThe address to bind\n"
+		"  --port=PORT\t\tThe port to listen on\n"
+		"  --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
+		"  --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
+		"  --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
+		"  --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
+		"\n");
+#endif
+
+#if defined(BUILD_HEADLESS_COMPOSITOR)
+	fprintf(stderr,
+		"Options for headless-backend.so:\n\n"
+		"  --width=WIDTH\t\tWidth of memory surface\n"
+		"  --height=HEIGHT\tHeight of memory surface\n"
+		"  --transform=TR\tThe output transformation, TR is one of:\n"
+		"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
+		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n\n");
+#endif
+
+	exit(error_code);
+}
+
+static int on_term_signal(int signal_number, void *data)
+{
+	struct wl_display *display = data;
+
+	weston_log("caught signal %d\n", signal_number);
+	wl_display_terminate(display);
+
+	return 1;
+}
+
+static void
+on_caught_signal(int s, siginfo_t *siginfo, void *context)
+{
+	/* This signal handler will do a best-effort backtrace, and
+	 * then call the backend restore function, which will switch
+	 * back to the vt we launched from or ungrab X etc and then
+	 * raise SIGTRAP.  If we run weston under gdb from X or a
+	 * different vt, and tell gdb "handle *s* nostop", this
+	 * will allow weston to switch back to gdb on crash and then
+	 * gdb will catch the crash with SIGTRAP.*/
+
+	weston_log("caught signal: %d\n", s);
+
+	print_backtrace();
+
+	segv_compositor->backend->restore(segv_compositor);
+
+	raise(SIGTRAP);
+}
+
+static void
+catch_signals(void)
+{
+	struct sigaction action;
+
+	action.sa_flags = SA_SIGINFO | SA_RESETHAND;
+	action.sa_sigaction = on_caught_signal;
+	sigemptyset(&action.sa_mask);
+	sigaction(SIGSEGV, &action, NULL);
+	sigaction(SIGABRT, &action, NULL);
+}
+
+static const char *
+clock_name(clockid_t clk_id)
+{
+	static const char *names[] = {
+		[CLOCK_REALTIME] =		"CLOCK_REALTIME",
+		[CLOCK_MONOTONIC] =		"CLOCK_MONOTONIC",
+		[CLOCK_MONOTONIC_RAW] =		"CLOCK_MONOTONIC_RAW",
+		[CLOCK_REALTIME_COARSE] =	"CLOCK_REALTIME_COARSE",
+		[CLOCK_MONOTONIC_COARSE] =	"CLOCK_MONOTONIC_COARSE",
+		[CLOCK_BOOTTIME] =		"CLOCK_BOOTTIME",
+	};
+
+	if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
+		return "unknown";
+
+	return names[clk_id];
+}
+
+static const struct {
+	uint32_t bit; /* enum weston_capability */
+	const char *desc;
+} capability_strings[] = {
+	{ WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
+	{ WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
+};
+
+static void
+weston_compositor_log_capabilities(struct weston_compositor *compositor)
+{
+	unsigned i;
+	int yes;
+
+	weston_log("Compositor capabilities:\n");
+	for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
+		yes = compositor->capabilities & capability_strings[i].bit;
+		weston_log_continue(STAMP_SPACE "%s %s\n",
+				    capability_strings[i].desc,
+				    yes ? "yes" : "no");
+	}
+
+	weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
+			    clock_name(compositor->presentation_clock),
+			    compositor->presentation_clock);
+}
+
+static void
+handle_primary_client_destroyed(struct wl_listener *listener, void *data)
+{
+	struct wl_client *client = data;
+
+	weston_log("Primary client died.  Closing...\n");
+
+	wl_display_terminate(wl_client_get_display(client));
+}
+
+static int
+weston_create_listening_socket(struct wl_display *display, const char *socket_name)
+{
+	if (socket_name) {
+		if (wl_display_add_socket(display, socket_name)) {
+			weston_log("fatal: failed to add socket: %m\n");
+			return -1;
+		}
+	} else {
+		socket_name = wl_display_add_socket_auto(display);
+		if (!socket_name) {
+			weston_log("fatal: failed to add socket: %m\n");
+			return -1;
+		}
+	}
+
+	setenv("WAYLAND_DISPLAY", socket_name, 1);
+
+	return 0;
+}
+
+static int
+load_modules(struct weston_compositor *ec, const char *modules,
+	     int *argc, char *argv[], struct weston_config *config)
+{
+	const char *p, *end;
+	char buffer[256];
+	int (*module_init)(struct weston_compositor *ec,
+			   int *argc, char *argv[],
+			   struct weston_config *config);
+
+	if (modules == NULL)
+		return 0;
+
+	p = modules;
+	while (*p) {
+		end = strchrnul(p, ',');
+		snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
+		module_init = weston_load_module(buffer, "module_init");
+		if (module_init)
+			module_init(ec, argc, argv, config);
+		p = end;
+		while (*p == ',')
+			p++;
+
+	}
+
+	return 0;
+}
+
+static int
+weston_compositor_init_config(struct weston_compositor *ec,
+			      struct weston_config *config)
+{
+	struct xkb_rule_names xkb_names;
+	struct weston_config_section *s;
+
+	s = weston_config_get_section(config, "keyboard", NULL, NULL);
+	weston_config_section_get_string(s, "keymap_rules",
+					 (char **) &xkb_names.rules, NULL);
+	weston_config_section_get_string(s, "keymap_model",
+					 (char **) &xkb_names.model, NULL);
+	weston_config_section_get_string(s, "keymap_layout",
+					 (char **) &xkb_names.layout, NULL);
+	weston_config_section_get_string(s, "keymap_variant",
+					 (char **) &xkb_names.variant, NULL);
+	weston_config_section_get_string(s, "keymap_options",
+					 (char **) &xkb_names.options, NULL);
+
+	if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
+		return -1;
+
+	weston_config_section_get_int(s, "repeat-rate",
+				      &ec->kb_repeat_rate, 40);
+	weston_config_section_get_int(s, "repeat-delay",
+				      &ec->kb_repeat_delay, 400);
+
+	text_backend_init(ec, config);
+
+	return 0;
+}
+
+static char *
+weston_choose_default_backend(void)
+{
+	char *backend = NULL;
+
+	if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
+		backend = strdup("wayland-backend.so");
+	else if (getenv("DISPLAY"))
+		backend = strdup("x11-backend.so");
+	else
+		backend = strdup(WESTON_NATIVE_BACKEND);
+
+	return backend;
+}
+
+static const struct { const char *name; uint32_t token; } transforms[] = {
+	{ "normal",     WL_OUTPUT_TRANSFORM_NORMAL },
+	{ "90",         WL_OUTPUT_TRANSFORM_90 },
+	{ "180",        WL_OUTPUT_TRANSFORM_180 },
+	{ "270",        WL_OUTPUT_TRANSFORM_270 },
+	{ "flipped",    WL_OUTPUT_TRANSFORM_FLIPPED },
+	{ "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
+	{ "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
+	{ "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
+};
+
+WL_EXPORT int
+weston_parse_transform(const char *transform, uint32_t *out)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_LENGTH(transforms); i++)
+		if (strcmp(transforms[i].name, transform) == 0) {
+			*out = transforms[i].token;
+			return 0;
+		}
+
+	*out = WL_OUTPUT_TRANSFORM_NORMAL;
+	return -1;
+}
+
+WL_EXPORT const char *
+weston_transform_to_string(uint32_t output_transform)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_LENGTH(transforms); i++)
+		if (transforms[i].token == output_transform)
+			return transforms[i].name;
+
+	return "<illegal value>";
+}
+
+static void
+handle_terminate(struct weston_compositor *c)
+{
+	wl_display_terminate(c->wl_display);
+}
+
+int main(int argc, char *argv[])
+{
+	int ret = EXIT_SUCCESS;
+	struct wl_display *display;
+	struct weston_compositor *ec;
+	struct wl_event_source *signals[4];
+	struct wl_event_loop *loop;
+	int (*backend_init)(struct weston_compositor *c,
+			    int *argc, char *argv[],
+			    struct weston_config *config);
+	int i, fd;
+	char *backend = NULL;
+	char *shell = NULL;
+	char *modules = NULL;
+	char *option_modules = NULL;
+	char *log = NULL;
+	char *server_socket = NULL, *end;
+	int32_t idle_time = -1;
+	int32_t help = 0;
+	char *socket_name = NULL;
+	int32_t version = 0;
+	int32_t noconfig = 0;
+	int32_t numlock_on;
+	struct weston_config *config = NULL;
+	struct weston_config_section *section;
+	struct wl_client *primary_client;
+	struct wl_listener primary_client_destroyed;
+	struct weston_seat *seat;
+
+	const struct weston_option core_options[] = {
+		{ WESTON_OPTION_STRING, "backend", 'B', &backend },
+		{ WESTON_OPTION_STRING, "shell", 0, &shell },
+		{ WESTON_OPTION_STRING, "socket", 'S', &socket_name },
+		{ WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
+		{ WESTON_OPTION_STRING, "modules", 0, &option_modules },
+		{ WESTON_OPTION_STRING, "log", 0, &log },
+		{ WESTON_OPTION_BOOLEAN, "help", 'h', &help },
+		{ WESTON_OPTION_BOOLEAN, "version", 0, &version },
+		{ WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
+	};
+
+	parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
+
+	if (help)
+		usage(EXIT_SUCCESS);
+
+	if (version) {
+		printf(PACKAGE_STRING "\n");
+		return EXIT_SUCCESS;
+	}
+
+	weston_log_file_open(log);
+
+	weston_log("%s\n"
+		   STAMP_SPACE "%s\n"
+		   STAMP_SPACE "Bug reports to: %s\n"
+		   STAMP_SPACE "Build: %s\n",
+		   PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
+		   BUILD_ID);
+	log_uname();
+
+	verify_xdg_runtime_dir();
+
+	display = wl_display_create();
+
+	loop = wl_display_get_event_loop(display);
+	signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
+					      display);
+	signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
+					      display);
+	signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
+					      display);
+
+	wl_list_init(&child_process_list);
+	signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
+					      NULL);
+
+	if (!signals[0] || !signals[1] || !signals[2] || !signals[3]) {
+		ret = EXIT_FAILURE;
+		goto out_signals;
+	}
+
+	if (noconfig == 0)
+		config = weston_config_parse("weston.ini");
+	if (config != NULL) {
+		weston_log("Using config file '%s'\n",
+			   weston_config_get_full_path(config));
+	} else {
+		weston_log("Starting with no config file.\n");
+	}
+	section = weston_config_get_section(config, "core", NULL, NULL);
+
+	if (!backend) {
+		weston_config_section_get_string(section, "backend", &backend,
+						 NULL);
+		if (!backend)
+			backend = weston_choose_default_backend();
+	}
+
+	backend_init = weston_load_module(backend, "backend_init");
+	if (!backend_init) {
+		ret = EXIT_FAILURE;
+		goto out_signals;
+	}
+
+	ec = zalloc(sizeof *ec);
+	if (ec == NULL) {
+		weston_log("fatal: failed to create compositor\n");
+		ret = EXIT_FAILURE;
+		goto out_signals;
+	}
+
+	ec->wl_display = display;
+	if (weston_compositor_init(ec) < 0 ||
+	    weston_compositor_init_config(ec, config) < 0) {
+		ret = EXIT_FAILURE;
+		goto out_signals;
+	}
+
+	if (backend_init(ec, &argc, argv, config) < 0) {
+		weston_log("fatal: failed to create compositor backend\n");
+		ret = EXIT_FAILURE;
+		goto out_signals;
+	}
+
+	catch_signals();
+	segv_compositor = ec;
+
+	if (idle_time < 0)
+		weston_config_section_get_int(section, "idle-time", &idle_time, -1);
+	if (idle_time < 0)
+		idle_time = 300; /* default idle timeout, in seconds */
+
+	ec->idle_time = idle_time;
+	ec->default_pointer_grab = NULL;
+	ec->exit_code = EXIT_SUCCESS;
+	ec->terminate = handle_terminate;
+
+	for (i = 1; i < argc; i++)
+		weston_log("fatal: unhandled option: %s\n", argv[i]);
+	if (argc > 1) {
+		ret = EXIT_FAILURE;
+		goto out;
+	}
+
+	weston_compositor_log_capabilities(ec);
+
+	server_socket = getenv("WAYLAND_SERVER_SOCKET");
+	if (server_socket) {
+		weston_log("Running with single client\n");
+		fd = strtol(server_socket, &end, 0);
+		if (*end != '\0')
+			fd = -1;
+	} else {
+		fd = -1;
+	}
+
+	if (fd != -1) {
+		primary_client = wl_client_create(display, fd);
+		if (!primary_client) {
+			weston_log("fatal: failed to add client: %m\n");
+			ret = EXIT_FAILURE;
+			goto out;
+		}
+		primary_client_destroyed.notify =
+			handle_primary_client_destroyed;
+		wl_client_add_destroy_listener(primary_client,
+					       &primary_client_destroyed);
+	} else if (weston_create_listening_socket(display, socket_name)) {
+		ret = EXIT_FAILURE;
+		goto out;
+	}
+
+	if (!shell)
+		weston_config_section_get_string(section, "shell", &shell,
+						 "desktop-shell.so");
+
+	if (load_modules(ec, shell, &argc, argv, config) < 0)
+		goto out;
+
+	weston_config_section_get_string(section, "modules", &modules, "");
+	if (load_modules(ec, modules, &argc, argv, config) < 0)
+		goto out;
+
+	if (load_modules(ec, option_modules, &argc, argv, config) < 0)
+		goto out;
+
+	section = weston_config_get_section(config, "keyboard", NULL, NULL);
+	weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
+	if (numlock_on) {
+		wl_list_for_each(seat, &ec->seat_list, link) {
+			if (seat->keyboard)
+				weston_keyboard_set_locks(seat->keyboard,
+							  WESTON_NUM_LOCK,
+							  WESTON_NUM_LOCK);
+		}
+	}
+
+	weston_compositor_wake(ec);
+
+	wl_display_run(display);
+
+	/* Allow for setting return exit code after
+	* wl_display_run returns normally. This is
+	* useful for devs/testers and automated tests
+	* that want to indicate failure status to
+	* testing infrastructure above
+	*/
+	ret = ec->exit_code;
+
+out:
+	weston_compositor_destroy(ec);
+
+out_signals:
+	for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
+		if (signals[i])
+			wl_event_source_remove(signals[i]);
+
+	wl_display_destroy(display);
+
+	weston_log_file_close();
+	weston_config_destroy(config);
+
+	free(backend);
+	free(shell);
+	free(socket_name);
+	free(option_modules);
+	free(log);
+	free(modules);
+
+	return ret;
+}