summaryrefslogtreecommitdiff
path: root/gui/gdmXnestchooser.c
diff options
context:
space:
mode:
authorBrian Cameron <bcameron@src.gnome.org>2007-01-29 11:17:09 +0000
committerBrian Cameron <bcameron@src.gnome.org>2007-01-29 11:17:09 +0000
commitd1992561fd28ec994cf34cb9ab7e716c9d394497 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /gui/gdmXnestchooser.c
parentc595a601f525fc830a24a62a5e0ed0fa20c9b3af (diff)
downloadgdm-GDM2_2_16_5_svn4555.tar.gz
Removing bad tag.GDM2_2_16_5_svn4555
Removing bad tag. svn path=/tags/GDM2_2_16_5; revision=4554
Diffstat (limited to 'gui/gdmXnestchooser.c')
-rw-r--r--gui/gdmXnestchooser.c678
1 files changed, 0 insertions, 678 deletions
diff --git a/gui/gdmXnestchooser.c b/gui/gdmXnestchooser.c
deleted file mode 100644
index 092eea9d..00000000
--- a/gui/gdmXnestchooser.c
+++ /dev/null
@@ -1,678 +0,0 @@
-/* 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/Xauth.h>
-
-#include "gdm.h"
-#include "gdmcomm.h"
-#include "gdmcommon.h"
-#include "gdmconfig.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, NULL, 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, NULL, 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 **vector;
- int i, ii;
- int argc;
- char **xnest_vec;
- char **options_vec = NULL;
- gboolean got_font_path = FALSE;
- char *font_path = NULL;
-
- if ( ! ve_string_empty (xnest_binary))
- xnest = xnest_binary;
-
- if (ve_string_empty (xnest))
- xnest = "Xnest";
-
- xnest_vec = ve_split (xnest);
- if (xnest_options != NULL)
- options_vec = ve_split (xnest_options);
- else
- options_vec = NULL;
-
- argc = ve_vector_len (xnest_vec) +
- 1 +
- ve_vector_len (options_vec) +
- 3 +
- 2;
-
- vector = g_new0 (char *, argc);
-
- ii = 0;
-
- /* lots of leaks follow */
-
- vector[ii++] = xnest_vec[0];
- vector[ii++] = display_num;
-
- for (i = 1; xnest_vec[i] != NULL; i++) {
- vector[ii++] = xnest_vec[i];
- if (strcmp (xnest_vec[i], "-fp") == 0)
- got_font_path = TRUE;
- }
-
- if (options_vec != NULL) {
- for (i = 0; options_vec[i] != NULL; i++) {
- vector[ii++] = options_vec[i];
- if (strcmp (options_vec[i], "-fp") == 0)
- got_font_path = TRUE;
- }
- }
-
- if ( ! no_query) {
- if (do_broadcast) {
- vector[ii++] = "-broadcast";
- } else if (do_direct) {
- vector[ii++] = "-query";
- vector[ii++] = indirect_host;
- } else {
- vector[ii++] = "-indirect";
- vector[ii++] = indirect_host;
- }
- }
-
- if ( ! got_font_path)
- font_path = get_font_path (NULL);
-
- if (font_path != NULL) {
- vector[ii++] = "-fp";
- vector[ii++] = font_path;
- }
-
- return vector;
-}
-
-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);
-}
-
-int
-main (int argc, char *argv[])
-{
- gboolean xdmcp_enabled;
- gboolean honor_indirect;
- int display;
- char *socket;
- 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_config_get_string (GDM_KEY_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 = ve_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 = ve_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 = ve_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 = ve_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 = ve_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;
-}