compositor: move the main() to a new main.c file
authorGiulio Camuffo <giuliocamuffo@gmail.com>
Sat, 11 Oct 2014 21:24:25 +0000 (00:24 +0300)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Fri, 10 Jul 2015 09:46:55 +0000 (12:46 +0300)
This commits starts to separate the libweston code from the weston
specific code. As such, the main() is moved, together with signals
handling and configuration handling.

The definition of DEFAULT_REPAINT_WINDOW is left in compositor.c, so the
config loading of repaint_msec is slightly modified to account that.

Acked-by: Bryce Harrington <bryce@osg.samsung.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Makefile.am
src/compositor.c
src/main.c [new file with mode: 0644]

index 4f0a45015eaf89ecac89524891b7cee9c91b61b1..a0d0c196cf30ba5e12a097d948343b922634176e 100644 (file)
@@ -86,6 +86,7 @@ weston_SOURCES =                                      \
        src/timeline.c                                  \
        src/timeline.h                                  \
        src/timeline-object.h                           \
+       src/main.c                                      \
        shared/helpers.h                                \
        shared/matrix.c                                 \
        shared/matrix.h                                 \
index dc3f4a5a66c4d195519637ef660d5257790064ae..150d1fb1e841fa25513298559d3dd975cef5d9a1 100644 (file)
 #include <time.h>
 #include <errno.h>
 
-#ifdef HAVE_LIBUNWIND
-#define UNW_LOCAL_ONLY
-#include <libunwind.h>
-#endif
-
 #include "timeline.h"
 
 #include "compositor.h"
@@ -88,37 +83,6 @@ timespec_to_nsec(const struct timespec *a)
        return (int64_t)a->tv_sec * NSEC_PER_SEC + a->tv_nsec;
 }
 
-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);
@@ -290,12 +254,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)
 {
@@ -4454,17 +4412,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)
 {
@@ -4539,6 +4486,7 @@ weston_compositor_create(struct wl_display *display, void *user_data)
        ec->session_active = 1;
 
        ec->output_id_pool = 0;
+       ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
 
        if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 3,
                              ec, compositor_bind))
@@ -4596,47 +4544,6 @@ fail:
        return NULL;
 }
 
