diff options
Diffstat (limited to 'daemon/main.c')
-rw-r--r-- | daemon/main.c | 766 |
1 files changed, 0 insertions, 766 deletions
diff --git a/daemon/main.c b/daemon/main.c deleted file mode 100644 index 414a9dd3..00000000 --- a/daemon/main.c +++ /dev/null @@ -1,766 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> -#include <wait.h> -#include <locale.h> - -#include <glib.h> -#include <glib/gi18n.h> -#include <glib/gstdio.h> -#include <glib-object.h> - -#define DBUS_API_SUBJECT_TO_CHANGE -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> - -#include "gdm-manager.h" -#include "gdm-log.h" -#include "gdm-signal-handler.h" - -#include "gdm-settings.h" -#include "gdm-settings-direct.h" -#include "gdm-settings-keys.h" - -#define GDM_DBUS_NAME "org.gnome.DisplayManager" - -static void bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, - GdmManager *manager); - -extern char **environ; - -static char **stored_argv = NULL; -static int stored_argc = 0; -static GList *stored_env = NULL; -static GdmManager *manager = NULL; -static GdmSettings *settings = NULL; -static uid_t gdm_uid = -1; -static gid_t gdm_gid = -1; - -static gboolean -timed_exit_cb (GMainLoop *loop) -{ - g_main_loop_quit (loop); - return FALSE; -} - -static DBusGProxy * -get_bus_proxy (DBusGConnection *connection) -{ - DBusGProxy *bus_proxy; - - bus_proxy = dbus_g_proxy_new_for_name (connection, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - return bus_proxy; -} - -static gboolean -acquire_name_on_proxy (DBusGProxy *bus_proxy) -{ - GError *error; - guint result; - gboolean res; - gboolean ret; - - ret = FALSE; - - if (bus_proxy == NULL) { - goto out; - } - - error = NULL; - res = dbus_g_proxy_call (bus_proxy, - "RequestName", - &error, - G_TYPE_STRING, GDM_DBUS_NAME, - G_TYPE_UINT, 0, - G_TYPE_INVALID, - G_TYPE_UINT, &result, - G_TYPE_INVALID); - if (! res) { - if (error != NULL) { - g_warning ("Failed to acquire %s: %s", GDM_DBUS_NAME, error->message); - g_error_free (error); - } else { - g_warning ("Failed to acquire %s", GDM_DBUS_NAME); - } - goto out; - } - - if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - if (error != NULL) { - g_warning ("Failed to acquire %s: %s", GDM_DBUS_NAME, error->message); - g_error_free (error); - } else { - g_warning ("Failed to acquire %s", GDM_DBUS_NAME); - } - goto out; - } - - ret = TRUE; - - out: - return ret; -} - -static DBusGConnection * -get_system_bus (void) -{ - GError *error; - DBusGConnection *bus; - DBusConnection *connection; - - error = NULL; - bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); - if (bus == NULL) { - g_warning ("Couldn't connect to system bus: %s", - error->message); - g_error_free (error); - goto out; - } - - connection = dbus_g_connection_get_connection (bus); - dbus_connection_set_exit_on_disconnect (connection, FALSE); - - out: - return bus; -} - -static gboolean -bus_reconnect (GdmManager *manager) -{ - DBusGConnection *bus; - DBusGProxy *bus_proxy; - gboolean ret; - - ret = TRUE; - - bus = get_system_bus (); - if (bus == NULL) { - goto out; - } - - bus_proxy = get_bus_proxy (bus); - if (bus_proxy == NULL) { - g_warning ("Could not construct bus_proxy object; will retry"); - goto out; - } - - if (! acquire_name_on_proxy (bus_proxy) ) { - g_warning ("Could not acquire name; will retry"); - goto out; - } - - manager = gdm_manager_new (); - if (manager == NULL) { - g_warning ("Could not construct manager object"); - exit (1); - } - - g_signal_connect (bus_proxy, - "destroy", - G_CALLBACK (bus_proxy_destroyed_cb), - manager); - - g_debug ("Successfully reconnected to D-Bus"); - - ret = FALSE; - - out: - return ret; -} - -static void -bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, - GdmManager *manager) -{ - g_debug ("Disconnected from D-Bus"); - - g_object_unref (manager); - manager = NULL; - - g_timeout_add (3000, (GSourceFunc)bus_reconnect, manager); -} - -static void -delete_pid (void) -{ - g_unlink (GDM_PID_FILE); -} - -static void -write_pid (void) -{ - int pf; - ssize_t written; - char pid[9]; - - errno = 0; - pf = open (GDM_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644); - if (pf < 0) { - g_warning (_("Cannot write PID file %s: possibly out of diskspace: %s"), - GDM_PID_FILE, - g_strerror (errno)); - - return; - } - - snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ()); - errno = 0; - written = write (pf, pid, strlen (pid)); - close (pf); - - if (written < 0) { - g_warning (_("Cannot write PID file %s: possibly out of diskspace: %s"), - GDM_PID_FILE, - g_strerror (errno)); - return; - } - - g_atexit (delete_pid); -} - -static void -gdm_final_cleanup (void) -{ - g_object_unref (manager); -} - -/* - * ------------------------------------- - * BEGIN Copyright status/holder unknown - * ------------------------------------- - */ -static void -main_saveenv (void) -{ - int i; - - g_list_foreach (stored_env, (GFunc)g_free, NULL); - g_list_free (stored_env); - stored_env = NULL; - - for (i = 0; environ[i] != NULL; i++) { - char *env = environ[i]; - stored_env = g_list_prepend (stored_env, g_strdup (env)); - } -} - -static void -main_restoreenv (void) -{ - GList *li; - -#ifdef HAVE_CLEARENV - clearenv (); -#else - if (environ != NULL) { - environ[0] = NULL; - } -#endif - - /* FIXME: leaks */ - - for (li = stored_env; li != NULL; li = li->next) { - putenv (g_strdup (li->data)); - } -} - -static void -gdm_restart_now (void) -{ - gdm_info (_("GDM restarting ...")); - gdm_final_cleanup (); - main_restoreenv (); - - do { - errno = 0; - execvp (stored_argv[0], stored_argv); - } while (errno == EINTR); - - g_warning (_("Failed to restart self")); - _exit (1); -} - -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 -check_logdir (void) -{ - struct stat statbuf; - int r; - const char *log_path; - - log_path = LOGDIR; - - r = g_stat (log_path, &statbuf); - if (r < 0 || ! S_ISDIR (statbuf.st_mode)) { - gdm_fail (_("Logdir %s does not exist or isn't a directory."), log_path); - } -} - -static void -check_servauthdir (const char *auth_path, - struct stat *statbuf) -{ - int r; - - /* Enter paranoia mode */ - r = g_stat (auth_path, statbuf); - if (r < 0) { - gdm_fail (_("Authdir %s does not exist. Aborting."), auth_path); - } - - if (! S_ISDIR (statbuf->st_mode)) { - gdm_fail (_("Authdir %s is not a directory. Aborting."), auth_path); - } -} - -static void -set_effective_user (uid_t uid) -{ - int res; - - res = 0; - - if (geteuid () != uid) { - res = seteuid (uid); - } - - if (res != 0) { - g_error ("Cannot set uid to %d: %s", - (int)uid, - g_strerror (errno)); - } -} - -static void -set_effective_group (gid_t gid) -{ - int res; - - res = 0; - if (getegid () != gid) { - res = setegid (gid); - } - - if (res != 0) { - g_error ("Cannot set gid to %d: %s", - (int)gid, - g_strerror (errno)); - } -} - -static void -set_effective_user_group (uid_t uid, - gid_t gid) -{ - set_effective_user (0); - set_effective_group (gid); - if (uid != 0) { - set_effective_user (0); - } -} - -static void -gdm_daemon_check_permissions (uid_t uid, - gid_t gid) -{ - struct stat statbuf; - const char *auth_path; - - auth_path = LOGDIR; - - /* Enter paranoia mode */ - check_servauthdir (auth_path, &statbuf); - - set_effective_user_group (0, 0); - - /* Now set things up for us as */ - chown (auth_path, 0, gid); - g_chmod (auth_path, (S_IRWXU|S_IRWXG|S_ISVTX)); - - set_effective_user_group (uid, gid); - - /* Again paranoid */ - check_servauthdir (auth_path, &statbuf); - - if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != gid) { - gdm_fail (_("Authdir %s is not owned by user %d, group %d. Aborting."), - auth_path, - (int)uid, - (int)gid); - } - - if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX)) { - gdm_fail (_("Authdir %s has wrong permissions %o. Should be %o. Aborting."), - auth_path, - statbuf.st_mode, - (S_IRWXU|S_IRWXG|S_ISVTX)); - } -} - -static void -gdm_daemon_change_user (uid_t *uidp, - gid_t *gidp) -{ - char *username; - char *groupname; - uid_t uid; - gid_t gid; - struct passwd *pwent; - struct group *grent; - - username = NULL; - groupname = NULL; - uid = 0; - gid = 0; - - gdm_settings_direct_get_string (GDM_KEY_USER, &username); - gdm_settings_direct_get_string (GDM_KEY_GROUP, &groupname); - - if (username == NULL || groupname == NULL) { - return; - } - - g_debug ("Changing user:group to %s:%s", username, groupname); - - /* Lookup user and groupid for the GDM user */ - pwent = getpwnam (username); - - /* Set uid and gid */ - if G_UNLIKELY (pwent == NULL) { - gdm_fail (_("Can't find the GDM user '%s'. Aborting!"), username); - } else { - uid = pwent->pw_uid; - } - - if G_UNLIKELY (uid == 0) { - gdm_fail (_("The GDM user should not be root. Aborting!")); - } - - grent = getgrnam (groupname); - - if G_UNLIKELY (grent == NULL) { - gdm_fail (_("Can't find the GDM group '%s'. Aborting!"), groupname); - } else { - gid = grent->gr_gid; - } - - if G_UNLIKELY (gid == 0) { - gdm_fail (_("The GDM group should not be root. Aborting!")); - } - - /* gid remains `gdm' */ - set_effective_user_group (uid, gid); - - if (uidp != NULL) { - *uidp = uid; - } - - if (gidp != NULL) { - *gidp = gid; - } - - g_free (username); - g_free (groupname); -} - -/* - * ------------------------------------- - * END Copyright status/holder unknown - * ------------------------------------- - */ - -static gboolean -signal_cb (int signo, - gpointer data) -{ - int ret; - - g_debug ("Got callback for signal %d", signo); - - ret = TRUE; - - switch (signo) { - case SIGSEGV: - case SIGBUS: - case SIGILL: - case SIGABRT: - g_debug ("Caught signal %d.", signo); - - ret = FALSE; - break; - - case SIGFPE: - case SIGPIPE: - /* let the fatal signals interrupt us */ - g_debug ("Caught signal %d, shutting down abnormally.", signo); - ret = FALSE; - - break; - - case SIGINT: - case SIGTERM: - /* let the fatal signals interrupt us */ - g_debug ("Caught signal %d, shutting down normally.", signo); - ret = FALSE; - - break; - - case SIGHUP: - g_debug ("Got HUP signal"); - /* FIXME: - * Reread config stuff like system config files, VPN service files, etc - */ - ret = TRUE; - - break; - - case SIGUSR1: - g_debug ("Got USR1 signal"); - /* FIXME: - * Play with log levels or something - */ - ret = TRUE; - - gdm_log_toggle_debug (); - - break; - - default: - g_debug ("Caught unhandled signal %d", signo); - ret = TRUE; - - break; - } - - return ret; -} - -int -main (int argc, - char **argv) -{ - GMainLoop *main_loop; - GOptionContext *context; - DBusGProxy *bus_proxy; - DBusGConnection *connection; - GError *error; - int ret; - int i; - gboolean res; - GdmSignalHandler *signal_handler; - static char *config_file = NULL; - static gboolean debug = FALSE; - static gboolean no_daemon = FALSE; - static gboolean no_console = FALSE; - static gboolean do_timed_exit = FALSE; - static gboolean print_version = FALSE; - static gboolean fatal_warnings = FALSE; - static GOptionEntry entries [] = { - { "config", 0, 0, G_OPTION_ARG_STRING, &config_file, N_("Alternative GDM System Defaults configuration file"), N_("CONFIGFILE") }, - - { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, - { "fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &fatal_warnings, N_("Make all warnings fatal"), NULL }, - { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_("Don't become a daemon"), NULL }, - { "no-console", 0, 0, G_OPTION_ARG_NONE, &no_console, N_("No console (static) servers to be run"), NULL }, - - { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time - for debugging"), NULL }, - { "version", 0, 0, G_OPTION_ARG_NONE, &print_version, N_("Print GDM version"), NULL }, - - { NULL } - }; - - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain (GETTEXT_PACKAGE); - setlocale (LC_ALL, ""); - - ret = 1; - - g_type_init (); - - store_argv (argc, argv); - main_saveenv (); - - context = g_option_context_new (_("GNOME Display Manager")); - g_option_context_add_main_entries (context, entries, NULL); - - /* 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 *) "--no-daemon"; - } - } - - error = NULL; - res = g_option_context_parse (context, &argc, &argv, &error); - g_option_context_free (context); - if (! res) { - g_warning ("%s", error->message); - g_error_free (error); - goto out; - } - - if (fatal_warnings) { - GLogLevelFlags fatal_mask; - - fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); - fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; - g_log_set_always_fatal (fatal_mask); - } - - if (! no_daemon && daemon (0, 0)) { - g_error ("Could not daemonize: %s", g_strerror (errno)); - } - - connection = get_system_bus (); - if (connection == NULL) { - goto out; - } - - bus_proxy = get_bus_proxy (connection); - if (bus_proxy == NULL) { - g_warning ("Could not construct bus_proxy object; bailing out"); - goto out; - } - - if (! acquire_name_on_proxy (bus_proxy) ) { - g_warning ("Could not acquire name; bailing out"); - goto out; - } - - gdm_log_init (); - - settings = gdm_settings_new (); - if (settings == NULL) { - g_warning ("Unable to initialize settings"); - goto out; - } - - if (! gdm_settings_direct_init (settings, GDMCONFDIR "/gdm.schemas", "/")) { - g_warning ("Unable to initialize settings"); - goto out; - } - - gdm_log_set_debug (debug); - - gdm_daemon_change_user (&gdm_uid, &gdm_gid); - gdm_daemon_check_permissions (gdm_uid, gdm_gid); - - set_effective_user_group (0, 0); - check_logdir (); - - /* XDM compliant error message */ - if (getuid () != 0) { - /* make sure the pid file doesn't get wiped */ - g_warning (_("Only root wants to run GDM")); - exit (-1); - } - - /* pid file */ - delete_pid (); - write_pid (); - - g_chdir (AUTHDIR); - - manager = gdm_manager_new (); - - if (manager == NULL) { - goto out; - } - - /* FIXME: pull from settings */ - gdm_manager_set_xdmcp_enabled (manager, TRUE); - - g_signal_connect (bus_proxy, - "destroy", - G_CALLBACK (bus_proxy_destroyed_cb), - manager); - - main_loop = g_main_loop_new (NULL, FALSE); - - signal_handler = gdm_signal_handler_new (); - gdm_signal_handler_set_main_loop (signal_handler, main_loop); - gdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGILL, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGBUS, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGSEGV, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGABRT, signal_cb, NULL); - gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL); - - if (do_timed_exit) { - g_timeout_add (1000 * 30, (GSourceFunc) timed_exit_cb, main_loop); - } - - gdm_manager_start (manager); - - g_main_loop_run (main_loop); - - if (manager != NULL) { - g_object_unref (manager); - } - - if (settings != NULL) { - g_object_unref (settings); - } - - if (signal_handler != NULL) { - g_object_unref (signal_handler); - } - - g_main_loop_unref (main_loop); - - ret = 0; - - out: - - return ret; -} |