summaryrefslogtreecommitdiff
path: root/daemon/gdm.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/gdm.c')
-rw-r--r--daemon/gdm.c4337
1 files changed, 0 insertions, 4337 deletions
diff --git a/daemon/gdm.c b/daemon/gdm.c
deleted file mode 100644
index b6d73a03..00000000
--- a/daemon/gdm.c
+++ /dev/null
@@ -1,4337 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * GDM - The GNOME Display Manager
- * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "config.h"
-
-#include <signal.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <unistd.h>
-#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
-#include <sched.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/resource.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <grp.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <locale.h>
-#include <dirent.h>
-
-#ifdef HAVE_CHKAUTHATTR
-#include <auth_attr.h>
-#include <secdb.h>
-#endif
-
-/* This should be moved to auth.c I suppose */
-
-#include <X11/Xauth.h>
-#include <glib/gi18n.h>
-#include <glib-object.h>
-
-#include <gtk/gtk.h>
-
-/* Needed for signal handling */
-#include "gdm-common.h"
-
-#include "gdm.h"
-#include "misc.h"
-#include "slave.h"
-#include "server.h"
-#include "verify.h"
-#include "display.h"
-#include "choose.h"
-#include "getvt.h"
-#include "gdm-net.h"
-#include "cookie.h"
-#include "filecheck.h"
-#include "errorgui.h"
-
-#include "gdm-socket-protocol.h"
-#include "gdm-daemon-config.h"
-#include "gdm-log.h"
-
-#include "xdmcp.h"
-
-#define DYNAMIC_ADD 0
-#define DYNAMIC_RELEASE 1
-#define DYNAMIC_REMOVE 2
-
-#ifdef HAVE_LOGINDEVPERM
-#include <libdevinfo.h>
-#endif /* HAVE_LOGINDEVPERM */
-
-/* Local functions */
-static void gdm_handle_message (GdmConnection *conn,
- const gchar *msg,
- gpointer data);
-static void gdm_handle_user_message (GdmConnection *conn,
- const gchar *msg,
- gpointer data);
-static void gdm_daemonify (void);
-static void gdm_safe_restart (void);
-static void gdm_try_logout_action (GdmDisplay *disp);
-static void gdm_restart_now (void);
-static void handle_flexi_server (GdmConnection *conn,
- int type,
- const gchar *server,
- gboolean handled,
- gboolean chooser,
- const gchar *xnest_disp,
- uid_t xnest_uid,
- const gchar *xnest_auth_file,
- const gchar *xnest_cookie,
- const gchar *username);
-static void custom_cmd_restart (long cmd_id);
-static void custom_cmd_no_restart (long cmd_id);
-
-/* Global vars */
-gint flexi_servers = 0; /* Number of flexi servers */
-static pid_t extra_process = 0; /* An extra process. Used for quickie
- processes, so that they also get whacked */
-static int extra_status = 0; /* Last status from the last extra process */
-
-gboolean gdm_wait_for_go = FALSE; /* wait for a GO in the fifo */
-
-static gboolean print_version = FALSE; /* print version number and quit */
-static gboolean preserve_ld_vars = FALSE; /* Preserve the ld environment variables */
-static gboolean no_daemon = FALSE; /* Do not daemonize */
-static gboolean no_console = FALSE; /* There are no static servers, this means,
- don't run static servers and second,
- don't display info on the console */
-
-GdmConnection *fifoconn = NULL; /* Fifo connection */
-GdmConnection *pipeconn = NULL; /* slavepipe (handled just like Fifo for compatibility) connection */
-GdmConnection *unixconn = NULL; /* UNIX Socket connection */
-int slave_fifo_pipe_fd = -1; /* the slavepipe connection */
-
-unsigned char *gdm_global_cookie = NULL;
-unsigned char *gdm_global_bcookie = NULL;
-
-gboolean gdm_first_login = TRUE;
-
-static GdmLogoutAction safe_logout_action = GDM_LOGOUT_ACTION_NONE;
-
-/* set in the main function */
-gchar **stored_argv = NULL;
-int stored_argc = 0;
-
-static gchar *config_file = NULL;
-static gboolean gdm_restart_mode = FALSE;
-
-static GMainLoop *main_loop = NULL;
-
-static gboolean monte_carlo_sqrt2 = FALSE;
-
-/*
- * lookup display number if the display number is
- * exists then clear the remove flag and return TRUE
- * otherwise return FALSE
- */
-static gboolean
-mark_display_exists (int num)
-{
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
- if (disp->dispnum == num) {
- disp->removeconf = FALSE;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * gdm_daemonify:
- *
- * Detach gdm daemon from the controlling terminal
- */
-
-static void
-gdm_daemonify (void)
-{
- FILE *pf;
- pid_t pid;
-
- pid = fork ();
- if (pid > 0) {
- const char *pidfile = GDM_PID_FILE;
-
- errno = 0;
- if ((pf = gdm_safe_fopen_w (pidfile)) != NULL) {
- errno = 0;
- VE_IGNORE_EINTR (fprintf (pf, "%d\n", (int)pid));
- VE_IGNORE_EINTR (fclose (pf));
- if G_UNLIKELY (errno != 0) {
- /* FIXME: how to handle this? */
- gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"),
- pidfile, strerror (errno));
- gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"),
- pidfile, strerror (errno));
-
- }
- } else if G_UNLIKELY (errno != 0) {
- /* FIXME: how to handle this? */
- gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"),
- pidfile, strerror (errno));
- gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"),
- pidfile, strerror (errno));
-
- }
-
- exit (EXIT_SUCCESS);
- }
-
- if G_UNLIKELY (pid < 0)
- gdm_fail (_("%s: fork () failed!"), "gdm_daemonify");
-
- if G_UNLIKELY (setsid () < 0)
- gdm_fail (_("%s: setsid () failed: %s!"), "gdm_daemonify",
- strerror (errno));
-
- VE_IGNORE_EINTR (g_chdir (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)));
- umask (022);
-
- VE_IGNORE_EINTR (close (0));
- VE_IGNORE_EINTR (close (1));
- VE_IGNORE_EINTR (close (2));
-
- gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */
- gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
- gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
-}
-
-static void
-gdm_start_first_unborn_local (int delay)
-{
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- /* tickle the random stuff */
- gdm_random_tick ();
-
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
-
- if (d != NULL &&
- d->type == TYPE_STATIC &&
- d->dispstat == DISPLAY_UNBORN) {
- GdmXserver *svr;
- g_debug ("gdm_start_first_unborn_local: "
- "Starting %s", d->name);
-
- /* well sleep at least 'delay' seconds
- * before starting */
- d->sleep_before_run = delay;
-
- /* only the first static display has
- * timed login going on */
- if (gdm_first_login)
- d->timed_login_ok = TRUE;
-
- svr = gdm_server_resolve (d);
-
- if ( ! gdm_display_manage (d)) {
- gdm_display_unmanage (d);
- /* only the first static display where
- we actually log in gets
- autologged in */
- if (svr != NULL &&
- svr->handled &&
- ! svr->chooser)
- gdm_first_login = FALSE;
- } else {
- /* only the first static display where
- we actually log in gets
- autologged in */
- if (svr != NULL &&
- svr->handled &&
- ! svr->chooser)
- gdm_first_login = FALSE;
- break;
- }
- }
- }
-}
-
-void
-gdm_final_cleanup (void)
-{
- GSList *list, *li;
- const char *pidfile;
- gboolean first;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- g_debug ("gdm_final_cleanup");
-
- if (extra_process > 1) {
- /* we sigterm extra processes, and we
- * don't wait */
- kill (-(extra_process), SIGTERM);
- extra_process = 0;
- }
-
- /* First off whack all XDMCP and FLEXI_XNEST
- slaves, we'll wait for them later */
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- if (SERVER_IS_XDMCP (d) ||
- SERVER_IS_PROXY (d)) {
- /* set to DEAD so that we won't kill it again */
- d->dispstat = DISPLAY_DEAD;
- if (d->slavepid > 1)
- kill (d->slavepid, SIGTERM);
- }
- }
-
- /* Now completely unmanage the static servers */
- first = TRUE;
- list = g_slist_copy (displays);
- /* somewhat of a hack to kill last server
- * started first. This mostly makes things end up on
- * the right vt */
- list = g_slist_reverse (list);
- for (li = list; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- if (SERVER_IS_XDMCP (d) ||
- SERVER_IS_PROXY (d))
- continue;
- /* HACK! Wait 2 seconds between killing of static servers
- * because X is stupid and full of races and will otherwise
- * hang my keyboard */
- if ( ! first) {
- /* there could be signals happening
- here */
- gdm_sleep_no_signal (2);
- }
- first = FALSE;
- gdm_display_unmanage (d);
- }
- g_slist_free (list);
-
- /* and now kill and wait for the XDMCP and FLEXI_XNEST
- slaves. unmanage will not kill slaves we have already
- killed unless a SIGTERM was sent in the meantime */
-
- list = g_slist_copy (displays);
- for (li = list; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- if (SERVER_IS_XDMCP (d) ||
- SERVER_IS_PROXY (d))
- gdm_display_unmanage (d);
- }
- g_slist_free (list);
-
- /* Close stuff */
-
- if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
- gdm_xdmcp_close ();
-
- if (fifoconn != NULL) {
- char *path;
- gdm_connection_close (fifoconn);
- path = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL);
- VE_IGNORE_EINTR (g_unlink (path));
- g_free (path);
- fifoconn = NULL;
- }
-
- if (pipeconn != NULL) {
- gdm_connection_close (pipeconn);
- pipeconn = NULL;
- }
-
- if (slave_fifo_pipe_fd >= 0) {
- VE_IGNORE_EINTR (close (slave_fifo_pipe_fd));
- slave_fifo_pipe_fd = -1;
- }
-
- if (unixconn != NULL) {
- gdm_connection_close (unixconn);
- VE_IGNORE_EINTR (g_unlink (GDM_SUP_SOCKET));
- unixconn = NULL;
- }
-
- pidfile = GDM_PID_FILE;
- if (pidfile != NULL) {
- VE_IGNORE_EINTR (g_unlink (pidfile));
- }
-
-#ifdef HAVE_LOGINDEVPERM
- (void) di_devperm_logout ("/dev/console");
-#endif /* HAVE_LOGINDEVPERM */
-}
-
-#ifdef __sun
-void
-gdm_rmdir (char *thedir)
-{
- DIR *odir;
- struct stat buf;
- struct dirent *dp;
- char thefile[FILENAME_MAX];
-
- if ((stat(thedir, &buf) == -1) || ! S_ISDIR(buf.st_mode))
- return ;
-
- if ((rmdir (thedir) == -1) && (errno == EEXIST))
- {
- odir = opendir (thedir);
- do {
- errno = 0;
- if ((dp = readdir (odir)) != NULL)
- {
- if (strcmp (dp->d_name, ".") == 0 ||
- strcmp (dp->d_name, "..") == 0)
- continue ;
- snprintf (thefile, FILENAME_MAX, "%s/%s", thedir, dp->d_name);
- if (stat (thefile, &buf) == -1)
- continue ;
- if (S_ISDIR(buf.st_mode))
- gdm_rmdir (thefile);
- else
- g_unlink (thefile);
- }
- } while (dp != NULL);
- closedir (odir);
- rmdir (thedir);
- }
-}
-#endif
-
-static gboolean
-deal_with_x_crashes (GdmDisplay *d)
-{
- gboolean just_abort = FALSE;
- const char *failsafe = gdm_daemon_config_get_value_string (GDM_KEY_FAILSAFE_XSERVER);
- const char *keepscrashing = gdm_daemon_config_get_value_string (GDM_KEY_X_KEEPS_CRASHING);
-
- if ( ! d->failsafe_xserver &&
- ! ve_string_empty (failsafe)) {
- char *bin = ve_first_word (failsafe);
- /* Yay we have a failsafe */
- if ( ! ve_string_empty (bin) &&
- g_access (bin, X_OK) == 0) {
- gdm_info (_("%s: Trying failsafe X "
- "server %s"),
- "deal_with_x_crashes",
- failsafe);
- g_free (bin);
- g_free (d->command);
- d->command = g_strdup (failsafe);
- d->failsafe_xserver = TRUE;
- return TRUE;
- }
- g_free (bin);
- }
-
- /* Eeek X keeps crashing, let's try the XKeepsCrashing script */
- if ( ! ve_string_empty (keepscrashing) &&
- g_access (keepscrashing, X_OK|R_OK) == 0) {
- pid_t pid;
-
- gdm_info (_("%s: Running the "
- "XKeepsCrashing script"),
- "deal_with_x_crashes");
-
- extra_process = pid = fork ();
- if (pid < 0)
- extra_process = 0;
-
- if (pid == 0) {
- char *argv[2];
- char *xlog = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
-
- gdm_unset_signals ();
-
- /* Also make a new process group so that we may use
- * kill -(extra_process) to kill extra process and all its
- * possible children */
- setsid ();
-
- if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
- gdm_xdmcp_close ();
-
- gdm_close_all_descriptors (0 /* from */, -1 /* except */, -1 /* except2 */);
-
- /* No error checking here - if it's messed the best response
- * is to ignore & try to continue */
- gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */
- gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
- gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
-
- argv[0] = (char *)gdm_daemon_config_get_value_string (GDM_KEY_X_KEEPS_CRASHING);
- argv[1] = NULL;
-
- gdm_restoreenv ();
-
- /* unset DISPLAY and XAUTHORITY if they exist
- * so that gdialog (if used) doesn't get confused */
- g_unsetenv ("DISPLAY");
- g_unsetenv ("XAUTHORITY");
-
- /* some promised variables */
- g_setenv ("XLOG", xlog, TRUE);
- g_setenv ("BINDIR", BINDIR, TRUE);
- g_setenv ("SBINDIR", SBINDIR, TRUE);
- g_setenv ("LIBEXECDIR", LIBEXECDIR, TRUE);
- g_setenv ("SYSCONFDIR", GDMCONFDIR, TRUE);
-
- /* To enable gettext stuff in the script */
- g_setenv ("TEXTDOMAIN", GETTEXT_PACKAGE, TRUE);
- g_setenv ("TEXTDOMAINDIR", GNOMELOCALEDIR, TRUE);
-
- if ( ! gdm_ok_console_language ()) {
- g_unsetenv ("LANG");
- g_unsetenv ("LC_ALL");
- g_unsetenv ("LC_MESSAGES");
- g_setenv ("LANG", "C", TRUE);
- g_setenv ("UNSAFE_TO_TRANSLATE", "yes", TRUE);
- }
-
- VE_IGNORE_EINTR (execv (argv[0], argv));
-
- /* yaikes! */
- _exit (32);
- } else if (pid > 0) {
- int status;
-
- if (extra_process > 1) {
- int ret;
- int killsignal = SIGTERM;
- int storeerrno;
- errno = 0;
- ret = waitpid (extra_process, &status, WNOHANG);
- do {
- /* wait for some signal, yes this is a race */
- if (ret <= 0)
- sleep (10);
- errno = 0;
- ret = waitpid (extra_process, &status, WNOHANG);
- storeerrno = errno;
- if ((ret <= 0) && gdm_daemon_config_signal_terminthup_was_notified ()) {
- kill (-(extra_process), killsignal);
- killsignal = SIGKILL;
- }
- } while (ret == 0 || (ret < 0 && storeerrno == EINTR));
- }
- extra_process = 0;
-
- if (WIFEXITED (status) &&
- WEXITSTATUS (status) == 0) {
- /* Yay, the user wants to try again, so
- * here we go */
- return TRUE;
- } else if (WIFEXITED (status) &&
- WEXITSTATUS (status) == 32) {
- /* We couldn't run the script, just drop through */
- ;
- } else {
- /* Things went wrong. */
- just_abort = TRUE;
- }
- }
-
- /* if we failed to fork, or something else has happened,
- * we fall through to the other options below */
- }
-
- /* if we have "open" we can talk to the user, not as user
- * friendly as the above script, but getting there */
- if ( ! just_abort &&
- g_access (LIBEXECDIR "/gdmopen", X_OK) == 0) {
- /* Shit if we knew what the program was to tell the user,
- * the above script would have been defined and we'd run
- * it for them */
- const char *error =
- C_(N_("The X server (your graphical interface) "
- "cannot be started. It is likely that it is not "
- "set up correctly. You will need to log in on a "
- "console and rerun the X configuration "
- "application, then restart GDM."));
- gdm_text_message_dialog (error);
- } /* else {
- * At this point .... screw the user, we don't know how to
- * talk to him. He's on some 'l33t system anyway, so syslog
- * reading will do him good
- * } */
-
- gdm_error (_("Failed to start X server several times in a short time period; disabling display %s"), d->name);
-
- return FALSE;
-}
-
-static gboolean
-try_command (const char *command,
- int *statusp)
-{
- GError *error;
- gboolean res;
- int status;
-
- g_debug ("Running %s", command);
-
- error = NULL;
- res = g_spawn_command_line_sync (command, NULL, NULL, &status, &error);
- if (error != NULL) {
- g_warning ("Command failed %s: %s", command, error->message);
- g_error_free (error);
- }
-
- *statusp = 0;
-
- if (WIFEXITED (status)) {
- *statusp = WEXITSTATUS (status);
- }
-
- return res;
-}
-
-static gboolean
-try_commands (const char **array)
-{
- int i;
- int status;
- gboolean ret;
-
- ret = FALSE;
-
- /* the idea here is to try the first available command and return if it succeeded */
-
- for (i = 0; array[i] != NULL; i++) {
- if (try_command (array[i], &status)) {
- ret = (status == 0);
-
- if (! ret) {
- gdm_error (_("command failed %s: %d"), array[i], status);
- }
-
- break;
- }
- }
-
- return ret;
-}
-
-static void
-suspend_machine (void)
-{
- const gchar **suspend;
-
- suspend = gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND);
-
- gdm_info (_("Master suspending..."));
-
- if (suspend == NULL) {
- return;
- }
-
- try_commands (suspend);
-}
-
-#ifdef __linux__
-static void
-change_to_first_and_clear (gboolean restart)
-{
- gdm_change_vt (1);
- VE_IGNORE_EINTR (close (0));
- VE_IGNORE_EINTR (close (1));
- VE_IGNORE_EINTR (close (2));
- VE_IGNORE_EINTR (open ("/dev/tty1", O_WRONLY));
- VE_IGNORE_EINTR (open ("/dev/tty1", O_WRONLY));
- VE_IGNORE_EINTR (open ("/dev/tty1", O_WRONLY));
-
- g_setenv ("TERM", "linux", TRUE);
-
- /* evil hack that will get the fonts right */
- if (g_access ("/bin/bash", X_OK) == 0)
- system ("/bin/bash -l -c /bin/true");
-
- /* clear screen and set to red */
- printf ("\033[H\033[J\n\n\033[1m---\n\033[1;31m ");
-
- if (restart)
- printf (_("System is restarting, please wait ..."));
- else
- printf (_("System is shutting down, please wait ..."));
- /* set to black */
- printf ("\033[0m\n\033[1m---\033[0m\n\n");
-}
-#endif /* __linux__ */
-
-static void
-halt_machine (void)
-{
- const char **s;
-
- g_debug (_("Master halting..."));
-
- s = gdm_daemon_config_get_value_string_array (GDM_KEY_HALT);
-
- if (try_commands (s)) {
- /* maybe these don't run but oh well - there isn't
- really a good way to know a priori if the command
- will succeed. */
- gdm_final_cleanup ();
- VE_IGNORE_EINTR (g_chdir ("/"));
-#ifdef __linux__
- change_to_first_and_clear (FALSE);
-#endif /* __linux */
-
- }
-}
-
-static void
-restart_machine (void)
-{
- const char **s;
-
- g_debug (_("Restarting computer..."));
-
- s = gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT);
-
- if (try_commands (s)) {
- gdm_final_cleanup ();
- VE_IGNORE_EINTR (g_chdir ("/"));
-
-#ifdef __linux__
- change_to_first_and_clear (TRUE);
-#endif /* __linux */
-
- }
-}
-
-static void
-custom_cmd (long cmd_id)
-{
- gchar * key_string;
-
- if (cmd_id < 0 || cmd_id >= GDM_CUSTOM_COMMAND_MAX) {
- /* We are just feeling very paranoid */
- gdm_error (_("custom_cmd: Custom command index %ld outside permitted range [0,%d)"),
- cmd_id, GDM_CUSTOM_COMMAND_MAX);
- return;
- }
-
- key_string = g_strdup_printf ("%s%ld=", GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, cmd_id);
- if (gdm_daemon_config_get_value_bool (key_string))
- custom_cmd_no_restart (cmd_id);
- else
- custom_cmd_restart (cmd_id);
-
- g_free(key_string);
-}
-
-static void
-custom_cmd_restart (long cmd_id)
-{
- gchar * key_string;
- char **argv;
- const char *s;
-
- g_debug (_("Executing custom command %ld with restart option..."), cmd_id);
-
- gdm_final_cleanup ();
- VE_IGNORE_EINTR (g_chdir ("/"));
-
-#ifdef __linux__
- change_to_first_and_clear (TRUE);
-#endif /* __linux */
-
- key_string = g_strdup_printf ("%s%ld=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id);
-
- argv = NULL;
- s = gdm_daemon_config_get_value_string (key_string);
- g_free (key_string);
- if (s != NULL) {
- g_shell_parse_argv (s, NULL, &argv, NULL);
- }
-
- if (argv != NULL && argv[0] != NULL)
- VE_IGNORE_EINTR (execv (argv[0], argv));
-
- g_strfreev (argv);
-
- gdm_error (_("%s: Execution of custom command failed: %s"),
- "gdm_child_action", strerror (errno));
-}
-
-static void
-custom_cmd_no_restart (long cmd_id)
-{
- pid_t pid;
-
- g_debug (_("Executing custom command %ld with no restart option ..."), cmd_id);
-
- pid = fork ();
-
- if (pid < 0) {
- /*failed fork*/
- gdm_error (_("custom_cmd: forking process for custom command %ld failed"), cmd_id);
- return;
- }
- else if (pid == 0) {
- /* child */
- char **argv;
- const char *s;
- gchar *key_string;
-
- key_string = g_strdup_printf ("%s%ld=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id);
-
- argv = NULL;
- s = gdm_daemon_config_get_value_string (key_string);
- g_free (key_string);
- if (s != NULL) {
- g_shell_parse_argv (s, NULL, &argv, NULL);
- }
-
- if (argv != NULL && argv[0] != NULL)
- VE_IGNORE_EINTR (execv (argv[0], argv));
-
- g_strfreev (argv);
-
- gdm_error (_("%s: Execution of custom command failed: %s"),
- "gdm_child_action", strerror (errno));
- _exit (0);
- }
- else {
- /* parent */
- gint exitstatus = 0, status;
- pid_t p_stat = waitpid (1, &exitstatus, WNOHANG);
- if (p_stat > 0) {
- if G_LIKELY (WIFEXITED (exitstatus)){
- status = WEXITSTATUS (exitstatus);
- g_debug (_("custom_cmd: child %d returned %d"), p_stat, status);
- }
- return;
- }
- }
-}
-
-static gboolean
-gdm_cleanup_children (void)
-{
- pid_t pid;
- gint exitstatus = 0, status;
- GdmDisplay *d = NULL;
- gboolean crashed;
- gboolean sysmenu;
-
- /* Pid and exit status of slave that died */
- pid = waitpid (-1, &exitstatus, WNOHANG);
-
- if (pid <= 0)
- return FALSE;
-
- if G_LIKELY (WIFEXITED (exitstatus)) {
- status = WEXITSTATUS (exitstatus);
- crashed = FALSE;
- g_debug ("gdm_cleanup_children: child %d returned %d", pid, status);
- } else {
- status = EXIT_SUCCESS;
- crashed = TRUE;
- if (WIFSIGNALED (exitstatus)) {
- if (WTERMSIG (exitstatus) == SIGTERM ||
- WTERMSIG (exitstatus) == SIGINT) {
- /* we send these signals, sometimes children don't handle them */
- g_debug ("gdm_cleanup_children: child %d died of signal %d (TERM/INT)", pid,
- (int)WTERMSIG (exitstatus));
- } else {
- gdm_error ("gdm_cleanup_children: child %d crashed of signal %d", pid,
- (int)WTERMSIG (exitstatus));
- }
- } else {
- gdm_error ("gdm_cleanup_children: child %d crashed", pid);
- }
- }
-
- if (pid == extra_process) {
- /* an extra process died, yay! */
- extra_process = 0;
- extra_status = exitstatus;
- return TRUE;
- }
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (pid);
-
- if (d == NULL)
- return TRUE;
-
- /* whack connections about this display */
- if (unixconn != NULL)
- gdm_kill_subconnections_with_display (unixconn, d);
-
- if G_UNLIKELY (crashed) {
- gdm_error ("gdm_cleanup_children: Slave crashed, killing its "
- "children");
-
- if (d->sesspid > 1)
- kill (-(d->sesspid), SIGTERM);
- d->sesspid = 0;
- if (d->greetpid > 1)
- kill (-(d->greetpid), SIGTERM);
- d->greetpid = 0;
- if (d->chooserpid > 1)
- kill (-(d->chooserpid), SIGTERM);
- d->chooserpid = 0;
- if (d->servpid > 1)
- kill (d->servpid, SIGTERM);
- d->servpid = 0;
-
- if (gdm_daemon_config_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS)) {
- /* XXX - This needs to be handled better */
- gdm_server_whack_lockfile (d);
- }
-
- /* race avoider */
- gdm_sleep_no_signal (1);
- }
-
- /* null all these, they are not valid most definately */
- d->servpid = 0;
- d->sesspid = 0;
- d->greetpid = 0;
- d->chooserpid = 0;
-
- /* definately not logged in now */
- d->logged_in = FALSE;
- g_free (d->login);
- d->login = NULL;
-
- /* Declare the display dead */
- d->slavepid = 0;
- d->dispstat = DISPLAY_DEAD;
-
- sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name);
-
- if ( ! sysmenu &&
- (status == DISPLAY_RESTARTGDM ||
- status == DISPLAY_REBOOT ||
- status == DISPLAY_SUSPEND ||
- status == DISPLAY_HALT)) {
- gdm_info (_("Restart GDM, Restart machine, Suspend, or Halt request when there is no system menu from display %s"), d->name);
- status = DISPLAY_REMANAGE;
- }
-
- if ( ! d->attached &&
- (status == DISPLAY_RESTARTGDM ||
- status == DISPLAY_REBOOT ||
- status == DISPLAY_SUSPEND ||
- status == DISPLAY_HALT)) {
- gdm_info (_("Restart GDM, Restart machine, Suspend or Halt request from a non-static display %s"), d->name);
- status = DISPLAY_REMANAGE;
- }
-
- if (status == DISPLAY_RUN_CHOOSER) {
- /* use the chooser on the next run (but only if allowed) */
- if (sysmenu &&
- gdm_daemon_config_get_value_bool_per_display (GDM_KEY_CHOOSER_BUTTON, d->name))
- d->use_chooser = TRUE;
- status = DISPLAY_REMANAGE;
- /* go around the display loop detection, these are short
- * sessions, so this decreases the chances of the loop
- * detection being hit */
- d->last_loop_start_time = 0;
- }
-
- if (status == DISPLAY_CHOSEN) {
- /* forget about this indirect id, since this
- * display will be dead very soon, and we don't want it
- * to take the indirect display with it */
- d->indirect_id = 0;
- status = DISPLAY_REMANAGE;
- }
-
- if (status == DISPLAY_GREETERFAILED) {
- if (d->managetime + 10 >= time (NULL)) {
- d->try_different_greeter = TRUE;
- } else {
- d->try_different_greeter = FALSE;
- }
- /* now just remanage */
- status = DISPLAY_REMANAGE;
- } else {
- d->try_different_greeter = FALSE;
- }
-
- /* checkout if we can actually do stuff */
- switch (status) {
- case DISPLAY_REBOOT:
- if (gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) == NULL)
- status = DISPLAY_REMANAGE;
- break;
- case DISPLAY_HALT:
- if (gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) == NULL)
- status = DISPLAY_REMANAGE;
- break;
- case DISPLAY_SUSPEND:
- if (gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) == NULL)
- status = DISPLAY_REMANAGE;
- break;
- default:
- break;
- }
-
- /* if we crashed clear the theme */
- if (crashed) {
- g_free (d->theme_name);
- d->theme_name = NULL;
- }
-
- start_autopsy:
-
- /* Autopsy */
- switch (status) {
-
- case DISPLAY_ABORT: /* Bury this display for good */
- gdm_info (_("%s: Aborting display %s"),
- "gdm_child_action", d->name);
-
- gdm_try_logout_action (d);
- gdm_safe_restart ();
-
- gdm_display_unmanage (d);
-
- /* If there are some pending statics, start them now */
- gdm_start_first_unborn_local (3 /* delay */);
- break;
-
- case DISPLAY_REBOOT: /* Restart machine */
- restart_machine ();
-
- status = DISPLAY_REMANAGE;
- goto start_autopsy;
- break;
-
- case DISPLAY_HALT: /* Halt machine */
- halt_machine ();
-
- status = DISPLAY_REMANAGE;
- goto start_autopsy;
- break;
-
- case DISPLAY_SUSPEND: /* Suspend machine */
- /* XXX: this is ugly, why should there be a suspend like this,
- * see GDM_SOP_SUSPEND_MACHINE */
- suspend_machine ();
-
- status = DISPLAY_REMANAGE;
- goto start_autopsy;
- break;
-
- case DISPLAY_RESTARTGDM:
- gdm_restart_now ();
- break;
-
- case DISPLAY_XFAILED: /* X sucks */
- g_debug ("X failed!");
- /* inform about error if needed */
- if (d->socket_conn != NULL) {
- GdmConnection *conn = d->socket_conn;
- d->socket_conn = NULL;
- gdm_connection_set_close_notify (conn, NULL, NULL);
- gdm_connection_write (conn, "ERROR 3 X failed\n");
- }
-
- gdm_try_logout_action (d);
- gdm_safe_restart ();
-
- /* in remote/flexi case just drop to _REMANAGE */
- if (d->type == TYPE_STATIC) {
- time_t now = time (NULL);
- d->x_faileds++;
- /* This really is likely the first time if it's been,
- some time, say 5 minutes */
- if (now - d->last_x_failed > (5*60)) {
- /* reset */
- d->x_faileds = 1;
- d->last_x_failed = now;
- /* well sleep at least 3 seconds before starting */
- d->sleep_before_run = 3;
- } else if (d->x_faileds >= 3) {
- g_debug ("gdm_child_action: dealing with X crashes");
- if ( ! deal_with_x_crashes (d)) {
- g_debug ("gdm_child_action: Aborting display");
- /* an original way to deal with these things:
- * "Screw you guys, I'm going home!" */
- gdm_display_unmanage (d);
-
- /* If there are some pending statics,
- * start them now */
- gdm_start_first_unborn_local (3 /* delay */);
- break;
- }
- g_debug ("gdm_child_action: Trying again");
-
- /* reset */
- d->x_faileds = 0;
- d->last_x_failed = 0;
- } else {
- /* well sleep at least 3 seconds before starting */
- d->sleep_before_run = 3;
- }
- /* go around the display loop detection, we're doing
- * our own here */
- d->last_loop_start_time = 0;
- }
- /* fall through */
-
- case DISPLAY_REMANAGE: /* Remanage display */
- default:
- g_debug ("gdm_child_action: In remanage");
-
- /* if we did REMANAGE, that means that we're no longer failing */
- if (status == DISPLAY_REMANAGE) {
- /* reset */
- d->x_faileds = 0;
- d->last_x_failed = 0;
- }
-
- /* inform about error if needed */
- if (d->socket_conn != NULL) {
- GdmConnection *conn = d->socket_conn;
- d->socket_conn = NULL;
- gdm_connection_set_close_notify (conn, NULL, NULL);
- gdm_connection_write (conn, "ERROR 2 Startup errors\n");
- }
-
- gdm_try_logout_action (d);
- gdm_safe_restart ();
-
- /* This is a static server so we start a new slave */
- if (d->type == TYPE_STATIC) {
- if ( ! gdm_display_manage (d)) {
- gdm_display_unmanage (d);
- /* If there are some pending statics,
- * start them now */
- gdm_start_first_unborn_local (3 /* delay */);
- }
- } else if (d->type == TYPE_FLEXI || d->type == TYPE_FLEXI_XNEST) {
- /* if this was a chooser session and we have chosen a host,
- then we don't want to unmanage, we want to manage and
- choose that host */
- if (d->chosen_hostname != NULL || d->use_chooser) {
- if ( ! gdm_display_manage (d)) {
- gdm_display_unmanage (d);
- }
- } else {
- /* else, this is a one time thing */
- gdm_display_unmanage (d);
- }
- /* Remote displays will send a request to be managed */
- } else /* TYPE_XDMCP */ {
- gdm_display_unmanage (d);
- }
-
- break;
- }
-
- gdm_try_logout_action (d);
- gdm_safe_restart ();
-
- return TRUE;
-}
-
-static void
-gdm_restart_now (void)
-{
- gdm_info (_("GDM restarting ..."));
- gdm_final_cleanup ();
- gdm_restoreenv ();
- VE_IGNORE_EINTR (execvp (stored_argv[0], stored_argv));
- gdm_error (_("Failed to restart self"));
- _exit (1);
-}
-
-static void
-gdm_safe_restart (void)
-{
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- if ( ! gdm_restart_mode)
- return;
-
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
-
- if (d->logged_in)
- return;
- }
-
- gdm_restart_now ();
-}
-
-static void
-gdm_do_logout_action (GdmLogoutAction logout_action)
-{
- switch (logout_action) {
- case GDM_LOGOUT_ACTION_HALT:
- halt_machine ();
- break;
-
- case GDM_LOGOUT_ACTION_REBOOT:
- restart_machine ();
- break;
-
- case GDM_LOGOUT_ACTION_SUSPEND:
- suspend_machine ();
- break;
-
- default:
- /* This is a bit ugly but its the only place we can
- check for the range of values */
- if (logout_action >= GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST &&
- logout_action <= GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST)
- custom_cmd (logout_action - GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST);
- break;
- }
-}
-
-static void
-gdm_try_logout_action (GdmDisplay *disp)
-{
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- if (disp != NULL &&
- disp->logout_action != GDM_LOGOUT_ACTION_NONE &&
- ! disp->logged_in) {
- gdm_do_logout_action (disp->logout_action);
- disp->logout_action = GDM_LOGOUT_ACTION_NONE;
- return;
- }
-
- if (safe_logout_action == GDM_LOGOUT_ACTION_NONE)
- return;
-
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
-
- if (d->logged_in)
- return;
- }
-
- gdm_do_logout_action (safe_logout_action);
- safe_logout_action = GDM_LOGOUT_ACTION_NONE;
-}
-
-static void
-main_daemon_abrt (int sig)
-{
- /* FIXME: note that this could mean out of memory */
- gdm_error (_("main daemon: Got SIGABRT. Something went very wrong. Going down!"));
- gdm_final_cleanup ();
- exit (EXIT_FAILURE);
-}
-
-static gboolean
-mainloop_sig_callback (int sig, gpointer data)
-{
- /* signals are at somewhat random times aren't they? */
- gdm_random_tick ();
-
- g_debug ("mainloop_sig_callback: Got signal %d", (int)sig);
- switch (sig)
- {
- case SIGCHLD:
- while (gdm_cleanup_children ())
- ;
- break;
-
- case SIGINT:
- case SIGTERM:
- g_debug ("mainloop_sig_callback: Got TERM/INT. Going down!");
- gdm_final_cleanup ();
- exit (EXIT_SUCCESS);
- break;
-
-#ifdef SIGXFSZ
- case SIGXFSZ:
- gdm_error ("main daemon: Hit file size rlimit, restarting!");
- gdm_restart_now ();
- break;
-#endif
-
-#ifdef SIGXCPU
- case SIGXCPU:
- gdm_error ("main daemon: Hit CPU rlimit, restarting!");
- gdm_restart_now ();
- break;
-#endif
-
- case SIGHUP:
- gdm_restart_now ();
- break;
-
- case SIGUSR1:
- gdm_restart_mode = TRUE;
- gdm_safe_restart ();
- break;
-
- default:
- break;
- }
-
- return TRUE;
-}
-
-/*
- * main: The main daemon control
- */
-
-static void
-store_argv (int argc, char *argv[])
-{
- int i;
-
- stored_argv = g_new0 (char *, argc + 1);
- for (i = 0; i < argc; i++)
- stored_argv[i] = g_strdup (argv[i]);
- stored_argv[i] = NULL;
- stored_argc = argc;
-}
-
-static void
-close_notify (gpointer data)
-{
- GdmConnection **conn = data;
- * conn = NULL;
-}
-
-static void
-create_connections (void)
-{
- int p[2];
- gchar *path;
-
- path = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL);
- fifoconn = gdm_connection_open_fifo (path, 0660);
- g_free (path);
-
- if G_LIKELY (fifoconn != NULL) {
- gdm_connection_set_handler (fifoconn,
- gdm_handle_message,
- NULL /* data */,
- NULL /* destroy_notify */);
- gdm_connection_set_close_notify (fifoconn,
- &fifoconn,
- close_notify);
- }
-
- if G_UNLIKELY (pipe (p) < 0) {
- slave_fifo_pipe_fd = -1;
- pipeconn = NULL;
- } else {
- slave_fifo_pipe_fd = p[1];
- pipeconn = gdm_connection_open_fd (p[0]);
- }
-
- if G_LIKELY (pipeconn != NULL) {
- gdm_connection_set_handler (pipeconn,
- gdm_handle_message,
- NULL /* data */,
- NULL /* destroy_notify */);
- gdm_connection_set_close_notify (pipeconn,
- &pipeconn,
- close_notify);
- } else {
- VE_IGNORE_EINTR (close (p[0]));
- VE_IGNORE_EINTR (close (p[1]));
- slave_fifo_pipe_fd = -1;
- }
-
- unixconn = gdm_connection_open_unix (GDM_SUP_SOCKET, 0666);
-
- if G_LIKELY (unixconn != NULL) {
- gdm_connection_set_handler (unixconn,
- gdm_handle_user_message,
- NULL /* data */,
- NULL /* destroy_notify */);
- gdm_connection_set_nonblock (unixconn, TRUE);
- gdm_connection_set_close_notify (unixconn,
- &unixconn,
- close_notify);
- }
-}
-
-static void
-calc_sqrt2 (void)
-{
- unsigned long n = 0, h = 0;
- double x;
- printf ("\n");
- for (;;) {
- x = g_random_double_range (1.0, 2.0);
- if (x*x <= 2.0)
- h++;
- n++;
- if ( ! (n & 0xfff)) {
- double sqrttwo = 1.0 + ((double)h)/(double)n;
- printf ("sqrt(2) ~~ %1.10f\t(1 + %lu/%lu) "
- "iteration: %lu \r",
- sqrttwo, h, n, n);
- }
- }
-}
-
-GOptionEntry options [] = {
- { "nodaemon", '\0', 0, G_OPTION_ARG_NONE,
- &no_daemon, N_("Do not fork into the background"), NULL },
- { "no-console", '\0', 0, G_OPTION_ARG_NONE,
- &no_console, N_("No console (static) servers to be run"), NULL },
- { "config", '\0', 0, G_OPTION_ARG_STRING,
- &config_file, N_("Alternative GDM System Defaults configuration file"), N_("CONFIGFILE") },
- { "preserve-ld-vars", '\0', 0, G_OPTION_ARG_NONE,
- &preserve_ld_vars, N_("Preserve LD_* variables"), NULL },
- { "version", '\0', 0, G_OPTION_ARG_NONE,
- &print_version, N_("Print GDM version"), NULL },
- { "wait-for-go", '\0', 0, G_OPTION_ARG_NONE,
- &gdm_wait_for_go, N_("Start the first X server but then halt until we get a GO in the fifo"), NULL },
- { "monte-carlo-sqrt2", 0, 0, G_OPTION_ARG_NONE,
- &monte_carlo_sqrt2, NULL, NULL },
- { NULL }
-};
-
-static gboolean
-linux_only_is_running (pid_t pid)
-{
- char resolved_self[PATH_MAX];
- char resolved_running[PATH_MAX];
-
- char *running = g_strdup_printf ("/proc/%lu/exe", (gulong)pid);
-
- if (realpath ("/proc/self/exe", resolved_self) == NULL) {
- g_free (running);
- /* probably not a linux system */
- return TRUE;
- }
-
- if (realpath (running, resolved_running) == NULL) {
- g_free (running);
- /* probably not a linux system */
- return TRUE;
- }
-
- g_free (running);
-
- if (strcmp (resolved_running, resolved_self) == 0)
- return TRUE;
- return FALSE;
-}
-
-static void
-ensure_desc_012 (void)
-{
- int fd;
- /* We here ensure descriptors 0, 1 and 2
- * we of course count on the fact that open
- * opens the lowest available descriptor */
- for (;;) {
- fd = gdm_open_dev_null (O_RDWR);
- /* Once we are up to 3, we're beyond stdin,
- * stdout and stderr */
- if (fd >= 3) {
- VE_IGNORE_EINTR (close (fd));
- break;
- }
- }
-}
-
-/* initially if we get a TERM or INT we just want to die,
- but we want to also kill an extra process if it exists */
-static void
-initial_term_int (int signal)
-{
- if (extra_process > 1)
- kill (-(extra_process), SIGTERM);
- _exit (EXIT_FAILURE);
-}
-
-static void
-gdm_make_global_cookie (void)
-{
- FILE *fp;
- char *file;
- mode_t oldmode;
-
- gdm_cookie_generate ((char **)&gdm_global_cookie, (char **)&gdm_global_bcookie);
-
- file = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".cookie", NULL);
- VE_IGNORE_EINTR (g_unlink (file));
-
- oldmode = umask (077);
- fp = gdm_safe_fopen_w (file);
- umask (oldmode);
- if G_UNLIKELY (fp == NULL) {
- gdm_error (_("Can't open %s for writing"), file);
- g_free (file);
- return;
- }
-
- VE_IGNORE_EINTR (fprintf (fp, "%s\n", gdm_global_cookie));
-
- /* FIXME: What about out of disk space errors? */
- errno = 0;
- VE_IGNORE_EINTR (fclose (fp));
- if G_UNLIKELY (errno != 0) {
- gdm_error (_("Can't write to %s: %s"), file,
- strerror (errno));
- }
-
- g_free (file);
-}
-
-int
-main (int argc, char *argv[])
-{
- FILE *pf;
- sigset_t mask;
- struct sigaction sig, child, abrt;
- GOptionContext *ctx;
- const char *pidfile;
- int i;
-
- /* semi init pseudorandomness */
- gdm_random_tick ();
-
- /* We here ensure descriptors 0, 1 and 2 */
- ensure_desc_012 ();
-
- /* store all initial stuff, args, env, rlimits, runlevel */
- store_argv (argc, argv);
- gdm_saveenv ();
- gdm_get_initial_limits ();
-
- bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
- textdomain (GETTEXT_PACKAGE);
-
- setlocale (LC_ALL, "");
-
- /* Initialize runtime environment */
- umask (022);
-
- g_type_init ();
-
- ctx = g_option_context_new (_("- The GNOME login manager"));
- g_option_context_add_main_entries (ctx, options, _("main options"));
-
- /* preprocess the arguments to support the xdm style -nodaemon
- * option
- */
- for (i = 0; i < argc; i++) {
- if (strcmp (argv[i], "-nodaemon") == 0)
- argv[i] = (char *) "--nodaemon";
- }
-
- g_option_context_parse (ctx, &argc, &argv, NULL);
- g_option_context_free (ctx);
-
- if (monte_carlo_sqrt2) {
- calc_sqrt2 ();
- return 0;
- }
-
- if (print_version) {
- printf ("GDM %s\n", VERSION);
- fflush (stdout);
- exit (0);
- }
-
- gdm_log_init ();
- /* Parse configuration file */
- gdm_daemon_config_parse (config_file, no_console);
- gdm_log_set_debug (gdm_daemon_config_get_bool_for_id (GDM_ID_DEBUG));
-
- /* XDM compliant error message */
- if G_UNLIKELY (getuid () != 0) {
- /* make sure the pid file doesn't get wiped */
- gdm_error (_("Only root wants to run GDM\n"));
- exit (-1);
- }
-
- main_loop = g_main_loop_new (NULL, FALSE);
-
- /* initial TERM/INT handler */
- sig.sa_handler = initial_term_int;
- sig.sa_flags = SA_RESTART;
- sigemptyset (&sig.sa_mask);
-
- /*
- * Do not call gdm_fail before calling gdm_config_parse ()
- * since the gdm_fail function uses config data
- */
- if G_UNLIKELY (sigaction (SIGTERM, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "TERM", strerror (errno));
-
- if G_UNLIKELY (sigaction (SIGINT, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "INT", strerror (errno));
-
- /* get the name of the root user */
- gdm_root_user ();
-
- pidfile = GDM_PID_FILE;
-
- /* Check if another gdm process is already running */
- if (g_access (pidfile, R_OK) == 0) {
-
- /* Check if the existing process is still alive. */
- gint pidv;
-
- pf = fopen (pidfile, "r");
-
- if (pf != NULL &&
- fscanf (pf, "%d", &pidv) == 1 &&
- kill (pidv, 0) == 0 &&
- linux_only_is_running (pidv)) {
- /* make sure the pid file doesn't get wiped */
- VE_IGNORE_EINTR (fclose (pf));
- gdm_fail (_("GDM already running. Aborting!"));
- }
-
- if (pf != NULL)
- VE_IGNORE_EINTR (fclose (pf));
- }
-
- /* Become daemon unless started in -nodaemon mode or child of init */
- if (no_daemon || getppid () == 1) {
-
- /* Write pid to pidfile */
- errno = 0;
- if ((pf = gdm_safe_fopen_w (pidfile)) != NULL) {
- errno = 0;
- VE_IGNORE_EINTR (fprintf (pf, "%d\n", (int)getpid ()));
- VE_IGNORE_EINTR (fclose (pf));
- if (errno != 0) {
- /* FIXME: how to handle this? */
- gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"),
- pidfile, strerror (errno));
- gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"),
- pidfile, strerror (errno));
-
- }
- } else if (errno != 0) {
- /* FIXME: how to handle this? */
- gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"),
- pidfile, strerror (errno));
- gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"),
- pidfile, strerror (errno));
-
- }
-
- VE_IGNORE_EINTR (g_chdir (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)));
- umask (022);
- }
- else
- gdm_daemonify ();
-
-#ifdef __sun
- g_unlink (SDTLOGIN_DIR);
- g_mkdir (SDTLOGIN_DIR, 0700);
-#endif
-
- /* Signal handling */
- ve_signal_add (SIGCHLD, mainloop_sig_callback, NULL);
- ve_signal_add (SIGTERM, mainloop_sig_callback, NULL);
- ve_signal_add (SIGINT, mainloop_sig_callback, NULL);
- ve_signal_add (SIGHUP, mainloop_sig_callback, NULL);
- ve_signal_add (SIGUSR1, mainloop_sig_callback, NULL);
-
- sig.sa_handler = ve_signal_notify;
- sig.sa_flags = SA_RESTART;
- sigemptyset (&sig.sa_mask);
-
- if G_UNLIKELY (sigaction (SIGTERM, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "TERM", strerror (errno));
-
- if G_UNLIKELY (sigaction (SIGINT, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "INT", strerror (errno));
-
- if G_UNLIKELY (sigaction (SIGHUP, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "HUP", strerror (errno));
-
- if G_UNLIKELY (sigaction (SIGUSR1, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "USR1", strerror (errno));
-
- /* some process limit signals we catch and restart on,
- note that we don't catch these in the slave, but then
- we catch those in the main daemon as slave crashing
- (terminated by signal), and we clean up appropriately */
-#ifdef SIGXCPU
- ve_signal_add (SIGXCPU, mainloop_sig_callback, NULL);
- if G_UNLIKELY (sigaction (SIGXCPU, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "XCPU", strerror (errno));
-#endif
-#ifdef SIGXFSZ
- ve_signal_add (SIGXFSZ, mainloop_sig_callback, NULL);
- if G_UNLIKELY (sigaction (SIGXFSZ, &sig, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "XFSZ", strerror (errno));
-#endif
-
- /* cannot use mainloop for SIGABRT, the handler can never
- return */
- abrt.sa_handler = main_daemon_abrt;
- abrt.sa_flags = SA_RESTART;
- sigemptyset (&abrt.sa_mask);
-
- if G_UNLIKELY (sigaction (SIGABRT, &abrt, NULL) < 0)
- gdm_fail (_("%s: Error setting up %s signal handler: %s"),
- "main", "ABRT", strerror (errno));
-
- child.sa_handler = ve_signal_notify;
- child.sa_flags = SA_RESTART|SA_NOCLDSTOP;
- sigemptyset (&child.sa_mask);
- sigaddset (&child.sa_mask, SIGCHLD);
-
- if G_UNLIKELY (sigaction (SIGCHLD, &child, NULL) < 0)
- gdm_fail (_("%s: Error setting up CHLD signal handler"), "gdm_main");
-
- sigemptyset (&mask);
- sigaddset (&mask, SIGINT);
- sigaddset (&mask, SIGTERM);
- sigaddset (&mask, SIGCHLD);
- sigaddset (&mask, SIGHUP);
- sigaddset (&mask, SIGUSR1);
- sigaddset (&mask, SIGABRT);
-#ifdef SIGXCPU
- sigaddset (&mask, SIGXCPU);
-#endif
-#ifdef SIGXFSZ
- sigaddset (&mask, SIGXFSZ);
-#endif
- sigprocmask (SIG_UNBLOCK, &mask, NULL);
-
- gdm_signal_ignore (SIGUSR2);
- gdm_signal_ignore (SIGPIPE);
-
- /* ignore power failures, up to user processes to
- * handle things correctly */
-#ifdef SIGPWR
- gdm_signal_ignore (SIGPWR);
-#endif
- /* can we ever even get this one? */
-#ifdef SIGLOST
- gdm_signal_ignore (SIGLOST);
-#endif
-
- g_debug ("gdm_main: Here we go...");
-
-#ifdef HAVE_LOGINDEVPERM
- di_devperm_login ("/dev/console", gdm_daemon_config_get_gdmuid (), gdm_daemon_config_get_gdmgid (), NULL);
-#endif /* HAVE_LOGINDEVPERM */
-
- /* Init XDMCP if applicable */
- if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) {
- gdm_xdmcp_init ();
- }
-
- create_connections ();
-
- /* make sure things (currently /tmp/.ICE-unix and /tmp/.X11-unix)
- * are sane */
- gdm_ensure_sanity () ;
-
- /* Make us a unique global cookie to authenticate */
- gdm_make_global_cookie ();
-
- /* Start static X servers */
- gdm_start_first_unborn_local (0 /* delay */);
-
- /* Accept remote connections */
- if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) {
- g_debug ("Accepting XDMCP connections...");
- gdm_xdmcp_run ();
- }
-
- /* We always exit via exit (), and sadly we need to g_main_quit ()
- * at times not knowing if it's this main or a recursive one we're
- * quitting.
- */
- while (1)
- {
- g_main_loop_run (main_loop);
- g_debug ("main: Exited main loop");
- }
-
- return EXIT_SUCCESS; /* Not reached */
-}
-
-static gboolean
-order_exists (int order)
-{
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- if (d->x_servers_order == order)
- return TRUE;
- }
- return FALSE;
-}
-
-static int
-get_new_order (GdmDisplay *d)
-{
- int order;
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- /* first try the position in the 'displays' list as
- * our order */
- for (order = 0, li = displays; li != NULL; order++, li = li->next) {
- if (li->data == d)
- break;
- }
- /* next make sure it's unique */
- while (order_exists (order))
- order++;
- return order;
-}
-
-static void
-write_x_servers (GdmDisplay *d)
-{
- FILE *fp;
- char *file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xservers");
- int i;
- int bogusname;
-
- if (d->x_servers_order < 0)
- d->x_servers_order = get_new_order (d);
-
- fp = gdm_safe_fopen_w (file);
- if G_UNLIKELY (fp == NULL) {
- gdm_error (_("Can't open %s for writing"), file);
- g_free (file);
- return;
- }
-
- for (bogusname = 0, i = 0; i < d->x_servers_order; bogusname++, i++) {
- char buf[32];
- g_snprintf (buf, sizeof (buf), ":%d", bogusname);
- if (strcmp (buf, d->name) == 0)
- g_snprintf (buf, sizeof (buf), ":%d", ++bogusname);
- VE_IGNORE_EINTR (fprintf (fp, "%s local /usr/X11R6/bin/Xbogus\n", buf));
- }
-
- if (SERVER_IS_LOCAL (d)) {
- char **argv;
- char *command;
- int argc;
- argc = 0;
- argv = NULL;
- gdm_server_resolve_command_line (d,
- FALSE, /* resolve_flags */
- NULL, /* vtarg */
- &argc,
- &argv);
- command = g_strjoinv (" ", argv);
- g_strfreev (argv);
- VE_IGNORE_EINTR (fprintf (fp, "%s local %s\n", d->name, command));
- g_free (command);
- } else {
- VE_IGNORE_EINTR (fprintf (fp, "%s foreign\n", d->name));
- }
-
- /* FIXME: What about out of disk space errors? */
- errno = 0;
- VE_IGNORE_EINTR (fclose (fp));
- if G_UNLIKELY (errno != 0) {
- gdm_error (_("Can't write to %s: %s"), file,
- strerror (errno));
- }
-
- g_free (file);
-}
-
-static void
-send_slave_ack_dialog_int (GdmDisplay *d, int type, int response)
-{
- if (d->master_notify_fd >= 0) {
- char *not;
-
- not = g_strdup_printf ("%c%c%d\n", GDM_SLAVE_NOTIFY_RESPONSE, type, response);
- VE_IGNORE_EINTR (write (d->master_notify_fd, not, strlen (not)));
-
- g_free (not);
- }
- if (d->slavepid > 1) {
- /* now yield the CPU as the other process has more
- useful work to do then we do */
-#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
- sched_yield ();
-#endif
- }
-}
-
-static void
-send_slave_ack_dialog_char (GdmDisplay *d, int type, const char *resp)
-{
- if (d->master_notify_fd >= 0) {
- if (resp == NULL) {
- char not[3];
-
- not[0] = GDM_SLAVE_NOTIFY_RESPONSE;
- not[1] = type;
- not[2] = '\n';
- VE_IGNORE_EINTR (write (d->master_notify_fd, not, 3));
- } else {
- char *not = g_strdup_printf ("%c%c%s\n",
- GDM_SLAVE_NOTIFY_RESPONSE,
- type,
- resp);
- VE_IGNORE_EINTR (write (d->master_notify_fd, not, strlen (not)));
- g_free (not);
- }
- }
- if (d->slavepid > 1) {
- /* now yield the CPU as the other process has more
- useful work to do then we do */
-#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
- sched_yield ();
-#endif
- }
-}
-
-static void
-send_slave_ack (GdmDisplay *d, const char *resp)
-{
- if (d->master_notify_fd >= 0) {
- if (resp == NULL) {
- char not[2];
- not[0] = GDM_SLAVE_NOTIFY_ACK;
- not[1] = '\n';
- VE_IGNORE_EINTR (write (d->master_notify_fd, not, 2));
- } else {
- char *not = g_strdup_printf ("%c%s\n",
- GDM_SLAVE_NOTIFY_ACK,
- resp);
- VE_IGNORE_EINTR (write (d->master_notify_fd, not, strlen (not)));
- g_free (not);
- }
- }
- if (d->slavepid > 1) {
- kill (d->slavepid, SIGUSR2);
- /* now yield the CPU as the other process has more
- useful work to do then we do */
-#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
- sched_yield ();
-#endif
- }
-}
-
-static void
-send_slave_command (GdmDisplay *d, const char *command)
-{
- if (d->master_notify_fd >= 0) {
- char *cmd = g_strdup_printf ("%c%s\n",
- GDM_SLAVE_NOTIFY_COMMAND,
- command);
- VE_IGNORE_EINTR (write (d->master_notify_fd, cmd, strlen (cmd)));
- g_free (cmd);
- }
- if (d->slavepid > 1) {
- kill (d->slavepid, SIGUSR2);
- /* now yield the CPU as the other process has more
- useful work to do then we do */
-#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
- sched_yield ();
-#endif
- }
-}
-
-static void
-gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data)
-{
- /* Evil!, all this for debugging? */
- if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) {
- if (strncmp (msg, GDM_SOP_COOKIE " ",
- strlen (GDM_SOP_COOKIE " ")) == 0) {
- char *s = g_strndup
- (msg, strlen (GDM_SOP_COOKIE " XXXX XX"));
- /* cut off most of the cookie for "security" */
- g_debug ("Handling message: '%s...'", s);
- g_free (s);
- } else if (strncmp (msg, GDM_SOP_SYSLOG " ",
- strlen (GDM_SOP_SYSLOG " ")) != 0) {
- /* Don't print out the syslog message as it will
- * be printed out anyway as that's the whole point
- * of the message. */
- g_debug ("Handling message: '%s'", msg);
- }
- }
-
- if (strncmp (msg, GDM_SOP_CHOSEN " ",
- strlen (GDM_SOP_CHOSEN " ")) == 0) {
- gdm_choose_data (msg);
- } else if (strncmp (msg, GDM_SOP_CHOSEN_LOCAL " ",
- strlen (GDM_SOP_CHOSEN_LOCAL " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- char *p;
-
- if (sscanf (msg, GDM_SOP_CHOSEN_LOCAL " %ld", &slave_pid)
- != 1)
- return;
- p = strchr (msg, ' ');
- if (p != NULL)
- p = strchr (p+1, ' ');
- if (p == NULL)
- return;
- p++;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- g_free (d->chosen_hostname);
- d->chosen_hostname = g_strdup (p);
- g_debug ("Got CHOSEN_LOCAL == %s", p);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_XPID " ",
- strlen (GDM_SOP_XPID " ")) == 0) {
- GdmDisplay *d;
- long slave_pid, pid;
-
- if (sscanf (msg, GDM_SOP_XPID " %ld %ld", &slave_pid, &pid)
- != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- d->servpid = pid;
- g_debug ("Got XPID == %ld", (long)pid);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_SESSPID " ",
- strlen (GDM_SOP_SESSPID " ")) == 0) {
- GdmDisplay *d;
- long slave_pid, pid;
-
- if (sscanf (msg, GDM_SOP_SESSPID " %ld %ld", &slave_pid, &pid)
- != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- d->sesspid = pid;
- g_debug ("Got SESSPID == %ld", (long)pid);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_GREETPID " ",
- strlen (GDM_SOP_GREETPID " ")) == 0) {
- GdmDisplay *d;
- long slave_pid, pid;
-
- if (sscanf (msg, GDM_SOP_GREETPID " %ld %ld", &slave_pid, &pid)
- != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- d->greetpid = pid;
- g_debug ("Got GREETPID == %ld", (long)pid);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_CHOOSERPID " ",
- strlen (GDM_SOP_CHOOSERPID " ")) == 0) {
- GdmDisplay *d;
- long slave_pid, pid;
-
- if (sscanf (msg, GDM_SOP_CHOOSERPID " %ld %ld",
- &slave_pid, &pid) != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- d->chooserpid = pid;
- g_debug ("Got CHOOSERPID == %ld", (long)pid);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_LOGGED_IN " ",
- strlen (GDM_SOP_LOGGED_IN " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- int logged_in;
- if (sscanf (msg, GDM_SOP_LOGGED_IN " %ld %d", &slave_pid,
- &logged_in) != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- d->logged_in = logged_in ? TRUE : FALSE;
- g_debug ("Got logged in == %s",
- d->logged_in ? "TRUE" : "FALSE");
-
- /* whack connections about this display if a user
- * just logged out since we don't want such
- * connections persisting to be authenticated */
- if ( ! logged_in && unixconn != NULL)
- gdm_kill_subconnections_with_display (unixconn, d);
-
- /* if the user just logged out,
- * let's see if it's safe to restart */
- if ( ! d->logged_in) {
- gdm_try_logout_action (d);
- gdm_safe_restart ();
- }
-
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_DISP_NUM " ",
- strlen (GDM_SOP_DISP_NUM " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- int disp_num;
-
- if (sscanf (msg, GDM_SOP_DISP_NUM " %ld %d",
- &slave_pid, &disp_num) != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- g_free (d->name);
- d->name = g_strdup_printf (":%d", disp_num);
- d->dispnum = disp_num;
- g_debug ("Got DISP_NUM == %d", disp_num);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_VT_NUM " ",
- strlen (GDM_SOP_VT_NUM " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- int vt_num;
-
- if (sscanf (msg, GDM_SOP_VT_NUM " %ld %d",
- &slave_pid, &vt_num) != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- d->vt = vt_num;
- g_debug ("Got VT_NUM == %d", vt_num);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_LOGIN " ",
- strlen (GDM_SOP_LOGIN " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- char *p;
-
- if (sscanf (msg, GDM_SOP_LOGIN " %ld",
- &slave_pid) != 1)
- return;
- p = strchr (msg, ' ');
- if (p != NULL)
- p = strchr (p+1, ' ');
- if (p == NULL)
- return;
-
- p++;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- g_free (d->login);
- d->login = g_strdup (p);
- g_debug ("Got LOGIN == %s", p);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_QUERYLOGIN " ",
- strlen (GDM_SOP_QUERYLOGIN " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- char *p;
-
- if (sscanf (msg, GDM_SOP_QUERYLOGIN " %ld",
- &slave_pid) != 1)
- return;
- p = strchr (msg, ' ');
- if (p != NULL)
- p = strchr (p+1, ' ');
- if (p == NULL)
- return;
-
- p++;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- GString *resp = NULL;
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- g_debug ("Got QUERYLOGIN %s", p);
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *di = li->data;
- if (di->logged_in &&
- di->login != NULL &&
- strcmp (di->login, p) == 0) {
- gboolean migratable = FALSE;
-
- if (resp == NULL)
- resp = g_string_new (NULL);
- else
- resp = g_string_append_c (resp, ',');
-
- g_string_append (resp, di->name);
- g_string_append_c (resp, ',');
-
- if (d->attached && di->attached && di->vt > 0)
- migratable = TRUE;
- else if (gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT) != NULL &&
- d->type == TYPE_XDMCP_PROXY && di->type == TYPE_XDMCP_PROXY)
- migratable = TRUE;
-
- g_string_append_c (resp, migratable ? '1' : '0');
- }
- }
-
- /* send ack */
- if (resp != NULL) {
- send_slave_ack (d, resp->str);
- g_string_free (resp, TRUE);
- } else {
- send_slave_ack (d, NULL);
- }
- }
- } else if (strncmp (msg, GDM_SOP_MIGRATE " ",
- strlen (GDM_SOP_MIGRATE " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- char *p;
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- if (sscanf (msg, GDM_SOP_MIGRATE " %ld", &slave_pid) != 1)
- return;
- p = strchr (msg, ' ');
- if (p != NULL)
- p = strchr (p+1, ' ');
- if (p == NULL)
- return;
-
- p++;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
- if (d == NULL)
- return;
-
- g_debug ("Got MIGRATE %s", p);
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *di = li->data;
- if (di->logged_in && strcmp (di->name, p) == 0) {
- if (d->attached && di->vt > 0)
- gdm_change_vt (di->vt);
- else if (d->type == TYPE_XDMCP_PROXY && di->type == TYPE_XDMCP_PROXY)
- gdm_xdmcp_migrate (d, di);
- }
- }
- send_slave_ack (d, NULL);
- } else if (strncmp (msg, GDM_SOP_COOKIE " ",
- strlen (GDM_SOP_COOKIE " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- char *p;
-
- if (sscanf (msg, GDM_SOP_COOKIE " %ld",
- &slave_pid) != 1)
- return;
- p = strchr (msg, ' ');
- if (p != NULL)
- p = strchr (p+1, ' ');
- if (p == NULL)
- return;
-
- p++;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- g_free (d->cookie);
- d->cookie = g_strdup (p);
- g_debug ("Got COOKIE == <secret>");
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_AUTHFILE " ",
- strlen (GDM_SOP_AUTHFILE " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- char *p;
-
- if (sscanf (msg, GDM_SOP_AUTHFILE " %ld",
- &slave_pid) != 1)
- return;
- p = strchr (msg, ' ');
- if (p != NULL)
- p = strchr (p+1, ' ');
- if (p == NULL)
- return;
-
- p++;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- g_free (d->authfile);
- d->authfile = g_strdup (p);
- g_debug ("Got AUTHFILE == %s", d->authfile);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_FLEXI_ERR " ",
- strlen (GDM_SOP_FLEXI_ERR " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- int err;
-
- if (sscanf (msg, GDM_SOP_FLEXI_ERR " %ld %d",
- &slave_pid, &err) != 2)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- char *error = NULL;
- GdmConnection *conn = d->socket_conn;
- d->socket_conn = NULL;
-
- if (conn != NULL)
- gdm_connection_set_close_notify (conn,
- NULL, NULL);
-
- if (err == 3)
- error = "ERROR 3 X failed\n";
- else if (err == 4)
- error = "ERROR 4 X too busy\n";
- else if (err == 5)
- error = "ERROR 5 Nested display can't connect\n";
- else
- error = "ERROR 999 Unknown error\n";
- if (conn != NULL)
- gdm_connection_write (conn, error);
-
- g_debug ("Got FLEXI_ERR == %d", err);
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_FLEXI_OK " ",
- strlen (GDM_SOP_FLEXI_OK " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
-
- if (sscanf (msg, GDM_SOP_FLEXI_OK " %ld",
- &slave_pid) != 1)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- GdmConnection *conn = d->socket_conn;
- d->socket_conn = NULL;
-
- if (conn != NULL) {
- gdm_connection_set_close_notify (conn,
- NULL, NULL);
- if ( ! gdm_connection_printf (conn, "OK %s\n", d->name))
- gdm_display_unmanage (d);
- }
-
- g_debug ("Got FLEXI_OK");
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strcmp (msg, GDM_SOP_SOFT_RESTART) == 0) {
- gdm_restart_mode = TRUE;
- gdm_safe_restart ();
- } else if (strcmp (msg, GDM_SOP_DIRTY_SERVERS) == 0) {
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- send_slave_command (d, GDM_NOTIFY_DIRTY_SERVERS);
- }
- } else if (strcmp (msg, GDM_SOP_SOFT_RESTART_SERVERS) == 0) {
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- send_slave_command (d, GDM_NOTIFY_SOFT_RESTART_SERVERS);
- }
- } else if (strncmp (msg, GDM_SOP_SYSLOG " ",
- strlen (GDM_SOP_SYSLOG " ")) == 0) {
- char *p;
- long pid;
- int type;
- p = strchr (msg, ' ');
- if (p == NULL)
- return;
- p++;
- if (sscanf (p, "%ld", &pid) != 1)
- return;
- p = strchr (p, ' ');
- if (p == NULL)
- return;
- p++;
- if (sscanf (p, "%d", &type) != 1)
- return;
-
- p = strchr (p, ' ');
- if (p == NULL)
- return;
- p++;
-
- /* FIXME: use g_critical or g_debug when required */
- g_warning ("(child %ld) %s", pid, p);
- } else if (strcmp (msg, GDM_SOP_START_NEXT_LOCAL) == 0) {
- gdm_start_first_unborn_local (3 /* delay */);
- } else if (strcmp (msg, GDM_SOP_HUP_ALL_GREETERS) == 0) {
- /* probably shouldn't be done too often */
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- if (d->greetpid > 1)
- kill (d->greetpid, SIGHUP);
- else if (d->chooserpid > 1)
- kill (d->chooserpid, SIGHUP);
- }
- } else if (strcmp (msg, GDM_SOP_GO) == 0) {
- GSList *li;
- gboolean old_wait = gdm_wait_for_go;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
- gdm_wait_for_go = FALSE;
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *d = li->data;
- send_slave_command (d, GDM_NOTIFY_GO);
- }
- /* Init XDMCP if applicable */
- if (old_wait && gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP)) {
- if (gdm_xdmcp_init ()) {
- g_debug ("Accepting XDMCP connections...");
- gdm_xdmcp_run ();
- }
- }
- } else if (strncmp (msg, GDM_SOP_WRITE_X_SERVERS " ",
- strlen (GDM_SOP_WRITE_X_SERVERS " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
-
- if (sscanf (msg, GDM_SOP_WRITE_X_SERVERS " %ld",
- &slave_pid) != 1)
- return;
-
- /* Find out who this slave belongs to */
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- write_x_servers (d);
-
- /* send ack */
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_SUSPEND_MACHINE " ",
- strlen (GDM_SOP_SUSPEND_MACHINE " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- gboolean sysmenu;
-
- if (sscanf (msg, GDM_SOP_SUSPEND_MACHINE " %ld", &slave_pid) != 1)
- return;
- d = gdm_display_lookup (slave_pid);
-
- gdm_info (_("Master suspending..."));
-
- sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name);
- if (sysmenu && gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND) != NULL) {
- suspend_machine ();
- }
- } else if (strncmp (msg, GDM_SOP_CHOSEN_THEME " ",
- strlen (GDM_SOP_CHOSEN_THEME " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- const char *p;
-
- if (sscanf (msg, GDM_SOP_CHOSEN_THEME " %ld", &slave_pid) != 1)
- return;
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- g_free (d->theme_name);
- d->theme_name = NULL;
-
- /* Syntax errors are partially OK here, if there
- was no theme argument we just wanted to clear the
- theme field */
- p = strchr (msg, ' ');
- if (p != NULL) {
- p = strchr (p+1, ' ');
- if (p != NULL) {
- while (*p == ' ')
- p++;
- if ( ! ve_string_empty (p))
- d->theme_name = g_strdup (p);
- }
- }
-
- send_slave_ack (d, NULL);
- }
- } else if (strncmp (msg, GDM_SOP_CUSTOM_CMD " ",
- strlen (GDM_SOP_CUSTOM_CMD " ")) == 0) {
- GdmDisplay *d;
- long slave_pid;
- long cmd_id;
-
- if (sscanf (msg, GDM_SOP_CUSTOM_CMD " %ld %ld", &slave_pid, &cmd_id) != 2)
- return;
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- custom_cmd (cmd_id);
- send_slave_ack (d, NULL);
- }
- } else if (strcmp (msg, GDM_SOP_FLEXI_XSERVER) == 0) {
- handle_flexi_server (NULL, TYPE_FLEXI, gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER),
- TRUE /* handled */,
- FALSE /* chooser */,
- NULL, 0, NULL, NULL, NULL);
- } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_ERROR_DIALOG,
- strlen ("opcode="GDM_SOP_SHOW_ERROR_DIALOG)) == 0) {
- GdmDisplay *d;
- GtkMessageType type;
- char **list;
- char *ptr;
- char *error;
- char *details_label;
- char *details_file;
- long slave_pid;
- int uid, gid;
-
- list = g_strsplit (msg, "$$", -1);
-
- ptr = strchr (list[1], '=');
- slave_pid = atol (ptr + 1);
-
- ptr = strchr (list[2], '=');
- type = atoi (ptr + 1);
-
- ptr = strchr (list[3], '=');
- error = g_malloc0 (strlen (ptr));
- strcpy (error, ptr + 1);
-
- ptr = strchr (list[4], '=');
- details_label = g_malloc0 (strlen (ptr));
- strcpy (details_label, ptr + 1);
-
- ptr = strchr (list[5], '=');
- details_file = g_malloc0 (strlen (ptr));
- strcpy (details_file, ptr + 1);
-
- ptr = strchr (list[6], '=');
- uid = atoi (ptr + 1);
-
- ptr = strchr (list[7], '=');
- gid = atoi (ptr + 1);
-
- d = gdm_display_lookup (slave_pid);
-
- if (d != NULL) {
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644));
- }
-
- /* FIXME: this is really bad */
- gdm_errorgui_error_box_full (d, type, error, details_label, details_file, 0, 0);
-
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640));
- }
-
- send_slave_ack_dialog_char (d, GDM_SLAVE_NOTIFY_ERROR_RESPONSE, NULL);
- }
-
- g_free (error);
- g_free (details_label);
- g_free (details_file);
- g_strfreev (list);
- } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_YESNO_DIALOG,
- strlen ("opcode="GDM_SOP_SHOW_YESNO_DIALOG)) == 0) {
- GdmDisplay *d;
- char **list;
- char *ptr;
- char *yesno_msg;
- long slave_pid;
- gboolean response_yesno;
-
- list = g_strsplit (msg, "$$", -1);
-
- ptr = strchr (list [1], '=');
- slave_pid = atol (ptr + 1);
-
- ptr = strchr (list [2], '=');
- yesno_msg = g_malloc0 (strlen (ptr));
- strcpy (yesno_msg, ptr + 1);
-
- d = gdm_display_lookup (slave_pid);
- if (d != NULL) {
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644));
- }
-
- response_yesno = gdm_errorgui_failsafe_yesno (d, yesno_msg);
-
- send_slave_ack_dialog_int (d, GDM_SLAVE_NOTIFY_YESNO_RESPONSE, response_yesno);
-
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640));
- }
- }
-
- g_free (yesno_msg);
- g_strfreev (list);
- } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_QUESTION_DIALOG,
- strlen ("opcode="GDM_SOP_SHOW_QUESTION_DIALOG)) == 0) {
- GdmDisplay *d;
- char **list;
- char *ptr;
- char *question_msg;
- char *response_question;
- long slave_pid;
- gboolean echo;
-
- list = g_strsplit (msg, "$$", -1);
-
- ptr = strchr (list [1], '=');
- slave_pid = atol (ptr + 1);
-
- ptr = strchr (list [2], '=');
- question_msg = g_malloc0 (strlen (ptr));
- strcpy (question_msg, ptr + 1);
-
- ptr = strchr (list [3], '=');
- echo = atoi (ptr + 1);
-
- d = gdm_display_lookup (slave_pid);
- if (d != NULL) {
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644));
- }
-
- response_question = gdm_errorgui_failsafe_question (d, question_msg, echo);
-
- send_slave_ack_dialog_char (d, GDM_SLAVE_NOTIFY_QUESTION_RESPONSE, response_question);
-
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640));
- }
- }
-
- g_free (question_msg);
- g_strfreev (list);
- } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_ASKBUTTONS_DIALOG,
- strlen ("opcode="GDM_SOP_SHOW_ASKBUTTONS_DIALOG)) == 0) {
- GdmDisplay *d;
- char *askbuttons_msg;
- char **list;
- char *ptr;
- char *options[4];
- long slave_pid;
- int i;
- int response_askbuttons;
-
- list = g_strsplit (msg, "$$", -1);
-
- ptr = strchr (list [1], '=');
- slave_pid = atol (ptr + 1);
-
- ptr = strchr (list [2], '=');
- askbuttons_msg = g_malloc0 (strlen (ptr));
- strcpy (askbuttons_msg, ptr + 1);
-
- ptr = strchr (list [3], '=');
- options[0] = g_malloc0 (strlen (ptr));
- strcpy (options[0], ptr + 1);
-
- ptr = strchr (list [4], '=');
- options[1] = g_malloc0 (strlen (ptr));
- strcpy (options[1], ptr + 1);
-
- ptr = strchr (list [5], '=');
- options[2] = g_malloc0 (strlen (ptr));
- strcpy (options[2], ptr + 1);
-
- ptr = strchr (list [6], '=');
- options[3] = g_malloc0 (strlen (ptr));
- strcpy (options[3], ptr + 1);
-
- d = gdm_display_lookup (slave_pid);
- if (d != NULL) {
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644));
- }
-
- response_askbuttons = gdm_errorgui_failsafe_ask_buttons (d, askbuttons_msg, options);
-
- send_slave_ack_dialog_int (d, GDM_SLAVE_NOTIFY_ASKBUTTONS_RESPONSE, response_askbuttons);
- if (GDM_AUTHFILE (d)) {
- VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640));
- }
- }
-
- g_free (askbuttons_msg);
-
- for (i = 0; i < 3; i ++)
- g_free (options[i]);
- g_strfreev (list);
- }
-}
-
-/* extract second word and the rest of the string */
-static void
-extract_dispname_uid_xauthfile_cookie (const char *msg,
- char **dispname,
- uid_t *uid,
- char **xauthfile,
- char **cookie)
-{
- const char *p;
- int i;
- char *pp;
-
- *dispname = NULL;
- *xauthfile = NULL;
- *cookie = NULL;
-
- /* Get dispname */
- p = strchr (msg, ' ');
- if (p == NULL)
- return;
-
- while (*p == ' ')
- p++;
-
- *dispname = g_strdup (p);
- pp = strchr (*dispname, ' ');
- if (pp != NULL)
- *pp = '\0';
-
- /* Get uid */
- p = strchr (p, ' ');
- if (p == NULL) {
- *dispname = NULL;
- g_free (*dispname);
- return;
- }
- while (*p == ' ')
- p++;
-
- if (sscanf (p, "%d", &i) != 1) {
- *dispname = NULL;
- g_free (*dispname);
- return;
- }
- *uid = i;
-
- /* Get cookie */
- p = strchr (p, ' ');
- if (p == NULL) {
- *dispname = NULL;
- g_free (*dispname);
- return;
- }
- while (*p == ' ')
- p++;
-
- *cookie = g_strdup (p);
- pp = strchr (*cookie, ' ');
- if (pp != NULL)
- *pp = '\0';
-
- /* Get xauthfile */
- p = strchr (p, ' ');
- if (p == NULL) {
- *cookie = NULL;
- g_free (*cookie);
- *dispname = NULL;
- g_free (*dispname);
- return;
- }
-
- while (*p == ' ')
- p++;
-
- *xauthfile = g_strstrip (g_strdup (p));
-
-}
-
-static void
-close_conn (gpointer data)
-{
- GdmDisplay *disp = data;
-
- /* We still weren't finished, so we want to whack this display */
- if (disp->socket_conn != NULL) {
- disp->socket_conn = NULL;
- gdm_display_unmanage (disp);
- }
-}
-
-static GdmDisplay *
-find_display (const char *name)
-{
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
- if (disp->name != NULL &&
- strcmp (disp->name, name) == 0)
- return disp;
- }
- return NULL;
-}
-
-static char *
-extract_dispnum (const char *addy)
-{
- int num;
- char *p;
-
- gdm_assert (addy != NULL);
-
- p = strchr (addy, ':');
- if (p == NULL)
- return NULL;
-
- /* Whee! handles DECnet even if we don't do that */
- while (*p == ':')
- p++;
-
- if (sscanf (p, "%d", &num) != 1)
- return NULL;
-
- return g_strdup_printf ("%d", num);
-}
-
-static char *
-dehex_cookie (const char *cookie, int *len)
-{
- /* it should be +1 really, but I'm paranoid */
- char *bcookie = g_new0 (char, (strlen (cookie) / 2) + 2);
- int i;
- const char *p;
-
- *len = 0;
-
- for (i = 0, p = cookie;
- *p != '\0' && *(p+1) != '\0';
- i++, p += 2) {
- unsigned int num;
- if (sscanf (p, "%02x", &num) != 1) {
- g_free (bcookie);
- return NULL;
- }
- bcookie[i] = num;
- }
- *len = i;
- return bcookie;
-}
-
-/* This runs as the user who owns the file */
-static gboolean
-check_cookie (const gchar *file, const gchar *disp, const gchar *cookie)
-{
- Xauth *xa;
- gchar *number;
- gchar *bcookie;
- int cookielen;
- gboolean ret = FALSE;
- int cnt = 0;
-
- FILE *fp = fopen (file, "r");
- if (fp == NULL)
- return FALSE;
-
- number = extract_dispnum (disp);
- if (number == NULL)
- return FALSE;
- bcookie = dehex_cookie (cookie, &cookielen);
- if (bcookie == NULL) {
- g_free (number);
- return FALSE;
- }
-
- while ((xa = XauReadAuth (fp)) != NULL) {
- if (xa->number_length == strlen (number) &&
- strncmp (xa->number, number, xa->number_length) == 0 &&
- xa->name_length == strlen ("MIT-MAGIC-COOKIE-1") &&
- strncmp (xa->name, "MIT-MAGIC-COOKIE-1",
- xa->name_length) == 0 &&
- xa->data_length == cookielen &&
- memcmp (xa->data, bcookie, cookielen) == 0) {
- XauDisposeAuth (xa);
- ret = TRUE;
- break;
- }
- XauDisposeAuth (xa);
-
- /* just being ultra anal */
- cnt++;
- if (cnt > 500)
- break;
- }
-
- g_free (number);
- g_free (bcookie);
-
- VE_IGNORE_EINTR (fclose (fp));
-
- return ret;
-}
-
-static void
-handle_flexi_server (GdmConnection *conn,
- int type,
- const char *server,
- gboolean handled,
- gboolean chooser,
- const char *xnest_disp,
- uid_t xnest_uid,
- const char *xnest_auth_file,
- const char *xnest_cookie,
- const char *username)
-{
- GdmDisplay *display;
- gchar *bin;
- uid_t server_uid = 0;
-
- g_debug ("flexi server: '%s'", server);
-
- if (gdm_wait_for_go) {
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 1 No more flexi servers\n");
- return;
- }
-
- if (type == TYPE_FLEXI_XNEST) {
- gboolean authorized = TRUE;
- struct passwd *pw;
- gid_t oldgid = getegid ();
-
- pw = getpwuid (xnest_uid);
- if (pw == NULL) {
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- /* paranoia */
- NEVER_FAILS_seteuid (0);
-
- if (setegid (pw->pw_gid) < 0)
- NEVER_FAILS_setegid (gdm_daemon_config_get_gdmgid ());
-
- if (seteuid (xnest_uid) < 0) {
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- gdm_assert (xnest_auth_file != NULL);
- gdm_assert (xnest_disp != NULL);
- gdm_assert (xnest_cookie != NULL);
-
- if (authorized &&
- ! gdm_auth_file_check ("handle_flexi_server", xnest_uid, xnest_auth_file, FALSE /* absentok */, NULL))
- authorized = FALSE;
-
- if (authorized &&
- ! check_cookie (xnest_auth_file,
- xnest_disp,
- xnest_cookie)) {
- authorized = FALSE;
- }
-
- /* this must always work, thus the asserts */
- NEVER_FAILS_root_set_euid_egid (0, oldgid);
-
- if (! authorized) {
- /* Sorry dude, you're not doing something
- * right */
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- server_uid = xnest_uid;
- }
-
- if (flexi_servers >= gdm_daemon_config_get_value_int (GDM_KEY_FLEXIBLE_XSERVERS)) {
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 1 No more flexi servers\n");
- return;
- }
-
- bin = ve_first_word (server);
- if (ve_string_empty (server) ||
- g_access (bin, X_OK) != 0) {
- g_free (bin);
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 6 No server binary\n");
- return;
- }
- g_free (bin);
-
- display = gdm_server_alloc (-1, server);
- if G_UNLIKELY (display == NULL) {
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 2 Startup errors\n");
- return;
- }
-
- /* It is kind of ugly that we don't use
- the standard resolution for this, but
- oh well, this makes other things simpler */
- display->handled = handled;
- display->use_chooser = chooser;
-
- if (type == TYPE_FLEXI_XNEST) {
- GdmDisplay *parent;
- gchar *disp, *p;
- gdm_assert (xnest_disp != NULL);
-
- disp = g_strdup (xnest_disp);
- /* whack the screen info */
- p = strchr (disp, ':');
- if (p != NULL)
- p = strchr (p+1, '.');
- if (p != NULL)
- *p = '\0';
- /* if it's on one of the attached displays we started,
- * it's on the console, else it's not (it could be but
- * we aren't sure and we don't want to be fooled) */
- parent = find_display (disp);
- if (/* paranoia */xnest_disp[0] == ':' &&
- parent != NULL &&
- parent->attached)
- display->attached = TRUE;
- else
- display->attached = FALSE;
- g_free (disp);
-
- display->server_uid = server_uid;
- }
-
- flexi_servers++;
-
- display->preset_user = g_strdup (username);
- display->type = type;
- display->socket_conn = conn;
- display->parent_disp = g_strdup (xnest_disp);
- display->parent_auth_file = g_strdup (xnest_auth_file);
- if (conn != NULL)
- gdm_connection_set_close_notify (conn, display, close_conn);
- gdm_daemon_config_display_list_append (display);
-
- if ( ! gdm_display_manage (display)) {
- gdm_display_unmanage (display);
- if (conn != NULL)
- gdm_connection_write (conn,
- "ERROR 2 Startup errors\n");
- return;
- }
- /* Now we wait for the server to start up (or not) */
-}
-
-static void
-handle_dynamic_server (GdmConnection *conn, int type, gchar *key)
-{
- GdmDisplay *disp;
- int disp_num;
- gchar *msg;
- gchar *full;
- gchar *val;
-
- if (!(gdm_daemon_config_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS))) {
- gdm_connection_write (conn, "ERROR 200 Dynamic Displays not allowed\n");
- return;
- }
-
- if ( ! GDM_CONN_AUTH_GLOBAL(conn)) {
- gdm_info (_("DYNAMIC request denied: " "Not authenticated"));
- gdm_connection_write (conn, "ERROR 100 Not authenticated\n");
- return;
- }
-
- if (key == NULL) {
- gdm_connection_write (conn, "ERROR 1 Bad display number <NULL>\n");
- return;
- } else if ( !(isdigit (*key))) {
- msg = g_strdup_printf ("ERROR 1 Bad display number <%s>\n", key);
- gdm_connection_write (conn, msg);
- g_free (msg);
- return;
- }
- disp_num = atoi (key);
-
- if (type == DYNAMIC_ADD) {
- /* prime an X server for launching */
-
- if (mark_display_exists (disp_num)) {
- /* need to skip starting this one again */
- gdm_connection_write (conn, "ERROR 2 Existing display\n");
- return;
- }
-
- full = strchr (key, '=');
- if (full == NULL || *(full + 1) == 0) {
- gdm_connection_write (conn, "ERROR 3 No server string\n");
- return;
- }
-
- val = full + 1;
- disp = gdm_server_alloc (disp_num, val);
-
- if (disp == NULL) {
- gdm_connection_write (conn, "ERROR 4 Display startup failure\n");
- return;
- }
-
- gdm_daemon_config_display_list_insert (disp);
-
- disp->dispstat = DISPLAY_CONFIG;
- disp->removeconf = FALSE;
-
- if (disp_num > gdm_daemon_config_get_high_display_num ())
- gdm_daemon_config_set_high_display_num (disp_num);
-
- gdm_connection_write (conn, "OK\n");
- return;
- }
-
- if (type == DYNAMIC_REMOVE) {
- GSList *li;
- GSList *nli;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- /* shutdown a dynamic X server */
-
- for (li = displays; li != NULL; li = nli) {
- disp = li->data;
- nli = li->next;
- if (disp->dispnum == disp_num) {
- disp->removeconf = TRUE;
- gdm_display_unmanage (disp);
- gdm_connection_write (conn, "OK\n");
- return;
- }
- }
-
- msg = g_strdup_printf ("ERROR 1 Bad display number <%d>\n", disp_num);
- gdm_connection_write (conn, msg);
- return;
- }
-
- if (type == DYNAMIC_RELEASE) {
- /* cause the newly configured X servers to actually run */
- GSList *li;
- GSList *nli;
- gboolean found = FALSE;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- for (li = displays; li != NULL; li = nli) {
- GdmDisplay *disp = li->data;
- nli = li->next;
- if ((disp->dispnum == disp_num) &&
- (disp->dispstat == DISPLAY_CONFIG)) {
- disp->dispstat = DISPLAY_UNBORN;
-
- if ( ! gdm_display_manage (disp)) {
- gdm_display_unmanage (disp);
- }
- found = TRUE;
- }
- }
-
- if (found)
- gdm_connection_write (conn, "OK\n");
- else {
- msg = g_strdup_printf ("ERROR 1 Bad display number <%d>\n", disp_num);
- gdm_connection_write (conn, msg);
- }
-
- /* Now we wait for the server to start up (or not) */
- return;
- }
-}
-
-static void
-sup_handle_auth_local (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- GSList *li;
- char *cookie;
- GSList *displays;
-
- cookie = g_strdup (&msg[strlen (GDM_SUP_AUTH_LOCAL " ")]);
-
- displays = gdm_daemon_config_get_display_list ();
-
- g_strstrip (cookie);
- if (strlen (cookie) != 16*2) /* 16 bytes in hex form */ {
- /* evil, just whack the connection in this case */
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- gdm_connection_close (conn);
- g_free (cookie);
- return;
- }
- /* check if cookie matches one of the attached displays */
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
- if (disp->attached &&
- disp->cookie != NULL &&
- g_ascii_strcasecmp (disp->cookie, cookie) == 0) {
- g_free (cookie);
- GDM_CONNECTION_SET_USER_FLAG
- (conn, GDM_SUP_FLAG_AUTHENTICATED);
- gdm_connection_set_display (conn, disp);
- gdm_connection_write (conn, "OK\n");
- return;
- }
- }
-
- if (gdm_global_cookie != NULL &&
- g_ascii_strcasecmp ((gchar *) gdm_global_cookie, cookie) == 0) {
- g_free (cookie);
- GDM_CONNECTION_SET_USER_FLAG
- (conn, GDM_SUP_FLAG_AUTH_GLOBAL);
- gdm_connection_write (conn, "OK\n");
- return;
- }
-
- /* Hmmm, perhaps this is better defined behaviour */
- GDM_CONNECTION_UNSET_USER_FLAG
- (conn, GDM_SUP_FLAG_AUTHENTICATED);
- GDM_CONNECTION_UNSET_USER_FLAG
- (conn, GDM_SUP_FLAG_AUTH_GLOBAL);
- gdm_connection_set_display (conn, NULL);
- gdm_connection_write (conn, "ERROR 100 Not authenticated\n");
- g_free (cookie);
-}
-
-static void
-sup_handle_attached_servers (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- GString *retMsg;
- GSList *li;
- const gchar *sep = " ";
- char *key;
- int msgLen=0;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- if (strncmp (msg, GDM_SUP_ATTACHED_SERVERS,
- strlen (GDM_SUP_ATTACHED_SERVERS)) == 0)
- msgLen = strlen (GDM_SUP_ATTACHED_SERVERS);
- else if (strncmp (msg, GDM_SUP_CONSOLE_SERVERS,
- strlen (GDM_SUP_CONSOLE_SERVERS)) == 0)
- msgLen = strlen (GDM_SUP_CONSOLE_SERVERS);
-
- key = g_strdup (&msg[msgLen]);
- g_strstrip (key);
-
- retMsg = g_string_new ("OK");
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
-
- if ( ! disp->attached)
- continue;
- if (!(strlen (key)) || (g_pattern_match_simple (key, disp->command))) {
- g_string_append_printf (retMsg, "%s%s,%s,", sep,
- ve_sure_string (disp->name),
- ve_sure_string (disp->login));
- sep = ";";
- if (disp->type == TYPE_FLEXI_XNEST) {
- g_string_append (retMsg, ve_sure_string (disp->parent_disp));
- } else {
- g_string_append_printf (retMsg, "%d", disp->vt);
- }
- }
- }
-
- g_string_append (retMsg, "\n");
- gdm_connection_write (conn, retMsg->str);
- g_free (key);
- g_string_free (retMsg, TRUE);
-}
-
-static void
-sup_handle_get_server_details (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
-
- const gchar *server = &msg[strlen (GDM_SUP_GET_SERVER_DETAILS " ")];
- gchar **splitstr = g_strsplit (server, " ", 2);
- GdmXserver *svr = gdm_daemon_config_find_xserver ((gchar *)splitstr[0]);
-
- if (svr != NULL) {
- if (g_strcasecmp (splitstr[1], "ID") == 0)
- gdm_connection_printf (conn, "OK %s\n", svr->id);
- else if (g_strcasecmp (splitstr[1], "NAME") == 0)
- gdm_connection_printf (conn, "OK %s\n", svr->name);
- else if (g_strcasecmp (splitstr[1], "COMMAND") == 0)
- gdm_connection_printf (conn, "OK %s\n", svr->command);
- else if (g_strcasecmp (splitstr[1], "PRIORITY") == 0)
- gdm_connection_printf (conn, "OK %d\n", svr->priority);
- else if (g_strcasecmp (splitstr[1], "FLEXIBLE") == 0 &&
- svr->flexible)
- gdm_connection_printf (conn, "OK true\n");
- else if (g_strcasecmp (splitstr[1], "FLEXIBLE") == 0 &&
- !svr->flexible)
- gdm_connection_printf (conn, "OK false\n");
- else if (g_strcasecmp (splitstr[1], "CHOOSABLE") == 0 &&
- svr->choosable)
- gdm_connection_printf (conn, "OK true\n");
- else if (g_strcasecmp (splitstr[1], "CHOOSABLE") == 0 &&
- !svr->choosable)
- gdm_connection_printf (conn, "OK false\n");
- else if (g_strcasecmp (splitstr[1], "HANDLED") == 0 &&
- svr->handled)
- gdm_connection_printf (conn, "OK true\n");
- else if (g_strcasecmp (splitstr[1], "HANDLED") == 0 &&
- !svr->handled)
- gdm_connection_printf (conn, "OK false\n");
- else if (g_strcasecmp (splitstr[1], "CHOOSER") == 0 &&
- svr->chooser)
- gdm_connection_printf (conn, "OK true\n");
- else if (g_strcasecmp (splitstr[1], "CHOOSER") == 0 &&
- !svr->chooser)
- gdm_connection_printf (conn, "OK false\n");
- else
- gdm_connection_printf (conn, "ERROR 2 Key not valid\n");
-
- g_strfreev (splitstr);
- } else {
- gdm_connection_printf (conn, "ERROR 1 Server not found\n");
- }
-}
-
-static void
-sup_handle_flexi_xserver (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- char *name;
- const char *command = NULL;
- GdmXserver *svr;
- const char *rest;
- char *username;
- char *end;
- gboolean has_user;
-
- has_user = strncmp (msg, GDM_SUP_FLEXI_XSERVER_USER " ", strlen (GDM_SUP_FLEXI_XSERVER_USER " ")) == 0;
-
- g_debug ("Handling flexi request has-user:%d", has_user);
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn)) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "FLEXI_XSERVER");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- if (has_user) {
- rest = msg + strlen (GDM_SUP_FLEXI_XSERVER_USER " ");
- end = strchr (rest, ' ');
- if (end) {
- username = g_strndup (rest, end - rest);
- rest = end + 1;
- } else {
- username = g_strdup (rest);
- rest = rest + strlen (rest);
- }
- } else {
- rest = msg + strlen (GDM_SUP_FLEXI_XSERVER " ");
- username = NULL;
- }
-
- name = g_strdup (rest);
- g_strstrip (name);
- if (ve_string_empty (name)) {
- g_free (name);
- name = g_strdup (GDM_STANDARD);
- }
-
- svr = gdm_daemon_config_find_xserver (name);
-
- if G_UNLIKELY (svr == NULL) {
- /* Don't print the name to syslog as it might be
- * long and dangerous */
- gdm_error (_("Unknown server type requested; using "
- "standard server."));
- command = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER);
- } else if G_UNLIKELY ( ! svr->flexible) {
- gdm_error (_("Requested server %s not allowed to be "
- "used for flexible servers; using "
- "standard server."), name);
- command = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER);
- } else {
- command = svr->command;
- }
- g_free (name);
-
- handle_flexi_server (conn,
- TYPE_FLEXI,
- command,
- /* It is kind of ugly that we don't use
- the standard resolution for this, but
- oh well, this makes other things simpler */
- svr->handled,
- svr->chooser,
- NULL,
- 0,
- NULL,
- NULL,
- username);
- g_free (username);
-}
-
-static void
-sup_handle_flexi_xnest (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- char *dispname = NULL;
- char *xauthfile = NULL;
- char *cookie = NULL;
- uid_t uid;
- const char *rest;
- char *username;
- char *end;
- gboolean has_user;
-
- has_user = strncmp (msg, GDM_SUP_FLEXI_XNEST_USER " ", strlen (GDM_SUP_FLEXI_XNEST_USER " ")) == 0;
-
- g_debug ("Handling flexi xnest request has-user:%d", has_user);
-
- if (has_user) {
- rest = msg + strlen (GDM_SUP_FLEXI_XNEST_USER " ");
- end = strchr (rest, ' ');
- username = g_strndup (rest, end - rest);
- } else {
- rest = msg;
- username = NULL;
- }
-
- extract_dispname_uid_xauthfile_cookie (rest,
- &dispname,
- &uid,
- &xauthfile,
- &cookie);
-
- if (dispname == NULL) {
- /* Something bogus is going on, so just whack the
- * connection */
- g_free (xauthfile);
- gdm_connection_close (conn);
- g_warning ("Unable to get display name from request");
- return;
- }
-
- /* This is probably a pre-2.2.4.2 client */
- if (xauthfile == NULL || cookie == NULL) {
- /* evil, just whack the connection in this case */
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- gdm_connection_close (conn);
- g_free (cookie);
- return;
- }
-
- handle_flexi_server (conn,
- TYPE_FLEXI_XNEST,
- gdm_daemon_config_get_value_string (GDM_KEY_XNEST),
- TRUE /* handled */,
- FALSE /* chooser */,
- dispname,
- uid,
- xauthfile,
- cookie,
- username);
-
- g_free (dispname);
- g_free (xauthfile);
- g_free (username);
-}
-
-static void
-sup_handle_get_config (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- const char *parms;
- char **splitstr;
- char *retval;
- static gboolean done_prefetch = FALSE;
-
- retval = NULL;
- parms = &msg[strlen (GDM_SUP_GET_CONFIG " ")];
-
- splitstr = g_strsplit (parms, " ", 2);
-
- if (splitstr == NULL || splitstr[0] == NULL) {
- goto out;
- }
-
- /*
- * It is not meaningful to manage this in a per-display
- * fashion since the prefetch program is only run once the
- * for the first display that requests the key. So process
- * this first and return "Unsupported key" for requests
- * after the first request.
- */
- if (strcmp (splitstr[0], GDM_KEY_PRE_FETCH_PROGRAM) == 0) {
- if (done_prefetch) {
- gdm_connection_printf (conn, "OK \n");
- } else {
- gdm_connection_printf (conn, "ERROR 50 Unsupported key <%s>\n", splitstr[0]);
- done_prefetch = TRUE;
- }
- goto out;
- }
-
- if (splitstr[0] != NULL) {
- gboolean res;
-
- /*
- * Note passing in the display is backwards compatible
- * since if it is NULL, it won't try to load the display
- * value at all.
- */
-
- g_debug ("Handling GET_CONFIG: %s for display %s", splitstr[0], splitstr[1]);
-
- res = gdm_daemon_config_to_string (splitstr[0], splitstr[1], &retval);
-
- if (res) {
- gdm_connection_printf (conn, "OK %s\n", retval);
- g_free (retval);
- } else {
- if (gdm_daemon_config_is_valid_key ((gchar *)splitstr[0]))
- gdm_connection_printf (conn, "OK \n");
- else
- gdm_connection_printf (conn,
- "ERROR 50 Unsupported key <%s>\n",
- splitstr[0]);
- }
- }
- out:
- g_strfreev (splitstr);
-}
-
-static gboolean
-is_action_available (GdmDisplay *disp, gchar *action)
-{
- const gchar **allowsyscmd;
- const gchar **rbackeys;
- gboolean sysmenu;
- gboolean ret = FALSE;
- int i;
-
- allowsyscmd = gdm_daemon_config_get_value_string_array (GDM_KEY_ALLOW_LOGOUT_ACTIONS);
- rbackeys = gdm_daemon_config_get_value_string_array (GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS);
- sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
-
- if (!disp->attached || !sysmenu) {
- return FALSE;
- }
-
- for (i = 0; allowsyscmd[i] != NULL; i++) {
- if (strcmp (allowsyscmd[i], action) == 0) {
- ret = TRUE;
- break;
- }
- }
-
-#ifdef HAVE_CHKAUTHATTR
- if (ret == TRUE && rbackeys) {
- for (i = 0; rbackeys[i] != NULL; i++) {
- gchar **rbackey = g_strsplit (rbackeys[i], ":", 2);
-
- if (! ve_string_empty (rbackey[0]) &&
- ! ve_string_empty (rbackey[1]) &&
- strcmp (rbackey[0], action) == 0) {
-
- if (!chkauthattr (rbackey[1], disp->login)) {
- g_strfreev (rbackey);
- ret = FALSE;
- break;
- }
-
- }
- g_strfreev (rbackey);
- }
- }
-#endif
-
- return ret;
-}
-
-static void
-sup_handle_query_logout_action (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- GdmLogoutAction logout_action;
- GdmDisplay *disp;
- GString *reply;
- const gchar *sep = " ";
- int i;
-
- disp = gdm_connection_get_display (conn);
-
- /* Only allow locally authenticated connections */
- if (! GDM_CONN_AUTHENTICATED (conn) || disp == NULL) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "QUERY_LOGOUT_ACTION");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- reply = g_string_new ("OK");
-
- logout_action = disp->logout_action;
- if (logout_action == GDM_LOGOUT_ACTION_NONE)
- logout_action = safe_logout_action;
-
- if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_HALT)) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) {
- g_string_append_printf (reply, "%s%s", sep,
- GDM_SUP_LOGOUT_ACTION_HALT);
- if (logout_action == GDM_LOGOUT_ACTION_HALT)
- g_string_append (reply, "!");
- sep = ";";
- }
- if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT)) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) {
- g_string_append_printf (reply, "%s%s", sep,
- GDM_SUP_LOGOUT_ACTION_REBOOT);
- if (logout_action == GDM_LOGOUT_ACTION_REBOOT)
- g_string_append (reply, "!");
- sep = ";";
- }
- if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND)) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
- g_string_append_printf (reply, "%s%s", sep,
- GDM_SUP_LOGOUT_ACTION_SUSPEND);
- if (logout_action == GDM_LOGOUT_ACTION_SUSPEND)
- g_string_append (reply, "!");
- sep = ";";
- }
-
- if (is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
- for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
- gchar *key_string = NULL;
- key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
-
- if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
-
- g_free (key_string);
- key_string = g_strdup_printf("%s%d=",
- GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
-
- if (gdm_daemon_config_get_value_bool (key_string)) {
- g_string_append_printf (reply, "%s%s%d", sep,
- GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, i);
- if (logout_action == (GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + i))
- g_string_append (reply, "!");
- sep = ";";
- }
- }
- g_free(key_string);
- }
- }
-
- g_string_append (reply, "\n");
- gdm_connection_write (conn, reply->str);
- g_string_free (reply, TRUE);
-}
-
-static void
-sup_handle_query_custom_cmd_labels (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
-
- GdmDisplay *disp;
- GString *reply;
- const gchar *sep = " ";
- gboolean sysmenu;
- int i;
-
- disp = gdm_connection_get_display (conn);
- sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn) ||
- disp == NULL) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "QUERY_CUSTOM_CMD_LABELS");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- reply = g_string_new ("OK");
-
- for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
- gchar *key_string = NULL;
- key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
- if (sysmenu && disp->attached &&
- ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
- g_free (key_string);
- key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
- if (gdm_daemon_config_get_value_bool (key_string)) {
- g_free (key_string);
- key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE, i);
- g_string_append_printf (reply, "%s%s", sep, gdm_daemon_config_get_value_string (key_string));
- sep = ";";
- }
- }
- g_free(key_string);
- }
-
- g_string_append (reply, "\n");
- gdm_connection_write (conn, reply->str);
- g_string_free (reply, TRUE);
-}
-
-static void
-sup_handle_all_servers (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- GString *reply;
- GSList *li;
- const gchar *sep = " ";
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- reply = g_string_new ("OK");
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
- g_string_append_printf (reply, "%s%s,%s", sep,
- ve_sure_string (disp->name),
- ve_sure_string (disp->login));
- sep = ";";
- }
- g_string_append (reply, "\n");
- gdm_connection_write (conn, reply->str);
- g_string_free (reply, TRUE);
-}
-
-static void
-sup_handle_get_server_list (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- gchar *retval = gdm_daemon_config_get_xservers ();
-
- if (retval != NULL) {
- gdm_connection_printf (conn, "OK %s\n", retval);
- g_free (retval);
- } else {
- gdm_connection_printf (conn, "ERROR 1 No servers found\n");
- }
-}
-
-static void
-sup_handle_get_custom_config_file (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- gchar *ret;
-
- ret = gdm_daemon_config_get_custom_config_file ();
- if (ret)
- gdm_connection_printf (conn, "OK %s\n", ret);
- else
- gdm_connection_write (conn,
- "ERROR 1 File not found\n");
-}
-
-static void
-sup_handle_greeterpids (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- GString *reply;
- GSList *li;
- const gchar *sep = " ";
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- reply = g_string_new ("OK");
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
- if (disp->greetpid > 0) {
- g_string_append_printf (reply, "%s%ld",
- sep, (long)disp->greetpid);
- sep = ";";
- }
- }
- g_string_append (reply, "\n");
- gdm_connection_write (conn, reply->str);
- g_string_free (reply, TRUE);
-}
-
-static void
-sup_handle_query_custom_cmd_no_restart_status (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
-
- GdmDisplay *disp;
- GString *reply;
- gboolean sysmenu;
- unsigned long no_restart_status_flag = 0; /* we can store up-to 32 commands this way */
- int i;
-
- disp = gdm_connection_get_display (conn);
- sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name);
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn) ||
- disp == NULL) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "QUERY_CUSTOM_CMD_NO_RESTART_STATUS");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- reply = g_string_new ("OK ");
-
- for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
- gchar *key_string = NULL;
- key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
- if (sysmenu && disp->attached &&
- ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
- g_free (key_string);
- key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
- if (gdm_daemon_config_get_value_bool (key_string)) {
- g_free (key_string);
- key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, i);
- if(gdm_daemon_config_get_value_bool (key_string))
- no_restart_status_flag |= (1 << i);
- }
- }
- g_free(key_string);
- }
-
- g_string_append_printf (reply, "%ld\n", no_restart_status_flag);
- gdm_connection_write (conn, reply->str);
- g_string_free (reply, TRUE);
-}
-
-static void
-sup_handle_set_logout_action (GdmConnection *conn,
- const char *msg,
- gpointer data)
-
-{
- GdmDisplay *disp;
- const gchar *action;
- gboolean was_ok = FALSE;
-
- action = &msg[strlen (GDM_SUP_SET_LOGOUT_ACTION " ")];
- disp = gdm_connection_get_display (conn);
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn) ||
- disp == NULL ||
- ! disp->logged_in) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "SET_LOGOUT_ACTION");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) {
- disp->logout_action = GDM_LOGOUT_ACTION_NONE;
- was_ok = TRUE;
- } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0 &&
- ! gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) {
- disp->logout_action = GDM_LOGOUT_ACTION_HALT;
- was_ok = TRUE;
- } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0 &&
- ! gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) {
- disp->logout_action = GDM_LOGOUT_ACTION_REBOOT;
- was_ok = TRUE;
- } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0 &&
- ! gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
- disp->logout_action = GDM_LOGOUT_ACTION_SUSPEND;
- was_ok = TRUE;
- }
- else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
- strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
-
- int cmd_index;
- if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) {
- gchar *key_string = NULL;
- key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index);
- if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
- disp->logout_action =
- GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
- was_ok = TRUE;
- }
- g_free(key_string);
- }
- }
-
- if (was_ok) {
- gdm_connection_write (conn, "OK\n");
- gdm_try_logout_action (disp);
- } else {
- gdm_connection_write (conn, "ERROR 7 Unknown logout action, or not available\n");
- }
-}
-
-static void
-sup_handle_set_safe_logout_action (GdmConnection *conn,
- const char *msg,
- gpointer data)
-
-{
- GdmDisplay *disp;
- const gchar *action;
- gboolean was_ok = FALSE;
-
- action = &msg[strlen (GDM_SUP_SET_SAFE_LOGOUT_ACTION " ")];
- disp = gdm_connection_get_display (conn);
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn) ||
- disp == NULL ||
- ! disp->logged_in) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "SET_LOGOUT_ACTION");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) {
- safe_logout_action = GDM_LOGOUT_ACTION_NONE;
- was_ok = TRUE;
- } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0 &&
- ! gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) {
- safe_logout_action = GDM_LOGOUT_ACTION_HALT;
- was_ok = TRUE;
- } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0 &&
- ! gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) {
- safe_logout_action = GDM_LOGOUT_ACTION_REBOOT;
- was_ok = TRUE;
- } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0 &&
- ! gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
- safe_logout_action = GDM_LOGOUT_ACTION_SUSPEND;
- was_ok = TRUE;
- }
- else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
- strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 &&
- is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
-
- int cmd_index;
- if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) {
-
- gchar *key_string = NULL;
- key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index);
-
- if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
- safe_logout_action =
- GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
- was_ok = TRUE;
- }
- g_free(key_string);
- }
- }
-
- if (was_ok) {
- gdm_connection_write (conn, "OK\n");
- gdm_try_logout_action (disp);
- } else {
- gdm_connection_write (conn, "ERROR 7 Unknown logout action, or not available\n");
- }
-}
-
-static void
-sup_handle_query_vt (GdmConnection *conn,
- const char *msg,
- gpointer data)
-
-{
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn)) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "QUERY_VT");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
-#if defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__)
- gdm_connection_printf (conn, "OK %d\n", gdm_get_cur_vt ());
-#else
- gdm_connection_write (conn, "ERROR 8 Virtual terminals not supported\n");
-#endif
-}
-
-static void
-sup_handle_set_vt (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
- int vt;
- GSList *li;
- GSList *displays;
-
- displays = gdm_daemon_config_get_display_list ();
-
- if (sscanf (msg, GDM_SUP_SET_VT " %d", &vt) != 1 ||
- vt < 0) {
- gdm_connection_write (conn,
- "ERROR 9 Invalid virtual terminal number\n");
- return;
- }
-
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn)) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "QUERY_VT");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
-#if defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__)
- gdm_change_vt (vt);
- for (li = displays; li != NULL; li = li->next) {
- GdmDisplay *disp = li->data;
- if (disp->vt == vt) {
- send_slave_command (disp, GDM_NOTIFY_TWIDDLE_POINTER);
- break;
- }
- }
- gdm_connection_write (conn, "OK\n");
-#else
- gdm_connection_write (conn, "ERROR 8 Virtual terminals not supported\n");
-#endif
-}
-
-static void
-gdm_handle_user_message (GdmConnection *conn,
- const char *msg,
- gpointer data)
-{
-
- g_debug ("Handling user message: '%s'", msg);
-
- if (gdm_connection_get_message_count (conn) > GDM_SUP_MAX_MESSAGES) {
- g_debug ("Closing connection, %d messages reached", GDM_SUP_MAX_MESSAGES);
- gdm_connection_write (conn, "ERROR 200 Too many messages\n");
- gdm_connection_close (conn);
- return;
- }
-
- if (strncmp (msg, GDM_SUP_AUTH_LOCAL " ",
- strlen (GDM_SUP_AUTH_LOCAL " ")) == 0) {
-
- sup_handle_auth_local (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_FLEXI_XSERVER) == 0) {
- /* Only allow locally authenticated connections */
- if ( ! GDM_CONN_AUTHENTICATED (conn)) {
- gdm_info (_("%s request denied: "
- "Not authenticated"), "FLEXI_XSERVER");
- gdm_connection_write (conn,
- "ERROR 100 Not authenticated\n");
- return;
- }
-
- handle_flexi_server (conn,
- TYPE_FLEXI,
- gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER),
- TRUE /* handled */,
- FALSE /* chooser */,
- NULL,
- 0,
- NULL,
- NULL,
- NULL);
- } else if ((strncmp (msg, GDM_SUP_FLEXI_XSERVER_USER " ",
- strlen (GDM_SUP_FLEXI_XSERVER_USER " ")) == 0) ||
- (strncmp (msg, GDM_SUP_FLEXI_XSERVER " ",
- strlen (GDM_SUP_FLEXI_XSERVER " ")) == 0)) {
-
- sup_handle_flexi_xserver (conn, msg, data);
-
- } else if ((strncmp (msg, GDM_SUP_FLEXI_XNEST_USER " ",
- strlen (GDM_SUP_FLEXI_XNEST_USER " ")) == 0) ||
- (strncmp (msg, GDM_SUP_FLEXI_XNEST " ",
- strlen (GDM_SUP_FLEXI_XNEST " ")) == 0)) {
-
- sup_handle_flexi_xnest (conn, msg, data);
-
- } else if ((strncmp (msg, GDM_SUP_ATTACHED_SERVERS,
- strlen (GDM_SUP_ATTACHED_SERVERS)) == 0) ||
- (strncmp (msg, GDM_SUP_CONSOLE_SERVERS,
- strlen (GDM_SUP_CONSOLE_SERVERS)) == 0)) {
-
- sup_handle_attached_servers (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_ALL_SERVERS) == 0) {
-
- sup_handle_all_servers (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_GET_SERVER_LIST) == 0) {
-
- sup_handle_get_server_list (conn, msg, data);
-
- } else if (strncmp (msg, GDM_SUP_GET_SERVER_DETAILS " ",
- strlen (GDM_SUP_GET_SERVER_DETAILS " ")) == 0) {
-
- sup_handle_get_server_details (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_GREETERPIDS) == 0) {
-
- sup_handle_greeterpids (conn, msg, data);
-
- } else if (strncmp (msg, GDM_SUP_UPDATE_CONFIG " ",
- strlen (GDM_SUP_UPDATE_CONFIG " ")) == 0) {
- const char *key;
-
- key = &msg[strlen (GDM_SUP_UPDATE_CONFIG " ")];
-
- if (! gdm_daemon_config_update_key ((gchar *)key))
- gdm_connection_printf (conn, "ERROR 50 Unsupported key <%s>\n", key);
- else
- gdm_connection_write (conn, "OK\n");
- } else if (strncmp (msg, GDM_SUP_GET_CONFIG " ",
- strlen (GDM_SUP_GET_CONFIG " ")) == 0) {
-
- sup_handle_get_config (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_GET_CONFIG_FILE) == 0) {
- /*
- * Value is only non-null if passed in on command line.
- * Otherwise print compiled-in default file location.
- */
- if (config_file == NULL) {
- gdm_connection_printf (conn, "OK %s\n",
- GDM_DEFAULTS_CONF);
- } else {
- gdm_connection_printf (conn, "OK %s\n", config_file);
- }
- } else if (strcmp (msg, GDM_SUP_GET_CUSTOM_CONFIG_FILE) == 0) {
-
- sup_handle_get_custom_config_file (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_QUERY_LOGOUT_ACTION) == 0) {
-
- sup_handle_query_logout_action (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_QUERY_CUSTOM_CMD_LABELS) == 0) {
-
- sup_handle_query_custom_cmd_labels (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_QUERY_CUSTOM_CMD_NO_RESTART_STATUS) == 0) {
-
- sup_handle_query_custom_cmd_no_restart_status (conn, msg, data);
-
- } else if (strncmp (msg, GDM_SUP_SET_LOGOUT_ACTION " ",
- strlen (GDM_SUP_SET_LOGOUT_ACTION " ")) == 0) {
-
- sup_handle_set_logout_action (conn, msg, data);
-
- } else if (strncmp (msg, GDM_SUP_SET_SAFE_LOGOUT_ACTION " ",
- strlen (GDM_SUP_SET_SAFE_LOGOUT_ACTION " ")) == 0) {
-
- sup_handle_set_safe_logout_action (conn, msg, data);
-
- } else if (strcmp (msg, GDM_SUP_QUERY_VT) == 0) {
-
- sup_handle_query_vt (conn, msg, data);
-
- } else if (strncmp (msg, GDM_SUP_SET_VT " ",
- strlen (GDM_SUP_SET_VT " ")) == 0) {
-
- sup_handle_set_vt (conn, msg, data);
-
- } else if (strncmp (msg, GDM_SUP_ADD_DYNAMIC_DISPLAY " ",
- strlen (GDM_SUP_ADD_DYNAMIC_DISPLAY " ")) == 0) {
- gchar *key;
-
- key = g_strdup (&msg[strlen (GDM_SUP_ADD_DYNAMIC_DISPLAY " ")]);
- g_strstrip (key);
- handle_dynamic_server (conn, DYNAMIC_ADD, key);
- g_free (key);
-
- } else if (strncmp (msg, GDM_SUP_REMOVE_DYNAMIC_DISPLAY " ",
- strlen (GDM_SUP_REMOVE_DYNAMIC_DISPLAY " ")) == 0) {
- gchar *key;
-
- key = g_strdup (&msg[strlen (GDM_SUP_REMOVE_DYNAMIC_DISPLAY " ")]);
- g_strstrip (key);
- handle_dynamic_server (conn, DYNAMIC_REMOVE, key);
- g_free (key);
-
- } else if (strncmp (msg, GDM_SUP_RELEASE_DYNAMIC_DISPLAYS " ",
- strlen (GDM_SUP_RELEASE_DYNAMIC_DISPLAYS " ")) == 0) {
-
- gchar *key;
-
- key = g_strdup (&msg[strlen (GDM_SUP_RELEASE_DYNAMIC_DISPLAYS " ")]);
- g_strstrip (key);
- handle_dynamic_server (conn, DYNAMIC_RELEASE, key);
- g_free (key);
-
- } else if (strcmp (msg, GDM_SUP_VERSION) == 0) {
- gdm_connection_write (conn, "GDM " VERSION "\n");
- } else if (strcmp (msg, GDM_SUP_SERVER_BUSY) == 0) {
- if (gdm_connection_is_server_busy (unixconn))
- gdm_connection_write (conn, "OK true\n");
- else
- gdm_connection_write (conn, "OK false\n");
- } else if (strcmp (msg, GDM_SUP_CLOSE) == 0) {
- gdm_connection_close (conn);
- } else {
- gdm_connection_write (conn, "ERROR 0 Not implemented\n");
- gdm_connection_close (conn);
- }
-}