-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);
-
-       s = weston_config_get_section(config, "core", NULL, NULL);
-       weston_config_section_get_int(s, "repaint-window", &ec->repaint_msec,
-                                     DEFAULT_REPAINT_WINDOW);
-       if (ec->repaint_msec < -10 || ec->repaint_msec > 1000) {
-               weston_log("Invalid repaint_window value in config: %d\n",
-                          ec->repaint_msec);
-               ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
-       }
-       weston_log("Output repaint window is %d ms maximum.\n",
-                  ec->repaint_msec);
-
-       return 0;
-}
-
 WL_EXPORT void
 weston_compositor_shutdown(struct weston_compositor *ec)
 {
@@ -4772,160 +4679,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)
 {
@@ -4964,562 +4717,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[])
-{
-       const char *p, *end;
-       char buffer[256];
-       int (*module_init)(struct weston_compositor *ec,
-                          int *argc, char *argv[]);
-
-       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)
-                       return -1;
-               if (module_init(ec, argc, argv) < 0)
-                       return -1;
-               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_HEADLESS_COMPOSITOR)
-                       "\t\t\t\theadless-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"
-               "  -c, --config=FILE\tConfig file to load, defaults to weston.ini\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"
-               "  --use-gl\t\tUse the GL renderer\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"
-               "  --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"
-               "  --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 int
-load_configuration(struct weston_config **config, int32_t noconfig,
-                  const char *config_file)
-{
-       const char *file = "weston.ini";
-       const char *full_path;
-
-       *config = NULL;
-
-       if (config_file)
-               file = config_file;
-
-       if (noconfig == 0)
-               *config = weston_config_parse(file);
-
-       if (*config) {
-               full_path = weston_config_get_full_path(*config);
-
-               weston_log("Using config file '%s'\n", full_path);
-               setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
-
-               return 0;
-       }
-
-       if (config_file && noconfig == 0) {
-               weston_log("fatal: error opening or reading config file"
-                          " '%s'.\n", config_file);
-
-               return -1;
-       }
-
-       weston_log("Starting with no config file.\n");
-       setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
-
-       return 0;
-}
-
-static void
-handle_exit(struct weston_compositor *c)
-{
-       wl_display_terminate(c->wl_display);
-}
-
-int main(int argc, char *argv[])
-{
-       int ret = EXIT_FAILURE;
-       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;
-       char *config_file = NULL;
-       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 },
-               { WESTON_OPTION_STRING, "config", 'c', &config_file },
-       };
-
-       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])
-               goto out_signals;
-
-       if (load_configuration(&config, noconfig, config_file) < 0)
-               goto out_signals;
-
-       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)
-               goto out_signals;
-
-       ec = weston_compositor_create(display, NULL);
-       if (ec == NULL) {
-               weston_log("fatal: failed to create compositor\n");
-               goto out_signals;
-       }
-
-       ec->config = config;
-       if (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->exit = handle_exit;
-
-       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");
-                       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)) {
-               goto out;
-       }
-
-       if (!shell)
-               weston_config_section_get_string(section, "shell", &shell,
-                                                "desktop-shell.so");
-
-       if (load_modules(ec, shell, &argc, argv) < 0)
-               goto out;
-
-       weston_config_section_get_string(section, "modules", &modules, "");
-       if (load_modules(ec, modules, &argc, argv) < 0)
-               goto out;
-
-       if (load_modules(ec, option_modules, &argc, argv) < 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);
-               }
-       }
-
-       for (i = 1; i < argc; i++)
-               weston_log("fatal: unhandled option: %s\n", argv[i]);
-       if (argc > 1)
-               goto out;
-
-       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);
-       if (config)
-               weston_config_destroy(config);
-       weston_log_file_close();
-
-       free(config_file);
-       free(backend);
-       free(shell);
-       free(socket_name);
-       free(option_modules);
-       free(log);
-       free(modules);
-
-       return ret;
-}
 
 /** Destroys the compositor.
  *
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..a2ed2b4
--- /dev/null
@@ -0,0 +1,848 @@
+/*
+ * Copyright Â© 2010-2011 Intel Corporation
+ * Copyright Â© 2008-2011 Kristian Høgsberg
+ * Copyright Â© 2012-2015 Collabora, Ltd.
+ *
+ * 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 (including the
+ * next paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS
+ * 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.
+ */
+
+#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 "../shared/helpers.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_HEADLESS_COMPOSITOR)
+                       "\t\t\t\theadless-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"
+               "  -c, --config=FILE\tConfig file to load, defaults to weston.ini\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"
+               "  --use-gl\t\tUse the GL renderer\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"
+               "  --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"
+               "  --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[])
+{
+       const char *p, *end;
+       char buffer[256];
+       int (*module_init)(struct weston_compositor *ec,
+                          int *argc, char *argv[]);
+
+       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)
+                       return -1;
+               if (module_init(ec, argc, argv) < 0)
+                       return -1;
+               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;
+       int repaint_msec;
+
+       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);
+
+       s = weston_config_get_section(config, "core", NULL, NULL);
+       weston_config_section_get_int(s, "repaint-window", &repaint_msec,
+                                     ec->repaint_msec);
+       if (repaint_msec < -10 || repaint_msec > 1000) {
+               weston_log("Invalid repaint_window value in config: %d\n",
+                          repaint_msec);
+       } else {
+               ec->repaint_msec = repaint_msec;
+       }
+       weston_log("Output repaint window is %d ms maximum.\n",
+                  ec->repaint_msec);
+
+       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 int
+load_configuration(struct weston_config **config, int32_t noconfig,
+                  const char *config_file)
+{
+       const char *file = "weston.ini";
+       const char *full_path;
+
+       *config = NULL;
+
+       if (config_file)
+               file = config_file;
+
+       if (noconfig == 0)
+               *config = weston_config_parse(file);
+
+       if (*config) {
+               full_path = weston_config_get_full_path(*config);
+
+               weston_log("Using config file '%s'\n", full_path);
+               setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
+
+               return 0;
+       }
+
+       if (config_file && noconfig == 0) {
+               weston_log("fatal: error opening or reading config file"
+                          " '%s'.\n", config_file);
+
+               return -1;
+       }
+
+       weston_log("Starting with no config file.\n");
+       setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
+
+       return 0;
+}
+
+static void
+handle_exit(struct weston_compositor *c)
+{
+       wl_display_terminate(c->wl_display);
+}
+
+int main(int argc, char *argv[])
+{
+       int ret = EXIT_FAILURE;
+       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;
+       char *config_file = NULL;
+       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 },
+               { WESTON_OPTION_STRING, "config", 'c', &config_file },
+       };
+
+       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])
+               goto out_signals;
+
+       if (load_configuration(&config, noconfig, config_file) < 0)
+               goto out_signals;
+
+       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)
+               goto out_signals;
+
+       ec = weston_compositor_create(display, NULL);
+       if (ec == NULL) {
+               weston_log("fatal: failed to create compositor\n");
+               goto out_signals;
+       }
+
+       ec->config = config;
+       if (weston_compositor_init_config(ec, config) < 0)
+               goto out_signals;
+
+       if (backend_init(ec, &argc, argv, config) < 0) {
+               weston_log("fatal: failed to create compositor backend\n");
+               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 = handle_exit;
+
+       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");
+                       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)) {
+               goto out;
+       }
+
+       if (!shell)
+               weston_config_section_get_string(section, "shell", &shell,
+                                                "desktop-shell.so");
+
+       if (load_modules(ec, shell, &argc, argv) < 0)
+               goto out;
+
+       weston_config_section_get_string(section, "modules", &modules, "");
+       if (load_modules(ec, modules, &argc, argv) < 0)
+               goto out;
+
+       if (load_modules(ec, option_modules, &argc, argv) < 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);
+               }
+       }
+
+       for (i = 1; i < argc; i++)
+               weston_log("fatal: unhandled option: %s\n", argv[i]);
+       if (argc > 1)
+               goto out;
+
+       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();
+
+       if (config)
+               weston_config_destroy(config);
+       free(config_file);
+       free(backend);
+       free(shell);
+       free(socket_name);
+       free(option_modules);
+       free(log);
+       free(modules);
+
+       return ret;
+}