int
main (int    argc,
      char **argv)
{
    GMainLoop        *main_loop;
    GOptionContext   *context;
    DBusGConnection  *connection;
    MdmSlave         *slave;
    static char      *display_id = NULL;
    MdmSignalHandler *signal_handler;
    static GOptionEntry entries []   = {
        { "display-id", 0, 0, G_OPTION_ARG_STRING, &display_id, N_("Display ID"), N_("ID") },
        { NULL }
    };

    bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
    textdomain (GETTEXT_PACKAGE);
    setlocale (LC_ALL, "");

    mdm_set_fatal_warnings_if_unstable ();

    g_type_init ();

    context = g_option_context_new (_("MATE Display Manager Slave"));
    g_option_context_add_main_entries (context, entries, NULL);

    g_option_context_parse (context, &argc, &argv, NULL);
    g_option_context_free (context);

    connection = get_system_bus ();
    if (connection == NULL) {
        goto out;
    }

    mdm_xerrors_init ();
    mdm_log_init ();

    settings = mdm_settings_new ();
    if (settings == NULL) {
        g_warning ("Unable to initialize settings");
        goto out;
    }

    if (! mdm_settings_direct_init (settings, DATADIR "/mdm/mdm.schemas", "/")) {
        g_warning ("Unable to initialize settings");
        goto out;
    }

    mdm_log_set_debug (is_debug_set ());

    if (display_id == NULL) {
        g_critical ("No display ID set");
        exit (1);
    }

    main_loop = g_main_loop_new (NULL, FALSE);

    signal_handler = mdm_signal_handler_new ();
    mdm_signal_handler_set_fatal_func (signal_handler,
                                       (GDestroyNotify)g_main_loop_quit,
                                       main_loop);
    mdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGILL, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGBUS, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGSEGV, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGABRT, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL);
    mdm_signal_handler_add (signal_handler, SIGUSR2, signal_cb, NULL);

    slave = mdm_product_slave_new (display_id);
    if (slave == NULL) {
        goto out;
    }
    g_signal_connect (slave,
                      "stopped",
                      G_CALLBACK (on_slave_stopped),
                      main_loop);
    mdm_slave_start (slave);

    g_main_loop_run (main_loop);

    if (slave != NULL) {
        g_object_unref (slave);
    }

    if (signal_handler != NULL) {
        g_object_unref (signal_handler);
    }

    if (main_loop != NULL) {
        g_main_loop_unref (main_loop);
    }

out:

    g_debug ("Slave finished");

    return mdm_return_code;
}
Example #2
0
gboolean 
mdm_display_manage (MdmDisplay *d)
{
    pid_t pid;
    int fds[2];

    if (!d) 
	return FALSE;

    mdm_debug ("mdm_display_manage: Managing %s", d->name);

    if (pipe (fds) < 0) {
	    mdm_error ("mdm_display_manage: Cannot create pipe");
    }

    if ( ! mdm_display_check_loop (d))
	    return FALSE;

    if (d->slavepid != 0)
	    mdm_debug ("mdm_display_manage: Old slave pid is %d", (int)d->slavepid);

    /* If we have an old slave process hanging around, kill it */
    /* This shouldn't be a normal code path however, so it doesn't matter
     * that we are hanging */
    whack_old_slave (d, FALSE /* kill_connection */);

    /* Ensure that /tmp/.ICE-unix and /tmp/.X11-unix exist and have the
     * correct permissions */
    mdm_ensure_sanity ();

    d->managetime = time (NULL);

    mdm_debug ("Forking slave process");

    /* Fork slave process */
    pid = d->slavepid = fork ();

    switch (pid) {

    case 0:

	setpgid (0, 0);

	/* Make the slave it's own leader.  This 1) makes killing -pid of
	 * the daemon work more sanely because the daemon can whack the
	 * slave much better itself */
	setsid ();

	/* In the child setup empty mask and set all signals to
	 * default values, we'll make them more fun later */
	mdm_unset_signals ();

	d->slavepid = getpid ();
	
	mdm_connection_close (pipeconn);
	pipeconn = NULL;
	mdm_connection_close (unixconn);
	unixconn = NULL;

	mdm_log_shutdown ();

	/* Debian changes */
#if 0
	/* upstream version */
-	/* Close everything */
-	mdm_close_all_descriptors (0 /* from */, fds[0] /* except */, slave_fifo_pipe_fd /* except2 */);
#endif
	/* Close stdin/stdout/stderr.  Leave others, as pam modules may have them open */
	VE_IGNORE_EINTR (close (0));
	VE_IGNORE_EINTR (close (1));
	VE_IGNORE_EINTR (close (2));
	/* End of Debian changes */

	/* No error checking here - if it's messed the best response
         * is to ignore & try to continue */
	mdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */
	mdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
	mdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */

	mdm_log_init ();

	d->slave_notify_fd = fds[0];

	fcntl (d->slave_notify_fd, F_SETFL, fcntl (d->slave_notify_fd, F_GETFL) | O_NONBLOCK);

	mdm_slave_start (d);
	/* should never retern */

	/* yaikes, how did we ever get here? */
	mdm_server_stop (d);
	_exit (DISPLAY_REMANAGE);

	break;

    case -1:
	d->slavepid = 0;
	mdm_error ("mdm_display_manage: Failed forking MDM slave process for %s", d->name);

	return FALSE;

    default:
	mdm_debug ("mdm_display_manage: Forked slave: %d", (int)pid);
	d->master_notify_fd = fds[1];
	VE_IGNORE_EINTR (close (fds[0]));
	break;
    }

    /* invalidate chosen hostname */
    g_free (d->chosen_hostname);
    d->chosen_hostname = NULL;

    /* use_chooser can only be temporary, if you want it permanent you set it
       up in the server definition with "chooser=true" and it will get set up
       during server command line resolution */
    d->use_chooser = FALSE;

    if (SERVER_IS_LOCAL (d)) {
	    d->dispstat = DISPLAY_ALIVE;
    }

    /* reset sleep to 1, to sleep just in case (avoids X server races) */
    d->sleep_before_run = 1;

    return TRUE;
}