diff options
author | George Lebl <jirka@5z.com> | 2002-08-22 19:15:03 +0000 |
---|---|---|
committer | George Lebl <jirka@src.gnome.org> | 2002-08-22 19:15:03 +0000 |
commit | d815ebedf37fc0be3bbeea3d7274d963540f6104 (patch) | |
tree | 9ded54c64a200f4e86b424f7ad4762bb8f9e327d | |
parent | 2cd3e7f97694aa1f282ae31b5d4049d89a041947 (diff) | |
download | gdm-d815ebedf37fc0be3bbeea3d7274d963540f6104.tar.gz |
Make the vt member exist for non-linux systems as well just for kicks. Set
Thu Aug 22 12:23:49 2002 George Lebl <jirka@5z.com>
* daemon/gdm.[ch], daemon/server.[ch], daemon/Makefile.am,
daemon/getvt.[ch], daemon/xdmcp.c, config/gdm.conf.in:
Make the vt member exist for non-linux systems as well just
for kicks. Set up a vt allocation thingie (kind of a hack
to get a VT higher then a certain number, but oh well). Currently
only for linux. And add vt<number> arguments unless there
was such an argument added already. This should fix all
the problems with people running gdm as a service since
all the VT stuff is so horribly broken. Should fix #62997.
Adds two keys FirstVT and VTAllocation to control this
behaviour.
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | config/gdm.conf.in | 19 | ||||
-rw-r--r-- | daemon/Makefile.am | 4 | ||||
-rw-r--r-- | daemon/gdm.c | 18 | ||||
-rw-r--r-- | daemon/gdm.h | 6 | ||||
-rw-r--r-- | daemon/getvt.c | 115 | ||||
-rw-r--r-- | daemon/getvt.h | 34 | ||||
-rw-r--r-- | daemon/server.c | 75 | ||||
-rw-r--r-- | daemon/server.h | 3 | ||||
-rw-r--r-- | daemon/xdmcp.c | 2 |
10 files changed, 243 insertions, 47 deletions
@@ -1,3 +1,17 @@ +Thu Aug 22 12:23:49 2002 George Lebl <jirka@5z.com> + + * daemon/gdm.[ch], daemon/server.[ch], daemon/Makefile.am, + daemon/getvt.[ch], daemon/xdmcp.c, config/gdm.conf.in: + Make the vt member exist for non-linux systems as well just + for kicks. Set up a vt allocation thingie (kind of a hack + to get a VT higher then a certain number, but oh well). Currently + only for linux. And add vt<number> arguments unless there + was such an argument added already. This should fix all + the problems with people running gdm as a service since + all the VT stuff is so horribly broken. Should fix #62997. + Adds two keys FirstVT and VTAllocation to control this + behaviour. + Tue Aug 20 10:28:45 2002 George Lebl <jirka@5z.com> * Release 2.4.0.8 diff --git a/config/gdm.conf.in b/config/gdm.conf.in index 42d76843..356a87de 100644 --- a/config/gdm.conf.in +++ b/config/gdm.conf.in @@ -85,6 +85,11 @@ StandardXServer=/usr/X11R6/bin/X FlexibleXServers=5 # the X nest command Xnest=/usr/X11R6/bin/Xnest -name Xnest +# Automatic VT allocation. Right now only works on Linux. This way +# we force X to use specific vts. turn VTAllocation to false if this +# is causing problems. +FirstVT=7 +VTAllocation=true [security] # If any distributions ship with this one off, they should be shot @@ -189,13 +194,13 @@ Enable=false # the 0 server is used. 0=Standard #1=Standard -#Note: If you want to make sure X runs on a specific virtual console on linux, -# you can use the following (for console 7). However this can cause -# problems for some users. Be careful about this, getting this wrong -# can lead to an unusable console. Best solution is to make sure gdm -# starts as the last thing, and that will make it not neccessary to -# do hacks like this since X will itself find the first free console -#0=Standard vt7 +# Note the VTAllocation and FirstVT keys on linux. Don't add any vt<number> +# arguments if VTAllocation is on, and set FirstVT to be the first vt +# available that your gettys don't grab (gettys are usually dumb and grab +# even a vt that has already been taken). Using 7 will work pretty much for +# all linux distributions. VTAllocation is not currently implemented on +# anything but linux since I don't own any non-linux systems. Feel free to +# send patches. X servers will just not get any extra arguments then. # #Note: If you want to run an X terminal you could add an X server such as this #0=Terminal -query serverhostname diff --git a/daemon/Makefile.am b/daemon/Makefile.am index ddf1f482..f6aeff07 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -51,7 +51,9 @@ gdm_binary_SOURCES = \ errorgui.c \ errorgui.h \ gdm-net.c \ - gdm-net.h + gdm-net.h \ + getvt.c \ + getvt.h EXTRA_gdm_binary_SOURCES = verify-pam.c verify-crypt.c verify-shadow.c diff --git a/daemon/gdm.c b/daemon/gdm.c index 006abe87..689243df 100644 --- a/daemon/gdm.c +++ b/daemon/gdm.c @@ -160,6 +160,9 @@ gint GdmTimedLoginDelay = 0; gchar *GdmStandardXServer = NULL; gint GdmFlexibleXServers = 5; gchar *GdmXnest = NULL; +int GdmFirstVT = 7; +gboolean GdmVTAllocation = TRUE; + /* set in the main function */ char **stored_argv = NULL; @@ -310,6 +313,9 @@ gdm_config_parse (void) if (ve_string_empty (GdmXnest)) GdmXnest = NULL; + GdmFirstVT = gnome_config_get_int (GDM_KEY_FIRSTVT); + GdmVTAllocation = gnome_config_get_bool (GDM_KEY_VTALLOCATION); + GdmDebug = gnome_config_get_bool (GDM_KEY_DEBUG); gnome_config_pop_prefix(); @@ -1620,7 +1626,8 @@ write_x_servers (GdmDisplay *d) char **argv; char *command; argv = gdm_server_resolve_command_line - (d, FALSE /* resolve_handled */); + (d, FALSE /* resolve_handled */, + NULL /* vtarg */); command = g_strjoinv (" ", argv); g_strfreev (argv); fprintf (fp, "%s local %s\n", d->name, command); @@ -1817,9 +1824,7 @@ gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data) d = gdm_display_lookup (slave_pid); if (d != NULL) { -#ifdef __linux__ d->vt = vt_num; -#endif gdm_debug ("Got VT_NUM == %d", vt_num); /* send ack */ send_slave_ack (d); @@ -2716,12 +2721,7 @@ gdm_handle_user_message (GdmConnection *conn, const char *msg, gpointer data) ve_sure_string (disp->xnest_disp)); } else { gdm_connection_printf (conn, "%d", -#ifdef __linux__ - disp->vt -#else - -1 -#endif - ); + disp->vt); } } gdm_connection_write (conn, "\n"); diff --git a/daemon/gdm.h b/daemon/gdm.h index c3acde23..bda48c66 100644 --- a/daemon/gdm.h +++ b/daemon/gdm.h @@ -161,6 +161,10 @@ enum { #define GDM_KEY_STANDARD_XSERVER "daemon/StandardXServer=/usr/X11R6/bin/X" #define GDM_KEY_FLEXIBLE_XSERVERS "daemon/FlexibleXServers=5" #define GDM_KEY_XNEST "daemon/Xnest=/usr/X11R6/bin/Xnest -name Xnest" +/* Keys for automatic VT allocation rather then letting it up to the + * X server */ +#define GDM_KEY_FIRSTVT "daemon/FirstVT=7" +#define GDM_KEY_VTALLOCATION "daemon/VTAllocation=true" /* Per server definitions */ #define GDM_KEY_SERVER_NAME "name=Standard server" @@ -292,9 +296,7 @@ struct _GdmDisplay { gboolean handled; -#ifdef __linux__ int vt; -#endif gboolean busy_display; diff --git a/daemon/getvt.c b/daemon/getvt.c new file mode 100644 index 00000000..04f15d99 --- /dev/null +++ b/daemon/getvt.c @@ -0,0 +1,115 @@ +#include "config.h" + +#include <libgnome/libgnome.h> +#include "gdm.h" +#include "misc.h" +#include "getvt.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +extern int GdmFirstVT; +extern gboolean GdmVTAllocation; + +#ifdef __linux__ + +#include <sys/vt.h> + +static int +open_vt (int vtno) +{ + char *vtname = g_strdup_printf ("/dev/tty%d", vtno); + int fd = open (vtname, O_RDWR); + g_free (vtname); + return fd; +} + +static int +get_free_vt (int *vtfd) +{ + int fd, fdv; + int vtno; + GList *to_close_vts = NULL, *li; + + *vtfd = -1; + + fd = open ("/dev/console", O_WRONLY, 0); + if (fd < 0) + return -1; + + if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) { + close (fd); + return -1; + } + + fdv = open_vt (vtno); + if (fdv < 0) { + close (fd); + return -1; + } + + while (vtno < GdmFirstVT) { + int oldvt = vtno; + to_close_vts = g_list_prepend (to_close_vts, + GINT_TO_POINTER (fdv)); + + if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) { + vtno = -1; + goto cleanup; + } + + if (oldvt == vtno) { + vtno = -1; + goto cleanup; + } + + fdv = open_vt (vtno); + if (fdv < 0) { + vtno = -1; + goto cleanup; + } + } + + *vtfd = fdv; + +cleanup: + for (li = to_close_vts; li != NULL; li = li->next) { + close (GPOINTER_TO_INT (li->data)); + } + return vtno; +} + +char * +gdm_get_empty_vt_argument (int *fd, int *vt) +{ + if ( ! GdmVTAllocation) { + *fd = -1; + return NULL; + } + + *vt = get_free_vt (fd); + if (*vt < 0) + return NULL; + else + return g_strdup_printf ("vt%d", *vt); +} + +#else /* here this is just a stub, we don't know how to do this outside + of linux really */ + +char * +gdm_get_empty_vt_argument (int *fd, int *vt) +{ + *fd = -1; + *vt = -1; + return NULL; +} + +#endif diff --git a/daemon/getvt.h b/daemon/getvt.h new file mode 100644 index 00000000..a444834c --- /dev/null +++ b/daemon/getvt.h @@ -0,0 +1,34 @@ +/* GDM - The Gnome Display Manager + * Copyright (C) 2002 Queen of England + * + * 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 + */ + +#ifndef GETVT_H +#define GETVT_H + +/* gets an argument we should pass to the X server, on + * linux for example we get the first empty vt (higher + * then or equal to GdmFirstVT) and then return vt<number> + * (e.g. "vt7") as a newly allocated string. + * Can return NULL if we can't figure out what to do + * or if GdmVTAllocation is false. */ +/* fd is opened so that we are saying we have opened this + * vt. This should be closed after the server has started. + * This is to avoid race with other stuff openning this vt. + * It can be set to -1 if nothing could be opened. */ +char * gdm_get_empty_vt_argument (int *fd, int *vt); + +#endif /* GETVT_H */ diff --git a/daemon/server.c b/daemon/server.c index a325add5..b608392a 100644 --- a/daemon/server.c +++ b/daemon/server.c @@ -34,6 +34,7 @@ #include <syslog.h> #include <errno.h> #include <time.h> +#include <ctype.h> #include <X11/Xlib.h> #include <vicious.h> @@ -45,12 +46,13 @@ #include "display.h" #include "auth.h" #include "slave.h" +#include "getvt.h" #define SERVER_WAIT_ALARM 10 /* Local prototypes */ -static void gdm_server_spawn (GdmDisplay *d); +static void gdm_server_spawn (GdmDisplay *d, const char *vtarg); static void gdm_server_usr1_handler (gint); static void gdm_server_alarm_handler (gint); static void gdm_server_child_handler (gint); @@ -268,7 +270,6 @@ display_busy (GdmDisplay *disp) return FALSE; } -#ifdef __linux__ static int display_vt (GdmDisplay *disp) { @@ -295,7 +296,6 @@ display_vt (GdmDisplay *disp) fclose (fp); return -1; } -#endif /** * gdm_server_start: @@ -312,6 +312,8 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi, struct sigaction old_usr1, old_chld, old_alrm; sigset_t mask, oldmask; int flexi_disp = 20; + char *vtarg = NULL; + int vtfd = -1, vt = -1; if (disp == NULL) return FALSE; @@ -321,14 +323,12 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi, /* if an X server exists, wipe it */ gdm_server_stop (d); - /* On linux first clear the VT number */ -#ifdef __linux__ + /* First clear the VT number */ if (d->type == TYPE_LOCAL || d->type == TYPE_FLEXI) { d->vt = -1; gdm_slave_send_num (GDM_SOP_VT_NUM, -1); } -#endif if (SERVER_IS_FLEXI (d) || treat_as_flexi) { @@ -420,8 +420,13 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi, d->servstat = SERVER_DEAD; + if (d->type == TYPE_LOCAL || + d->type == TYPE_FLEXI) { + vtarg = gdm_get_empty_vt_argument (&vtfd, &vt); + } + /* fork X server process */ - gdm_server_spawn (d); + gdm_server_spawn (d, vtarg); /* we can now use d->handled since that's set up above */ @@ -482,6 +487,11 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi, alarm (0); } + /* If we were holding a vt open for the server, close it now as it has + * already taken the bait. */ + if (vtfd > 0) + close (vtfd); + switch (d->servstat) { case SERVER_TIMEOUT: @@ -507,14 +517,16 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi, if (SERVER_IS_FLEXI (d)) gdm_slave_send_num (GDM_SOP_FLEXI_OK, 0 /* bogus */); -#ifdef __linux__ if (d->type == TYPE_LOCAL || d->type == TYPE_FLEXI) { - d->vt = display_vt (d); + if (vt >= 0) + d->vt = vt; + + if (d->vt < 0) + d->vt = display_vt (d); if (d->vt >= 0) gdm_slave_send_num (GDM_SOP_VT_NUM, d->vt); } -#endif return TRUE; default: @@ -605,7 +617,6 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi, void gdm_server_checklog (GdmDisplay *disp) { -#ifdef __linux__ if (d->vt < 0 && (d->type == TYPE_LOCAL || d->type == TYPE_FLEXI)) { @@ -613,7 +624,6 @@ gdm_server_checklog (GdmDisplay *disp) if (d->vt >= 0) gdm_slave_send_num (GDM_SOP_VT_NUM, d->vt); } -#endif } static void @@ -640,14 +650,17 @@ rotate_logs (const char *dname) g_free (fname); } + char ** gdm_server_resolve_command_line (GdmDisplay *disp, - gboolean resolve_handled) + gboolean resolve_handled, + const char *vtarg) { char *bin; char **argv; int len; int i; + gboolean gotvtarg = FALSE; bin = ve_first_word (disp->command); if (bin == NULL) { @@ -682,23 +695,36 @@ gdm_server_resolve_command_line (GdmDisplay *disp, argv = ve_split (disp->command); } - for (len = 0; argv != NULL && argv[len] != NULL; len++) - ; + for (len = 0; argv != NULL && argv[len] != NULL; len++) { + char *arg = argv[len]; + /* HACK! Not to add vt argument to servers that already force + * allocation. Mostly for backwards compat only */ + if (strncmp (arg, "vt", 2) == 0 && + isdigit (arg[2]) && + (arg[3] == '\0' || + (isdigit (arg[3]) && arg[4] == '\0'))) + gotvtarg = TRUE; + } - argv = g_renew (char *, argv, len + 4); + argv = g_renew (char *, argv, len + 5); for (i = len - 1; i >= 1; i--) { argv[i+1] = argv[i]; } /* server number is the FIRST argument, before any others */ argv[1] = g_strdup (disp->name); + len++; if (disp->authfile != NULL) { - argv[len+1] = g_strdup ("-auth"); - argv[len+2] = g_strdup (disp->authfile); - argv[len+3] = NULL; - } else { - argv[len+1] = NULL; + argv[len++] = g_strdup ("-auth"); + argv[len++] = g_strdup (disp->authfile); } + if (vtarg != NULL && + ! gotvtarg) { + argv[len++] = g_strdup (vtarg); + } + + argv[len++] = NULL; + g_free (bin); return argv; @@ -715,7 +741,7 @@ gdm_server_resolve_command_line (GdmDisplay *disp, */ static void -gdm_server_spawn (GdmDisplay *d) +gdm_server_spawn (GdmDisplay *d, const char *vtarg) { struct sigaction ign_signal, dfl_signal; sigset_t mask; @@ -743,7 +769,8 @@ gdm_server_spawn (GdmDisplay *d) /* Figure out the server command */ argv = gdm_server_resolve_command_line (d, - TRUE /* resolve handled */); + TRUE /* resolve handled */, + vtarg); command = g_strjoinv (" ", argv); @@ -1078,9 +1105,7 @@ gdm_server_alloc (gint id, const gchar *command) d->handled = TRUE; -#ifdef __linux__ d->vt = -1; -#endif d->x_servers_order = -1; diff --git a/daemon/server.h b/daemon/server.h index a3b3668b..b9c722ca 100644 --- a/daemon/server.h +++ b/daemon/server.h @@ -36,7 +36,8 @@ void gdm_server_whack_clients (GdmDisplay *disp); void gdm_server_checklog (GdmDisplay *disp); char ** gdm_server_resolve_command_line (GdmDisplay *disp, - gboolean resolve_handled); + gboolean resolve_handled, + const char *vtarg); diff --git a/daemon/xdmcp.c b/daemon/xdmcp.c index 9a408bea..67687644 100644 --- a/daemon/xdmcp.c +++ b/daemon/xdmcp.c @@ -1535,9 +1535,7 @@ gdm_xdmcp_display_alloc (struct in_addr *addr, const char *hostname, gint displa d->handled = TRUE; -#ifdef __linux__ d->vt = -1; -#endif d->x_servers_order = -1; |