summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Lebl <jirka@5z.com>2002-08-22 19:15:03 +0000
committerGeorge Lebl <jirka@src.gnome.org>2002-08-22 19:15:03 +0000
commitd815ebedf37fc0be3bbeea3d7274d963540f6104 (patch)
tree9ded54c64a200f4e86b424f7ad4762bb8f9e327d
parent2cd3e7f97694aa1f282ae31b5d4049d89a041947 (diff)
downloadgdm-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--ChangeLog14
-rw-r--r--config/gdm.conf.in19
-rw-r--r--daemon/Makefile.am4
-rw-r--r--daemon/gdm.c18
-rw-r--r--daemon/gdm.h6
-rw-r--r--daemon/getvt.c115
-rw-r--r--daemon/getvt.h34
-rw-r--r--daemon/server.c75
-rw-r--r--daemon/server.h3
-rw-r--r--daemon/xdmcp.c2
10 files changed, 243 insertions, 47 deletions
diff --git a/ChangeLog b/ChangeLog
index ce0a53e2..c9a76617 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;