summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog44
-rw-r--r--Makefile.am2
-rw-r--r--TODO6
-rwxr-xr-xconfig/XKeepsCrashing75
-rw-r--r--configure.in17
-rw-r--r--daemon/gdm.c72
-rw-r--r--daemon/gdm.h2
-rw-r--r--daemon/misc.c192
-rw-r--r--daemon/misc.h4
-rw-r--r--daemon/server.c88
-rw-r--r--daemon/server.h1
-rw-r--r--daemon/slave.c40
-rw-r--r--daemon/verify-crypt.c3
-rw-r--r--daemon/verify-pam.c3
-rw-r--r--daemon/verify-shadow.c3
-rw-r--r--daemon/xdmcp.c2
-rw-r--r--gdm.spec.in1
-rw-r--r--gui/gdmflexiserver.desktop.in1
-rw-r--r--utils/.cvsignore6
-rw-r--r--utils/Makefile.am41
-rw-r--r--utils/gdmaskpass.c58
-rw-r--r--utils/gdmopen.c201
22 files changed, 736 insertions, 126 deletions
diff --git a/ChangeLog b/ChangeLog
index 01f6a3d3..c560ad09 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,47 @@
+Wed Aug 22 23:01:59 2001 George Lebl <jirka@5z.com>
+
+ * configure.in, Makefile.am, utils/gdmopen.c, utils/gdmaskpass.c:
+ Add two new small sbin utils. gdmopen is like open (based on it)
+ but better suited for gdm. Exitcode is returned so no temp files
+ are needed. Process is cleaned up on a signal, the new vt is
+ deallocated after use. And unlike openvt this thing actually waits
+ for the child. Gdmaskpass just asks for the root password, for
+ use in the XKeepsCrashing script. Both of these things will only
+ run as root as I'm too paranoid and it doesn't make sense for
+ them to run otherwise for gdm anyway.
+
+ * configure.in: Fix sbin expansion.
+
+ * daemon/gdm.c, daemon/misc.[ch], daemon/slave.c, daemon/server.c:
+ Use gdmopen to run dialog and add helper functions for doing this.
+
+ * daemon/gdm.h, daemon/slave.c, daemon/server.[ch]: When a server is
+ busy, ask the user if we want to run it on a new display number
+ or retry.
+
+ * daemon/gdm.c, daemon/misc.c, daemon/slave.c: Make sure to whack
+ any extra helper processes we launch when we are killed so that
+ we don't leave things like 'dialog' processes around
+
+ * daemon/gdm.c, config/XKeepsCrashing: Use gdmaskpass, ask if
+ the user wants to view X logs if X is crashing. And use gdmopen
+ in the script and correctly abort with exit 32. Also make it
+ not use the ugly tempfile stuff (Though a tempfile is still given
+ to the script for now)
+
+ * gdm.spec.in: raise epoch to 1, people abuse this field, and if they
+ do abuse it again and raise it beyond 1, I'll just max it out since
+ it makes package upgrading not work.
+
+ * daemon/slave.c, daemon/verify-(pam|crypt|shadow).c: add
+ /sbin/nologin as a thing to test for for disabled logins in
+ addition to /bin/false and /bin/true (it worked, but this adds a
+ nicer message)
+
+ * daemon/xdmcp.c: fix a warning.
+
+ * gui/gdmflexiserver.desktop.in: kill TryExec here
+
Tue Aug 21 04:42:05 2001 George Lebl <jirka@5z.com>
* gui/gdmconfig.[ch]: Finish the editting of the server definitions.
diff --git a/Makefile.am b/Makefile.am
index f8d3dc0c..9ca0b6b2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
SUBDIRS = config macros pixmaps intl vicious-extensions \
- daemon gui docs omf-install po
+ daemon gui utils docs omf-install po
EXTRA_DIST = \
ChangeLog \
diff --git a/TODO b/TODO
index 9b75a84d..f6e14fde 100644
--- a/TODO
+++ b/TODO
@@ -17,15 +17,11 @@ xsri like logo functionality
the photosetup proggie should be put into some sort of crapplet and there
should be other settings in the crapplet as well.
-Added configs, do docs and gdmconfig stuff:
+Added configs, do docs:
daemon/StandardXServer
daemon/FlexibleXServers
daemon/Xnest
-On busy server start up local server on a free display optionaly
-
-investigate doc building stuff
-
handle all the XFree86 Xserver error thingies, such as
No "Display" subsection for
etc...
diff --git a/config/XKeepsCrashing b/config/XKeepsCrashing
index 98a128af..44f615d6 100755
--- a/config/XKeepsCrashing
+++ b/config/XKeepsCrashing
@@ -12,68 +12,89 @@
# The second argument is a temporary file we can use
#
# $3 = 'Your X server is b0rk I will disable this server'
-# $4 = 'Your X server is b0rk would you like to try to reconfigure it?"
+# $4 = 'Would you like to try to reconfigure your server?"
# $5 = 'Please type in the root password'
# $6 = 'I will now restart the X server again'
# $7 = 'I will disable this X server'
+# $8 = 'Your X server is b0rk, do ya wanna view X logs?'
+
+# there are some env vars defined:
+# XLOG = the log file for the X server
+# BINDIR = location of gdm binaries
+# SBINDIR = location of gdm system binaries
+
+# return values are
+# 0 = try again, runs this server again
+# 1 = abort this display, removes this server from the list
+# 32 = something went very wrong, things will just get logged.
+# this means this script didn't work so do alternative things
+# to tell the user if possible
+
+# we require "gdmopen", to open a console, because we really don't
+# have one. Perhaps someone should try to figure out some shell
+# black magic to get this to work on other then linux systems
+if test ! -x $SBINDIR/gdmopen ; then
+ exit 32
+fi
# when we run ourselves from the open we will pass a -noopen argument
if test x$1 = x-noopen ; then
- shift
+ shift
else
- TEMPFILE="$2"
- # we require "open", to open a console, because we really don't
- # have one. Perhaps someone should try to figure out some shell
- # black magic to get this to work on other then linux systems
- if test -x /usr/bin/open ; then
- /usr/bin/open -s -w -- $0 -noopen "$@"
- if grep TRYAGAIN "$TEMPFILE" >/dev/null ; then
- exit 0
- else
- exit 1
- fi
- else
- exit 1
- fi
+ $SBINDIR/gdmopen $0 -noopen "$@"
+ exit $?
fi
SETUP=`which $1`
-TEMPFILE="$2"
DIALOG=`which dialog`
if test x$DIALOG = x ; then
- DIALOG=`which gdialog`
+ DIALOG=`which gdialog`
+fi
+if test -x $SBINDIR/gdmaskpass ; then
+ ASKPASS=$SBINDIR/gdmaskpass
+else
+ ASKPASS=
fi
clear
# Note, dialog required, though this script could be fixed to not require it
# I suppose
-if test x = x$SETUP -o x = x$DIALOG -o x = x$TEMPFILE ; then
+if test x = x$SETUP -o x = x$DIALOG ; then
+ echo =======================================================================
+ echo
+ cat $XLOG
+ echo
echo =======================================================================
echo
echo "$3"
echo
echo =======================================================================
read
- if test x != x$TEMPFILE ; then
- echo ABORT > $TEMPFILE
- fi
exit 1
fi
+if $DIALOG --yesno "$8" 10 50 ; then
+ $DIALOG --textbox $XLOG 22 76
+fi
+
if $DIALOG --yesno "$4" 10 50 ; then
clear
echo
echo "$5"
- # dirty trick to fool su into asking the root password even if we're
- # root
- su nobody -c "su -c $SETUP"
+ if test x$ASKPASS = x ; then
+ # dirty trick to fool su into asking the root password even if we're
+ # root
+ su nobody -c "su -c $SETUP"
+ else
+ if $ASKPASS ; then
+ $SETUP
+ fi
+ fi
clear
$DIALOG --msgbox "$6" 8 50
- echo TRYAGAIN > $TEMPFILE
exit 0
else
$DIALOG --msgbox "$7" 8 50
- echo ABORT > $TEMPFILE
exit 1
fi
diff --git a/configure.in b/configure.in
index 8c7cff98..7c5f8c86 100644
--- a/configure.in
+++ b/configure.in
@@ -193,6 +193,13 @@ fi
AC_MSG_CHECKING("for corrupt government")
AC_MSG_RESULT(yes)
+dnl ## gdmopen building
+dnl There are perhaps others where this works
+GDMOPEN=
+AC_CHECK_HEADERS(linux/vt.h, [
+ GDMOPEN=gdmopen])
+AC_SUBST(GDMOPEN)
+
dnl ## Autentication scheme
have_pam=no
VRFY="verify-crypt"
@@ -205,6 +212,13 @@ if test x$enable_authentication_scheme != xcrypt -a \
AC_DEFINE(HAVE_PAM)])
fi
+GDMASKPASS=
+if test x$have_pam = xyes ; then
+ AC_CHECK_HEADERS(security/pam_misc.h, [
+ GDMASKPASS=gdmaskpass])
+fi
+AC_SUBST(GDMASKPASS)
+
if test x$enable_authentication_scheme = xpam -a x$have_pam = xno ; then
AC_MSG_ERROR(PAM support requested but not available)
fi
@@ -327,7 +341,7 @@ EXPANDED_BINDIR=`eval echo $BINDIR_TMP`
AC_SUBST(EXPANDED_BINDIR)
AC_DEFINE_UNQUOTED(EXPANDED_BINDIR,"$EXPANDED_BINDIR")
-SBINDIR_TMP="$bindir"
+SBINDIR_TMP="$sbindir"
EXPANDED_SBINDIR=`eval echo $SBINDIR_TMP`
AC_SUBST(EXPANDED_SBINDIR)
AC_DEFINE_UNQUOTED(EXPANDED_SBINDIR,"$EXPANDED_SBINDIR")
@@ -382,6 +396,7 @@ AC_OUTPUT([
Makefile
daemon/Makefile
gui/Makefile
+utils/Makefile
pixmaps/Makefile
macros/Makefile
config/Makefile
diff --git a/daemon/gdm.c b/daemon/gdm.c
index 97c1338e..ae8fb903 100644
--- a/daemon/gdm.c
+++ b/daemon/gdm.c
@@ -70,6 +70,8 @@ gint flexi_servers = 0; /* Number of flexi servers */
sigset_t sysmask; /* Inherited system signal mask */
uid_t GdmUserId; /* Userid under which gdm should run */
gid_t GdmGroupId; /* Groupid under which gdm should run */
+pid_t extra_process = -1; /* An extra process. Used for quickie
+ processes, so that they also get whacked */
static GdmConnection *fifoconn = NULL; /* Fifo connection */
static GdmConnection *unixconn = NULL; /* UNIX Socket connection */
@@ -602,6 +604,13 @@ final_cleanup (void)
sigaddset (&mask, SIGCHLD);
sigprocmask (SIG_BLOCK, &mask, NULL);
+ if (extra_process > 1) {
+ /* we sigterm extra processes, and we
+ * don't wait */
+ kill (extra_process, SIGTERM);
+ extra_process = -1;
+ }
+
list = g_slist_copy (displays);
g_slist_foreach (list, (GFunc) gdm_display_unmanage, NULL);
g_slist_free (list);
@@ -658,19 +667,25 @@ deal_with_x_crashes (GdmDisplay *d)
if (configurators[i] != NULL) {
strcpy (tempname, "/tmp/gdm-X-failed-XXXXXX");
tempfd = mkstemp (tempname);
- close (tempfd);
+ if (tempfd >= 0) {
+ close (tempfd);
- gdm_info (_("deal_with_x_crashes: Running the "
- "XKeepsCrashing script"));
+ gdm_info (_("deal_with_x_crashes: Running the "
+ "XKeepsCrashing script"));
- pid = fork ();
+ extra_process = pid = fork ();
+ } else {
+ /* no forking, we're screwing this */
+ pid = -1;
+ }
} else {
tempfd = -1;
/* no forking, we're screwing this */
pid = -1;
}
if (pid == 0) {
- char *argv[9];
+ char *argv[10];
+ char *xlog = g_strconcat (GdmLogDir, "/", d->name, ".log", NULL);
argv[0] = GdmXKeepsCrashing;
argv[1] = configurators[i];
@@ -680,9 +695,7 @@ deal_with_x_crashes (GdmDisplay *d)
"up correctly. You will need to log in on a "
"console and rerun the X configuration "
"program. Then restart GDM.");
- argv[4] = _("I cannot start the X server (your graphical "
- "interface). It is likely that it is not set "
- "up correctly. Would you like me to try to "
+ argv[4] = _("Would you like me to try to "
"run the X configuration program? Note that "
"you will need the root password for this.");
argv[5] = _("Please type in the root (privilaged user) "
@@ -691,7 +704,15 @@ deal_with_x_crashes (GdmDisplay *d)
"again.");
argv[7] = _("I will disable this X server for now. "
"Restart GDM when it is configured correctly.");
- argv[8] = NULL;
+ argv[8] = _("I cannot start the X server (your graphical "
+ "interface). It is likely that it is not set "
+ "up correctly. Would you like to view the "
+ "X server output to diagnose the problem?");
+ argv[9] = NULL;
+
+ ve_setenv ("XLOG", xlog, TRUE);
+ ve_setenv ("BINDIR", EXPANDED_BINDIR, TRUE);
+ ve_setenv ("SBINDIR", EXPANDED_SBINDIR, TRUE);
execv (argv[0], argv);
@@ -700,13 +721,16 @@ deal_with_x_crashes (GdmDisplay *d)
} else if (pid > 0) {
int status;
waitpid (pid, &status, 0);
+
+ extra_process = -1;
+
if (WIFEXITED (status) &&
WEXITSTATUS (status) == 0) {
/* Yay, the user wants to try again, so
* here we go */
return TRUE;
} else if (WIFEXITED (status) &&
- WEXITSTATUS (status) == 32) {
+ WEXITSTATUS (status) == 32) {
/* We couldn't run the script, just drop through */
;
} else {
@@ -726,9 +750,7 @@ deal_with_x_crashes (GdmDisplay *d)
/* if we have "open" we can talk to the user, not as user
* friendly as the above script, but getting there */
if ( ! just_abort &&
- access ("/usr/bin/open", X_OK) == 0) {
- char *dialog; /* do we have dialog?*/
-
+ access (EXPANDED_SBINDIR "/gdmopen", X_OK) == 0) {
/* Shit if we knew what the program was to tell the user,
* the above script would have been defined and we'd run
* it for them */
@@ -737,29 +759,7 @@ deal_with_x_crashes (GdmDisplay *d)
"up correctly. You will need to log in on a "
"console and rerun the X configuration "
"program. Then restart GDM.");
-
- dialog = gnome_is_program_in_path ("dialog");
- if (dialog == NULL)
- dialog = gnome_is_program_in_path ("gdialog");
- if (dialog != NULL) {
- char *command =
- g_strdup_printf
- ("/usr/bin/open -s -w -- /bin/sh -c 'clear ; "
- "%s --msgbox \"%s\" 10 70 ; clear'",
- dialog,
- error);
- system (command);
- g_free (command);
- g_free (dialog);
- } else {
- char *command =
- g_strdup_printf
- ("/usr/bin/open -s -w -- /bin/sh -c 'clear ; "
- "echo \"%s\" 10 70 ; read ; clear'",
- error);
- system (command);
- g_free (command);
- }
+ gdm_text_message_dialog (error);
} /* else {
* At this point .... screw the user, we don't know how to
* talk to him. He's on some 'l33t system anyway, so syslog
diff --git a/daemon/gdm.h b/daemon/gdm.h
index c93a65a5..f90686f1 100644
--- a/daemon/gdm.h
+++ b/daemon/gdm.h
@@ -268,6 +268,8 @@ struct _GdmDisplay {
int vt;
#endif
+ gboolean busy_display;
+
gboolean console;
time_t last_start_time;
diff --git a/daemon/misc.c b/daemon/misc.c
index 8b6549ad..7db6d5b1 100644
--- a/daemon/misc.c
+++ b/daemon/misc.c
@@ -16,12 +16,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <config.h>
+#include "config.h"
#include <gnome.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <sys/socket.h>
+#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
@@ -41,6 +43,8 @@ extern GSList *displays;
extern char **environ;
+extern pid_t extra_process;
+
/**
* gdm_fail:
@@ -216,7 +220,8 @@ gdm_get_free_display (int start, int server_uid)
serv_addr.sin_port = htons (6000 + i);
errno = 0;
- if (connect (sock, &serv_addr, sizeof (serv_addr)) >= 0 ||
+ if (connect (sock, (struct sockaddr *)&serv_addr,
+ sizeof (serv_addr)) >= 0 ||
errno != ECONNREFUSED) {
close (sock);
continue;
@@ -241,4 +246,187 @@ gdm_get_free_display (int start, int server_uid)
return -1;
}
+gboolean
+gdm_text_message_dialog (const char *msg)
+{
+ char *dialog; /* do we have dialog?*/
+
+ if (access (EXPANDED_SBINDIR "/gdmopen", X_OK) != 0)
+ return FALSE;
+
+ dialog = gnome_is_program_in_path ("dialog");
+ if (dialog == NULL)
+ dialog = gnome_is_program_in_path ("gdialog");
+ if (dialog != NULL) {
+ char *argv[7];
+
+ argv[0] = EXPANDED_SBINDIR "/gdmopen";
+ argv[1] = dialog;
+ argv[2] = "--msgbox";
+ argv[3] = (char *)msg;
+ argv[4] = "11";
+ argv[5] = "70";
+ argv[6] = NULL;
+
+ if (gdm_exec_wait (argv) < 0) {
+ g_free (dialog);
+ return FALSE;
+ }
+
+ g_free (dialog);
+ } else {
+ char *argv[5];
+
+ argv[0] = EXPANDED_SBINDIR "/gdmopen";
+ argv[1] = "/bin/sh";
+ argv[2] = "-c";
+ argv[3] = g_strdup_printf
+ ("clear ; "
+ "echo \"%s\" ; read ; clear",
+ msg);
+ argv[4] = NULL;
+
+ if (gdm_exec_wait (argv) < 0) {
+ g_free (argv[3]);
+ return FALSE;
+ }
+ g_free (argv[3]);
+ }
+ return TRUE;
+}
+
+gboolean
+gdm_text_yesno_dialog (const char *msg, gboolean *ret)
+{
+ char *dialog; /* do we have dialog?*/
+
+ if (access (EXPANDED_SBINDIR "/gdmopen", X_OK) != 0)
+ return FALSE;
+
+ if (ret != NULL)
+ *ret = FALSE;
+
+ dialog = gnome_is_program_in_path ("dialog");
+ if (dialog == NULL)
+ dialog = gnome_is_program_in_path ("gdialog");
+ if (dialog != NULL) {
+ char *argv[7];
+ int retint;
+
+ argv[0] = EXPANDED_SBINDIR "/gdmopen";
+ argv[1] = dialog;
+ argv[2] = "--yesno";
+ argv[3] = (char *)msg;
+ argv[4] = "11";
+ argv[5] = "70";
+ argv[6] = NULL;
+
+ retint = gdm_exec_wait (argv);
+ if (retint < 0) {
+ g_free (dialog);
+ return FALSE;
+ }
+
+ if (ret != NULL)
+ *ret = (retint == 0) ? TRUE : FALSE;
+
+ g_free (dialog);
+
+ return TRUE;
+ } else {
+ char tempname[] = "/tmp/gdm-yesno-XXXXXX";
+ int tempfd;
+ FILE *fp;
+ char buf[256];
+ char *argv[5];
+
+ tempfd = mkstemp (tempname);
+ if (tempfd < 0)
+ return FALSE;
+
+ close (tempfd);
+
+ argv[0] = EXPANDED_SBINDIR "/gdmopen";
+ argv[1] = "/bin/sh";
+ argv[2] = "-c";
+ argv[3] = g_strdup_printf
+ ("clear ; "
+ "echo \"%s\" ; echo ; echo \"%s\" ; "
+ "read RETURN ; echo $RETURN > %s ; clear'",
+ msg,
+ /* Translators, don't translate the 'y' and 'n' */
+ _("y = Yes or n = No? >"),
+ tempname);
+ argv[4] = NULL;
+
+ if (gdm_exec_wait (argv) < 0) {
+ g_free (argv[3]);
+ return FALSE;
+ }
+ g_free (argv[3]);
+
+ if (ret != NULL) {
+ fp = fopen (tempname, "r");
+ if (fp != NULL) {
+ if (fgets (buf, sizeof (buf), fp) != NULL &&
+ (buf[0] == 'y' || buf[0] == 'Y'))
+ *ret = TRUE;
+ fclose (fp);
+ } else {
+ return FALSE;
+ }
+ }
+
+ unlink (tempname);
+
+ return TRUE;
+ }
+}
+
+int
+gdm_exec_wait (char * const *argv)
+{
+ int status;
+ pid_t pid;
+
+ if (argv == NULL ||
+ argv[0] == NULL ||
+ access (argv[0], X_OK) != 0)
+ return -1;
+
+ /* Note a fun and unavoidable (also almost
+ * impossible to happen race. If the parent gets
+ * whacked before it executes any code, it will
+ * not whack the child. Oh well. */
+ extra_process = pid = fork ();
+ if (pid == 0) {
+ int i;
+
+ for (i = 0; i < sysconf (_SC_OPEN_MAX); i++)
+ close (i);
+
+ /* No error checking here - if it's messed the best response
+ * is to ignore & try to continue */
+ open ("/dev/null", O_RDONLY); /* open stdin - fd 0 */
+ open ("/dev/null", O_RDWR); /* open stdout - fd 1 */
+ open ("/dev/null", O_RDWR); /* open stderr - fd 2 */
+
+ execv (argv[0], argv);
+
+ _exit (-1);
+ }
+
+ if (pid < 0)
+ return -1;
+
+ waitpid (pid, &status, 0);
+
+ extra_process = -1;
+
+ if (WIFEXITED (status))
+ return WEXITSTATUS (status);
+ else
+ return -1;
+}
+
/* EOF */
diff --git a/daemon/misc.h b/daemon/misc.h
index b90a0886..7e6c73f0 100644
--- a/daemon/misc.h
+++ b/daemon/misc.h
@@ -33,6 +33,10 @@ void gdm_clearenv_no_lang (void);
int gdm_get_free_display (int start, int server_uid);
+gboolean gdm_text_message_dialog (const char *msg);
+gboolean gdm_text_yesno_dialog (const char *msg, gboolean *ret);
+int gdm_exec_wait (char * const *argv);
+
#endif /* GDM_MISC_H */
/* EOF */
diff --git a/daemon/server.c b/daemon/server.c
index 46274821..13b563b5 100644
--- a/daemon/server.c
+++ b/daemon/server.c
@@ -127,55 +127,37 @@ gdm_server_stop (GdmDisplay *disp)
unlink (disp->authfile);
}
-static void
-busy_inform_user (GdmDisplay *disp)
+static gboolean
+busy_ask_user (GdmDisplay *disp)
{
/* if we have "open" we can talk to the user */
- if (access ("/usr/bin/open", X_OK) == 0) {
- char *dialog; /* do we have dialog?*/
+ if (access (EXPANDED_SBINDIR "/gdmopen", X_OK) == 0) {
char *error = g_strdup_printf
(_("There already appears to be an X server "
- "running on display %s. Please quit this "
- "server and then press Enter.%s"),
+ "running on display %s. Should I try another "
+ "display number? If you answer no, I will "
+ "attempt to start the server on %s again.%s"),
+ disp->name,
disp->name,
#ifdef __linux__
- _(" You can change consoles by pressing Ctrl-Alt "
+ _(" (You can change consoles by pressing Ctrl-Alt "
"plus a function key, such as Ctrl-Alt-F7 to go "
"to console 7. X servers usually run on consoles "
- "7 and higher.")
+ "7 and higher.)")
#else /* ! __linux__ */
/* no info for non linux users */
""
#endif /* __linux__ */
);
- dialog = gnome_is_program_in_path ("dialog");
- if (dialog == NULL)
- dialog = gnome_is_program_in_path ("gdialog");
- if (dialog != NULL) {
- char *command =
- g_strdup_printf
- ("/usr/bin/open -s -w -- /bin/sh -c 'clear ; "
- "%s --msgbox \"%s\" 10 70 ; clear'",
- dialog,
- error);
- system (command);
- g_free (command);
- g_free (dialog);
- } else {
- char *command =
- g_strdup_printf
- ("/usr/bin/open -s -w -- /bin/sh -c 'clear ; "
- "echo \"%s\" 10 70 ; read ; clear'",
- error);
- system (command);
- g_free (command);
- }
+ gboolean ret = TRUE;
+ /* default ret to TRUE */
+ if ( ! gdm_text_yesno_dialog (error, &ret))
+ ret = TRUE;
g_free (error);
+ return ret;
} else {
- /* If we can't ask, sleep 30 seconds and try again */
- gdm_info (_("Sleeping 30 seconds before retrying display %s"),
- disp->name);
- sleep (30);
+ /* Well we'll just try another display number */
+ return TRUE;
}
}
@@ -276,7 +258,8 @@ display_vt (GdmDisplay *disp)
*/
gboolean
-gdm_server_start (GdmDisplay *disp, int min_flexi_disp, int flexi_retries)
+gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi,
+ int min_flexi_disp, int flexi_retries)
{
struct sigaction usr1, chld, alrm;
struct sigaction old_usr1, old_chld, old_alrm;
@@ -291,7 +274,8 @@ gdm_server_start (GdmDisplay *disp, int min_flexi_disp, int flexi_retries)
/* if an X server exists, wipe it */
gdm_server_stop (d);
- if (SERVER_IS_FLEXI (d)) {
+ if (SERVER_IS_FLEXI (d) ||
+ treat_as_flexi) {
flexi_disp = gdm_get_free_display
(MAX (high_display_num + 1, min_flexi_disp) /* start */,
0 /* server uid */);
@@ -432,25 +416,37 @@ gdm_server_start (GdmDisplay *disp, int min_flexi_disp, int flexi_retries)
* this we'll exit with DISPLAY_REMANAGE to try again if the
* user wants to, or abort this display */
if (display_busy (disp)) {
- if (SERVER_IS_FLEXI (disp)) {
+ if (SERVER_IS_FLEXI (disp) ||
+ treat_as_flexi) {
/* for flexi displays, try again a few times with different
* display numbers */
if (flexi_retries <= 0) {
/* Send X too busy */
- gdm_slave_send_num (GDM_SOP_FLEXI_ERR,
- 4 /* X too busy */);
+ gdm_error (_("%s: Cannot find a free "
+ "display number"),
+ "gdm_server_start");
+ if (SERVER_IS_FLEXI (disp)) {
+ gdm_slave_send_num (GDM_SOP_FLEXI_ERR,
+ 4 /* X too busy */);
+ }
/* eki eki */
_exit (DISPLAY_REMANAGE);
}
- return gdm_server_start (d, flexi_disp + 1,
+ return gdm_server_start (d, treat_as_flexi,
+ flexi_disp + 1,
flexi_retries - 1);
} else {
- /* FIXME: find first free display here above
- * high_display_num optionally, and if the user
- * has no dialog/gdialog, then just do that
- * immediately. Must give an error as well on
- * the X server once greeter is up. */
- busy_inform_user (disp);
+ if (busy_ask_user (disp)) {
+ gdm_error (_("%s: Display %s busy. Trying "
+ "another display number."),
+ "gdm_server_start",
+ d->name);
+ d->busy_display = TRUE;
+ return gdm_server_start (d,
+ TRUE /* treat as flexi */,
+ high_display_num + 1,
+ flexi_retries - 1);
+ }
_exit (DISPLAY_REMANAGE);
}
}
diff --git a/daemon/server.h b/daemon/server.h
index 6ab2abfe..823606da 100644
--- a/daemon/server.h
+++ b/daemon/server.h
@@ -22,6 +22,7 @@
#include "gdm.h"
gboolean gdm_server_start (GdmDisplay *d,
+ gboolean treat_as_flexi,
int min_flexi_disp,
int flexi_retries);
void gdm_server_stop (GdmDisplay *d);
diff --git a/daemon/slave.c b/daemon/slave.c
index 1e3bd71e..235143d6 100644
--- a/daemon/slave.c
+++ b/daemon/slave.c
@@ -74,6 +74,7 @@ static gchar *ParsedTimedLogin = NULL;
extern gboolean gdm_first_login;
extern gboolean gdm_emergency_server;
+extern pid_t extra_process;
/* Configuration option variables */
extern gchar *GdmUser;
@@ -356,6 +357,7 @@ gdm_slave_run (GdmDisplay *display)
if (SERVER_IS_LOCAL (d) &&
d->servpid <= 0) {
gdm_server_start (d,
+ FALSE /* treat_as_flexi */,
20 /* min_flexi_disp */,
5 /* flexi_retries */);
gdm_slave_send_num (GDM_SOP_XPID, d->servpid);
@@ -1105,6 +1107,15 @@ gdm_slave_greeter (void)
"configure the X server."));
}
+ if (d->busy_display) {
+ char *msg = g_strdup_printf
+ (_("The specified display number was busy, so "
+ "this server was started on display %s."),
+ d->name);
+ gdm_error_box (d, GNOME_MESSAGE_BOX_ERROR, msg);
+ g_free (msg);
+ }
+
argv = ve_split (GdmGreeter);
execv (argv[0], argv);
@@ -2063,7 +2074,9 @@ gdm_slave_session_start (void)
/* just a stupid test, the below would fail, but this gives a better
* message */
- if (strcmp (shell, "/bin/false") == 0) {
+ if (strcmp (shell, "/sbin/nologin") == 0 ||
+ strcmp (shell, "/bin/false") == 0 ||
+ strcmp (shell, "/bin/true") == 0) {
gdm_error (_("gdm_slave_session_start: User not allowed to log in"));
gdm_error_box (d, GNOME_MESSAGE_BOX_ERROR,
_("The system administrator has\n"
@@ -2196,6 +2209,12 @@ gdm_slave_term_handler (int sig)
sigaddset (&tmask, SIGCHLD);
sigprocmask (SIG_BLOCK, &tmask, &omask);
+ if (extra_process > 1) {
+ /* we sigterm extra processes, and we
+ * don't wait */
+ kill (extra_process, SIGTERM);
+ extra_process = -1;
+ }
if (d->greetpid != 0) {
greet = FALSE;
@@ -2461,6 +2480,7 @@ gdm_slave_exec_script (GdmDisplay *d, const gchar *dir, const char *login,
gchar *script, *defscript, *scr;
gchar **argv;
gint status;
+ int i;
if (!d || !dir)
return EXIT_SUCCESS;
@@ -2475,9 +2495,19 @@ gdm_slave_exec_script (GdmDisplay *d, const gchar *dir, const char *login,
else
return EXIT_SUCCESS;
- switch (pid = fork()) {
+ extra_process = pid = fork();
+ switch (pid) {
case 0:
+ for (i = 0; i < sysconf (_SC_OPEN_MAX); i++)
+ close (i);
+
+ /* No error checking here - if it's messed the best response
+ * is to ignore & try to continue */
+ open ("/dev/null", O_RDONLY); /* open stdin - fd 0 */
+ open ("/dev/null", O_RDWR); /* open stdout - fd 1 */
+ open ("/dev/null", O_RDWR); /* open stderr - fd 2 */
+
if (login != NULL) {
ve_setenv ("LOGNAME", login, TRUE);
ve_setenv ("USER", login, TRUE);
@@ -2512,6 +2542,8 @@ gdm_slave_exec_script (GdmDisplay *d, const gchar *dir, const char *login,
default:
waitpid (pid, &status, 0); /* Wait for script to finish */
+ extra_process = -1;
+
if (WIFEXITED (status))
return WEXITSTATUS (status);
else
@@ -2630,7 +2662,8 @@ gdm_parse_enriched_login (const gchar *s, GdmDisplay *display)
if (pipe(pipe1) < 0)
syslog (LOG_ERR, _("gdm_parse_enriched_login: Failed creating pipe"));
- switch (pid = fork()) {
+ extra_process = pid = fork();
+ switch (pid) {
case 0:
/* The child will write the username to stdout based on the DISPLAY
@@ -2670,6 +2703,7 @@ gdm_parse_enriched_login (const gchar *s, GdmDisplay *display)
close(pipe1[0]);
waitpid (pid, &status, 0); /* Wait for script to finish */
+ extra_process = -1;
}
}
diff --git a/daemon/verify-crypt.c b/daemon/verify-crypt.c
index 65722bd3..14cd8f23 100644
--- a/daemon/verify-crypt.c
+++ b/daemon/verify-crypt.c
@@ -166,7 +166,8 @@ gdm_verify_user (const char *username,
/* check for the standard method of disallowing users */
if (pwent->pw_shell != NULL &&
- (strcmp (pwent->pw_shell, "/bin/true") == 0 ||
+ (strcmp (pwent->pw_shell, "/sbin/nologin") == 0 ||
+ strcmp (pwent->pw_shell, "/bin/true") == 0 ||
strcmp (pwent->pw_shell, "/bin/false") == 0)) {
gdm_error (_("User %s not allowed to log in"), login);
if (GdmVerboseAuth) {
diff --git a/daemon/verify-pam.c b/daemon/verify-pam.c
index bd7d1a9f..137662b9 100644
--- a/daemon/verify-pam.c
+++ b/daemon/verify-pam.c
@@ -234,7 +234,8 @@ gdm_verify_user (const char *username,
/* check for the standard method of disallowing users */
if (pwent != NULL &&
pwent->pw_shell != NULL &&
- (strcmp (pwent->pw_shell, "/bin/true") == 0 ||
+ (strcmp (pwent->pw_shell, "/sbin/nologin") == 0 ||
+ strcmp (pwent->pw_shell, "/bin/true") == 0 ||
strcmp (pwent->pw_shell, "/bin/false") == 0)) {
gdm_error (_("User %s not allowed to log in"), login);
if (GdmVerboseAuth) {
diff --git a/daemon/verify-shadow.c b/daemon/verify-shadow.c
index bd96293a..0bbe2547 100644
--- a/daemon/verify-shadow.c
+++ b/daemon/verify-shadow.c
@@ -175,7 +175,8 @@ gdm_verify_user (const char *username, const gchar *display, gboolean local)
/* check for the standard method of disallowing users */
if (pwent->pw_shell != NULL &&
- (strcmp (pwent->pw_shell, "/bin/true") == 0 ||
+ (strcmp (pwent->pw_shell, "/sbin/nologin") == 0 ||
+ strcmp (pwent->pw_shell, "/bin/true") == 0 ||
strcmp (pwent->pw_shell, "/bin/false") == 0)) {
gdm_error (_("User %s not allowed to log in"), login);
if (GdmVerboseAuth) {
diff --git a/daemon/xdmcp.c b/daemon/xdmcp.c
index 80742edf..78b3b47a 100644
--- a/daemon/xdmcp.c
+++ b/daemon/xdmcp.c
@@ -419,7 +419,7 @@ gdm_xdmcp_decode_packet (GIOChannel *source, GIOCondition cond, gpointer data)
"MANAGED_FORWARD"
};
- if (!XdmcpFill (xdmcpfd, &buf, &clnt_sa, &sa_len)) {
+ if (!XdmcpFill (xdmcpfd, &buf, (XdmcpNetaddr)&clnt_sa, &sa_len)) {
gdm_error (_("gdm_xdmcp_decode: Could not create XDMCP buffer!"));
return TRUE;
}
diff --git a/gdm.spec.in b/gdm.spec.in
index 8ae30aac..3ac68f6e 100644
--- a/gdm.spec.in
+++ b/gdm.spec.in
@@ -14,6 +14,7 @@ BuildRoot: %{_tmppath}/gdm-%{version}-root
Prereq: /usr/sbin/useradd
Requires: pam >= 0.68
Requires: gnome-libs >= 1.0.17
+Epoch: 1
%description
Gdm (the GNOME Display Manager) is a highly configurable
diff --git a/gui/gdmflexiserver.desktop.in b/gui/gdmflexiserver.desktop.in
index d18c2282..3f112ddf 100644
--- a/gui/gdmflexiserver.desktop.in
+++ b/gui/gdmflexiserver.desktop.in
@@ -1,7 +1,6 @@
[Desktop Entry]
_Name=New login
_Comment=Log in as another user without loging out
-TryExec=gdmflexiserver
Exec=gdmflexiserver
Icon=
Terminal=0
diff --git a/utils/.cvsignore b/utils/.cvsignore
new file mode 100644
index 00000000..005306fe
--- /dev/null
+++ b/utils/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+.libs
+.deps
+gdmaskpass
+gdmopen
diff --git a/utils/Makefile.am b/utils/Makefile.am
new file mode 100644
index 00000000..d24fce3e
--- /dev/null
+++ b/utils/Makefile.am
@@ -0,0 +1,41 @@
+## Process this file with automake to produce makefile.in
+CFLAGS += -g -Wall \
+ -Wpointer-arith \
+ -Wmissing-prototypes -Wmissing-declarations
+
+DEFS += -DGDM_CONFIG_FILE=\"@sysconfdir@/gdm/gdm.conf\" \
+ -DGDM_FACTORY_CONFIG_FILE=\"@sysconfdir@/gdm/factory-gdm.conf\" \
+ -DGDM_GLADE_DIR=\"@datadir@/gdm\"
+
+INCLUDES = \
+ -I. \
+ -I.. \
+ -I$(top_srcdir)/daemon \
+ -I$(top_srcdir)/vicious-extensions \
+ -I$(includedir) \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ @LIBGLADE_CFLAGS@ \
+ @PIXBUF_CFLAGS@ \
+ $(GNOME_CFLAGS) \
+ $(GNOME_INCLUDEDIR)
+
+sbin_PROGRAMS = \
+ @GDMASKPASS@ \
+ @GDMOPEN@
+EXTRA_PROGRAMS = gdmaskpass gdmopen
+
+gdmaskpass_SOURCES = \
+ gdmaskpass.c
+
+gdmopen_SOURCES = \
+ gdmopen.c
+
+gdmaskpass_LDADD = \
+ $(GNOME_LIBDIR) \
+ $(INTLLIBS) \
+ -lpam \
+ -lpam_misc
+
+gdmopen_LDADD = \
+ $(GNOME_LIBDIR) \
+ $(INTLLIBS)
diff --git a/utils/gdmaskpass.c b/utils/gdmaskpass.c
new file mode 100644
index 00000000..8c083a68
--- /dev/null
+++ b/utils/gdmaskpass.c
@@ -0,0 +1,58 @@
+/* Simple pam thingie to ask the root password, for use in XKeepsCrashing
+ * script. */
+#include "config.h"
+#include <gnome.h>
+#include <stdio.h>
+#include <locale.h>
+#include <unistd.h>
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+
+static struct pam_conv conv = {
+ misc_conv,
+ NULL
+};
+
+int
+main (int argc, char *argv[])
+{
+ pam_handle_t *pamh;
+ const char *username = "root";
+ int retval;
+ int tries = 3;
+
+ if (getuid () != geteuid () ||
+ getuid () != 0) {
+ fprintf (stderr, _("gdmaskpass only runs as root\n"));
+ return 1;
+ }
+
+ if (argc >= 2) {
+ username = argv[1];
+ }
+
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, GNOMELOCALEDIR);
+ textdomain (PACKAGE);
+
+ for (tries = 3; tries > 0; tries --) {
+ if ((retval = pam_start ("gdm", username, &conv, &pamh)) != PAM_SUCCESS) {
+ pam_end (pamh, retval);
+ pamh = NULL;
+ printf (_("Authentication failure!\n"));
+ continue;
+ }
+ if ((retval = pam_authenticate (pamh, 0)) != PAM_SUCCESS) {
+ pam_end (pamh, retval);
+ pamh = NULL;
+ printf (_("Authentication failure!\n"));
+ continue;
+ }
+ break;
+ }
+
+ if (pamh != NULL)
+ pam_end (pamh, retval);
+
+ return (retval == PAM_SUCCESS) ? 0 : 1;
+}
diff --git a/utils/gdmopen.c b/utils/gdmopen.c
new file mode 100644
index 00000000..d5c8574d
--- /dev/null
+++ b/utils/gdmopen.c
@@ -0,0 +1,201 @@
+/*
+ * gdmopen.c by the Queen of England, based upon original open.
+ * Simplified for the purposes of gdm. All useless (to me)
+ * functionality stripped. Also returns what the command returns.
+ * Return of 66 means error with open.
+ *
+ * Original header:
+ *
+ * open.c open a vt to run a new command (or shell).
+ *
+ * Copyright (c) 1994 by Jon Tombs <jon@gtex02.us.es>
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+
+/*
+ * Where your VTs are hidden
+ */
+#ifdef __linux__
+#define VTNAME "/dev/tty%d"
+#endif
+
+#ifdef ESIX_5_3_2_D
+#define VTBASE "/dev/vt%02d"
+#endif
+
+const char *GDMOPENversion = "gdmopen " VERSION " simplified (was: open: 1.4 (c) Jon Tombs 1994)";
+
+#ifndef VTNAME
+#error vt device name must be defined in open.c
+#endif
+
+static pid_t child_pid = -1;
+struct vt_stat vt;
+static int vtno;
+static int fd = 0;
+static int do_dealloc = FALSE;
+
+static void
+sighandler (int sig)
+{
+ if (child_pid > 1) {
+ if (kill (child_pid, sig) == 0)
+ waitpid (child_pid, NULL, 0);
+ }
+
+ if (do_dealloc) {
+ /* Switch back... */
+ (void) ioctl(fd, VT_ACTIVATE, vt.v_active);
+ /* wait to be really sure we have switched */
+ (void) ioctl(fd, VT_WAITACTIVE, vt.v_active);
+
+ /* Now deallocate our new one */
+ (void) ioctl(fd, VT_DISALLOCATE, vtno);
+ }
+
+ /* Kill myself with this signal */
+ signal (sig, SIG_DFL);
+ kill (getpid (), sig);
+}
+
+int
+main (int argc, char *argv[])
+{
+ char vtname[256];
+ int status;
+
+ if (getuid () != geteuid () ||
+ getuid () != 0) {
+ fprintf (stderr, "gdmopen: Only root wants to run me\n");
+ return 66;
+ }
+
+ signal (SIGTERM, sighandler);
+ signal (SIGINT, sighandler);
+ signal (SIGHUP, sighandler);
+
+ if (argc <= 1) {
+ fprintf (stderr, "gdmopen: must supply a command!\n");
+ return 66;
+ }
+
+ fd = open ("/dev/console", O_WRONLY, 0);
+ if (fd < 0) {
+ perror ("gdmopen: Failed to open /dev/console");
+ return 66;
+ }
+
+ errno = 0;
+ if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) {
+ perror ("gdmopen: Cannot find a free VT");
+ close (fd);
+ return 66;
+ }
+
+ if (ioctl(fd, VT_GETSTATE, &vt) < 0) {
+ perror ("gdmopen: can't get VTstate");
+ close(fd);
+ return 66;
+ }
+
+ snprintf (vtname, sizeof (vtname), VTNAME, vtno);
+
+ chown (vtname, 0, -1);
+
+ child_pid = fork();
+ if (child_pid == 0) {
+
+ signal (SIGTERM, SIG_DFL);
+ signal (SIGINT, SIG_DFL);
+ signal (SIGHUP, SIG_DFL);
+
+ /* leave current vt */
+ if (
+#ifdef ESIX_5_3_2_D
+ setpgrp() < 0
+#else
+ setsid() < 0
+#endif
+ ) {
+ fprintf(stderr, "open: Unable to set new session (%s)\n",
+ strerror(errno));
+ }
+ close(0);
+ close(1);
+ close(2);
+ close(fd);
+
+ /* and grab new one */
+ fd = open (vtname, O_RDWR);
+ if (fd < 0) { /* Shouldn't happen */
+ _exit (66); /* silently die */
+ }
+ dup(fd);
+ dup(fd);
+
+ /*
+ * Can't tell anyone if any of these fail, so throw away
+ * the return values
+ */
+ (void) ioctl(fd, VT_ACTIVATE, vtno);
+ /* wait to be really sure we have switched */
+ (void) ioctl(fd, VT_WAITACTIVE, vtno);
+
+ execvp (argv[1], &argv[1]);
+
+ _exit (66); /* failed */
+ }
+
+ if (child_pid < 0) {
+ perror ("gdmopen: fork() error");
+ return 66;
+ }
+
+ do_dealloc = TRUE;
+
+ waitpid (child_pid, &status, 0);
+ child_pid = -1;
+
+ do_dealloc = FALSE;
+
+ /* Switch back... */
+ (void) ioctl(fd, VT_ACTIVATE, vt.v_active);
+ /* wait to be really sure we have switched */
+ (void) ioctl(fd, VT_WAITACTIVE, vt.v_active);
+
+ /* Now deallocate our new one */
+ (void) ioctl(fd, VT_DISALLOCATE, vtno);
+
+ close (fd);
+
+ if (WIFEXITED (status))
+ return WEXITSTATUS (status);
+ else
+ return 66;
+}