diff options
Diffstat (limited to 'gui/gdmXnestchooser.c')
-rw-r--r-- | gui/gdmXnestchooser.c | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/gui/gdmXnestchooser.c b/gui/gdmXnestchooser.c deleted file mode 100644 index cc5afecc..00000000 --- a/gui/gdmXnestchooser.c +++ /dev/null @@ -1,679 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (c) 2001 Queen of England - * - * GDMXnestChooser - run X nest with a chooser using xdmcp - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "config.h" -#include <glib/gi18n.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <errno.h> - -#include <X11/Xlib.h> -#include <X11/Xauth.h> - -#include "gdm.h" -#include "gdmcomm.h" -#include "gdmcommon.h" -#include "gdmconfig.h" - -#include "gdm-common.h" -#include "gdm-daemon-config-keys.h" - -static gchar **args_remaining; -static pid_t xnest_pid = 0; - -#ifdef ENABLE_IPV6 -static gboolean -have_ipv6 () { - gint s; - - s = socket (AF_INET6, SOCK_STREAM, 0); - - if (s != -1) { - VE_IGNORE_EINTR (close (s)); - return TRUE; - } - - return FALSE; -} -#endif - -static void -term_handler (int sig) -{ - if (xnest_pid != 0) - kill (xnest_pid, SIGTERM); - else - exit (0); -} - -static int -get_free_display (void) -{ - int sock; - int i; - struct sockaddr_in serv_addr = {0}; - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - for (i = 20; i < 3000; i++) { - struct stat s; - char buf[256]; - FILE *fp; -#ifdef ENABLE_IPV6 - if (have_ipv6()) { - struct sockaddr_in6 serv6_addr = {0}; - - sock = socket (AF_INET6, SOCK_STREAM, 0); - serv6_addr.sin6_family = AF_INET6; - serv6_addr.sin6_addr = in6addr_loopback; - serv6_addr.sin6_port = htons (6000 + i); - - if (connect (sock, (struct sockaddr *)&serv6_addr, sizeof (serv6_addr)) >= 0 || errno != ECONNREFUSED) { - VE_IGNORE_EINTR (close (sock)); - continue; - } - } - else -#endif - { - - sock = socket (AF_INET, SOCK_STREAM, 0); - - serv_addr.sin_port = htons (6000 + i); - - errno = 0; - if (connect (sock, (struct sockaddr *)&serv_addr, - sizeof (serv_addr)) >= 0 || - errno != ECONNREFUSED) { - VE_IGNORE_EINTR (close (sock)); - continue; - } - } - - VE_IGNORE_EINTR (close (sock)); - - /* if lock file exists and the process exists */ - g_snprintf (buf, sizeof (buf), "/tmp/.X%d-lock", i); - VE_IGNORE_EINTR (fp = fopen (buf, "r")); - if (fp != NULL) { - char buf2[100]; - if (fgets (buf2, sizeof (buf2), fp) != NULL) { - gulong pid; - if (sscanf (buf2, "%lu", &pid) == 1 && - kill (pid, 0) == 0) { - VE_IGNORE_EINTR (fclose (fp)); - continue; - } - - } - VE_IGNORE_EINTR (fclose (fp)); - } - - g_snprintf (buf, sizeof (buf), "/tmp/.X11-unix/X%d", i); - if (g_stat (buf, &s) == 0 && - s.st_uid != getuid ()) { - continue; - } - - g_snprintf (buf, sizeof (buf), "/tmp/.X%d-lock", i); - if (g_stat (buf, &s) == 0 && - s.st_uid != getuid ()) { - continue; - } - - return i; - } - fprintf (stderr, "ERROR! Can't find free display!\n"); - - return -1; -} - -static const char *host = "localhost"; -static char *xnest_binary = NULL; -static char *xnest_options = NULL; -static gboolean no_query = FALSE; -static gboolean background = FALSE; -static gboolean do_direct = FALSE; -static gboolean do_broadcast = FALSE; -static gboolean no_gdm_check = FALSE; - -static char display_num[BUFSIZ] = ""; -static char indirect_host[BUFSIZ] = ""; - -/* options for Xnest only mode */ -static const GOptionEntry xnest_only_options[] = { - { "xnest", 'x', 0, G_OPTION_ARG_STRING, &xnest_binary, N_("Xnest command line"), N_("STRING") }, - { "xnest-extra-options", 'o', 0, G_OPTION_ARG_STRING, &xnest_options, N_("Extra options for Xnest"), N_("OPTIONS") }, - { "background", 'b', 0, G_OPTION_ARG_NONE, &background, N_("Run in background"), NULL }, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, NULL }, - { NULL } -}; - -static const GOptionEntry options[] = { - { "xnest", 'x', 0, G_OPTION_ARG_STRING, &xnest_binary, N_("Xnest command line"), N_("STRING") }, - { "xnest-extra-options", 'o', 0, G_OPTION_ARG_STRING, &xnest_options, N_("Extra options for Xnest"), N_("OPTIONS") }, - { "no-query", 'n', 0, G_OPTION_ARG_NONE, &no_query, N_("Just run Xnest, no query (no chooser)"), NULL }, - { "direct", 'd', 0, G_OPTION_ARG_NONE, &do_direct, N_("Do direct query instead of indirect (chooser)"), NULL }, - { "broadcast", 'B', 0, G_OPTION_ARG_NONE, &do_broadcast, N_("Run broadcast instead of indirect (chooser)"), NULL }, - { "background", 'b', 0, G_OPTION_ARG_NONE, &background, N_("Run in background"), NULL }, - { "no-gdm-check", '\0', 0, G_OPTION_ARG_NONE, &no_gdm_check, N_("Don't check for running GDM"), NULL }, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, NULL }, - { NULL } -}; - -#if 0 -/* Perhaps this may be useful sometime */ -static gboolean -test_opt (const char *cmd, const char *help, const char *option) -{ - char *q = g_shell_quote (cmd); - char *full; - char buf[1024]; - FILE *fp; - - full = g_strdup_printf ("%s %s 2>&1", q, help); - g_free (q); - - fp = popen (full, "r"); - g_free (full); - - if (fp == NULL) - return FALSE; - - while (fgets (buf, sizeof (buf), fp) != NULL) { - char *p = strstr (buf, option); - char end; - if (p == NULL) - continue; - /* must be a full word */ - end = *(p + strlen (option)); - if ((end >= 'a' && end <= 'z') || - (end >= 'A' && end <= 'Z') || - (end >= '0' && end <= '9') || - end == '_') - continue; - - fclose (fp); - return TRUE; - } - fclose (fp); - return FALSE; -} -#endif - -static char * -get_font_path (const char *display) -{ - Display *disp; - char **font_path; - int n_fonts; - int i; - GString *gs; - - disp = XOpenDisplay (display); - if (disp == NULL) - return NULL; - - font_path = XGetFontPath (disp, &n_fonts); - if (font_path == NULL) { - XCloseDisplay (disp); - return NULL; - } - - gs = g_string_new (NULL); - for (i = 0; i < n_fonts; i++) { - if (i != 0) - g_string_append_c (gs, ','); - g_string_append (gs, font_path[i]); - } - - XFreeFontPath (font_path); - - XCloseDisplay (disp); - - return g_string_free (gs, FALSE); -} - -static char ** -make_us_an_exec_vector (const char *xnest) -{ - char **argv; - int argc; - GString *command; - - if ( ! ve_string_empty (xnest_binary)) - xnest = xnest_binary; - - if (ve_string_empty (xnest)) - xnest = "Xnest"; - - command = g_string_new (xnest); - g_string_append_printf (command, " %s", display_num); - - if (xnest_options != NULL) { - g_string_append_printf (command, " %s", xnest_options); - } - - if ( ! no_query) { - if (do_broadcast) { - g_string_append (command, " -broadcast"); - } else if (do_direct) { - g_string_append_printf (command, " -query %s", indirect_host); - } else { - g_string_append_printf (command, " -indirect %s", indirect_host); - } - } - - if (g_strrstr (command->str, " -fp ") == NULL) { - char *font_path; - font_path = get_font_path (NULL); - g_string_append_printf (command, " -fp %s", font_path); - g_free (font_path); - } - - argv = NULL; - - g_shell_parse_argv (command->str, &argc, &argv, NULL); - - g_string_free (command, TRUE); - - return argv; -} - -static const char * -base (const char *s) -{ - const char *p = strchr (s, '/'); - if (p == NULL) - return s; - return p+1; -} - -static const char * -xauth_path (void) -{ - static char *xauth_path = NULL; - if (xauth_path == NULL) - xauth_path = g_find_program_in_path ("xauth"); - return xauth_path; -} - -static void -whack_cookie (int display) -{ - char *command; - - if (xauth_path () == NULL) { - return; - } - - command = g_strdup_printf ("%s remove :%d", - xauth_path (), - display); - system (command); - g_free (command); -} - -static Xauth * -get_auth_entry (int disp, char *cookie) -{ - Xauth *xa; - gchar *dispnum; - char hostname [1024]; - - xa = malloc (sizeof (Xauth)); - - if (xa == NULL) - return NULL; - - hostname[1023] = '\0'; - if (gethostname (hostname, 1023) != 0) { - strcpy (hostname, "localhost"); - } - - xa->family = FamilyLocal; - xa->address = malloc (strlen (hostname) + 1); - if (xa->address == NULL) { - free (xa); - return NULL; - } - - strcpy (xa->address, hostname); - xa->address_length = strlen (hostname);; - - dispnum = g_strdup_printf ("%d", disp); - xa->number = strdup (dispnum); - xa->number_length = strlen (dispnum); - g_free (dispnum); - - xa->name = strdup ("MIT-MAGIC-COOKIE-1"); - xa->name_length = strlen ("MIT-MAGIC-COOKIE-1"); - xa->data = malloc (16); - if (xa->data == NULL) { - free (xa->number); - free (xa->name); - free (xa->address); - free (xa); - return NULL; - } - memcpy (xa->data, cookie, 16); - xa->data_length = 16; - - return xa; -} - -static void -setup_cookie (int disp) -{ - char *cookie; - FILE *af; - Xauth *xa; - const char *filename = XauFileName (); - if (filename == NULL) - return; - - if (XauLockAuth (filename, 3, 3, 0) != LOCK_SUCCESS) - return; - - cookie = gdmcomm_get_a_cookie (TRUE /* binary */); - if (cookie == NULL) { - XauUnlockAuth (filename); - return; - } - - VE_IGNORE_EINTR (af = fopen (filename, "a+")); - if (af == NULL) { - XauUnlockAuth (filename); - g_free (cookie); - return; - } - - xa = get_auth_entry (disp, cookie); - if (xa == NULL) { - g_free (cookie); - VE_IGNORE_EINTR (fclose (af)); - XauUnlockAuth (filename); - return; - } - - g_free (cookie); - - XauWriteAuth (af, xa); - - XauDisposeAuth (xa); - - VE_IGNORE_EINTR (fclose (af)); - - XauUnlockAuth (filename); -} - -static GtkWidget * -hig_dialog_new (GtkWindow *parent, - GtkDialogFlags flags, - GtkMessageType type, - GtkButtonsType buttons, - const gchar *primary_message, - const gchar *secondary_message) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (parent), - GTK_DIALOG_DESTROY_WITH_PARENT, - type, - buttons, - "%s", primary_message); - - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - "%s", secondary_message); - - gtk_window_set_title (GTK_WINDOW (dialog), ""); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); - gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14); - - return dialog; -} - -int -main (int argc, char *argv[]) -{ - gboolean xdmcp_enabled; - gboolean honor_indirect; - int display; - char *socket; - const char *pidfile; - GOptionContext *ctx; - char *xnest; - char **execvec; - struct sigaction term; - - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - if (strcmp (base (argv[0]), "gdmXnest") == 0) { - gtk_init(&argc, &argv); - ctx = g_option_context_new (_("- Nested gdm login chooser")); - g_option_context_add_main_entries (ctx, xnest_only_options, _("main options")); - g_option_context_parse (ctx, &argc, &argv, NULL); - g_option_context_free (ctx); - no_query = TRUE; - no_gdm_check = TRUE; - } else { - gtk_init(&argc, &argv); - ctx = g_option_context_new (_("- Nested gdm login")); - g_option_context_add_main_entries (ctx, options, _("main options")); - g_option_context_parse (ctx, &argc, &argv, NULL); - g_option_context_free (ctx); - } - - if (args_remaining != NULL && args_remaining[0] != NULL) - host = args_remaining[0]; - g_strfreev (args_remaining); - - /* Read config data in bulk */ - gdmcomm_comm_bulk_start (); - - xdmcp_enabled = gdm_config_get_bool (GDM_KEY_XDMCP); - honor_indirect = gdm_config_get_bool (GDM_KEY_INDIRECT); - pidfile = GDM_PID_FILE; - xnest = gdm_config_get_string (GDM_KEY_XNEST); - - /* At this point we are done using the socket, so close it */ - gdmcomm_comm_bulk_stop (); - - /* complex and wonderous way to get the exec vector */ - execvec = make_us_an_exec_vector (xnest); - - if (execvec == NULL) { - GtkWidget *d; - d = hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Xnest doesn't exist."), - _("Please ask your system " - "administrator " - "to install it.")); - gtk_widget_show_all (d); - gtk_dialog_run (GTK_DIALOG (d)); - gtk_widget_destroy (d); - return 0; - } - - if ( ! no_query && - ! do_broadcast && - ! no_gdm_check && - strcmp (host, "localhost") == 0) { - FILE *fp = NULL; - long pid; - - if (( ! xdmcp_enabled || - ! honor_indirect) && - ! do_direct) { - GtkWidget *d; - d = hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Indirect XDMCP is not enabled"), - _("Please ask your " - "system administrator to enable " - "this feature.")); - gtk_widget_show_all (d); - gtk_dialog_run (GTK_DIALOG (d)); - gtk_widget_destroy (d); - return 0; - } - - if ( ! xdmcp_enabled && - do_direct) { - GtkWidget *d; - d = hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("XDMCP is not enabled"), - _("Please ask your " - "system administrator to enable " - "this feature.")); - gtk_widget_show_all (d); - gtk_dialog_run (GTK_DIALOG (d)); - gtk_widget_destroy (d); - return 0; - } - - pid = 0; - if (pidfile != NULL) { - VE_IGNORE_EINTR (fp = fopen (pidfile, "r")); - } - if (fp != NULL) { - int r; - VE_IGNORE_EINTR (r = fscanf (fp, "%ld", &pid)); - VE_IGNORE_EINTR (fclose (fp)); - if (r != 1) - pid = 0; - } - - errno = 0; - if (pid <= 1 || - (kill (pid, 0) < 0 && - errno != EPERM)) { - GtkWidget *d; - d = hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("GDM is not running"), - _("Please ask your " - "system administrator to start it.")); - gtk_widget_show_all (d); - gtk_dialog_run (GTK_DIALOG (d)); - gtk_widget_destroy (d); - return 0; - } - } - - display = get_free_display (); - if (display < 0) { - GtkWidget *d; - d = hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Could not find a free " - "display number"), - ""); - gtk_widget_show_all (d); - gtk_dialog_run (GTK_DIALOG (d)); - gtk_widget_destroy (d); - return 0; - } - - printf ("DISPLAY=:%d\n", display); - fflush (stdout); - - g_snprintf (display_num, sizeof (display_num), ":%d", display); - g_snprintf (indirect_host, sizeof (indirect_host), "%s", host); - - if (no_query) { - whack_cookie (display); - setup_cookie (display); - } - - if (background) { - if (fork () > 0) { - _exit (0); - } - VE_IGNORE_EINTR (close (0)); - VE_IGNORE_EINTR (close (1)); - VE_IGNORE_EINTR (close (2)); - VE_IGNORE_EINTR (open ("/dev/null", O_RDWR)); - VE_IGNORE_EINTR (open ("/dev/null", O_RDONLY)); - VE_IGNORE_EINTR (open ("/dev/null", O_RDONLY)); - } - - term.sa_handler = term_handler; - term.sa_flags = SA_RESTART; - sigemptyset (&term.sa_mask); - - sigaction (SIGTERM, &term, NULL); - sigaction (SIGINT, &term, NULL); - sigaction (SIGHUP, &term, NULL); - - xnest_pid = fork (); - if (xnest_pid == 0) { - execvp (execvec[0], execvec); - g_warning ("Can't exec, trying Xnest"); - execvec[0] = "Xnest"; - execvp (execvec[0], execvec); - g_warning ("Can't exec that either, giving up"); - /* FIXME: this should be handled in the GUI */ - _exit (1); - } else if (xnest_pid < 0) { - /* eeeek */ - g_warning ("Can't fork"); - _exit (1); - } - - ve_waitpid_no_signal (xnest_pid, NULL, 0); - xnest_pid = 0; - - socket = g_strdup_printf ("/tmp/.X11-unix/X%d", display); - g_unlink (socket); - g_free (socket); - - if (no_query) - whack_cookie (display); - - return 0; -} |