[pkg-fso-commits] [SCM] Automatic Display Manager branch, bug540201, updated. debian/0.6-1-43-g57ac67b

Enrico Zini enrico at enricozini.org
Wed Jul 6 11:01:00 UTC 2011


The following commit has been merged in the bug540201 branch:
commit 57ac67b7bb9e3effcf0cab7ab23e541bf30bfe01
Author: Enrico Zini <enrico at enricozini.org>
Date:   Wed Jul 6 13:00:56 2011 +0200

    Cleaned up VT allocation code

diff --git a/Makefile.am b/Makefile.am
index a59bba1..84016ef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,9 +6,9 @@ ACLOCAL_AMFLAGS = -I m4
 
 sbin_PROGRAMS = nodm
 
-dist_noinst_HEADERS = common.h dm.h log.h test.h xserver.h xsession.h xsession-child.h
+dist_noinst_HEADERS = common.h dm.h log.h test.h vt.h xserver.h xsession.h xsession-child.h
 
-libsources = common.c log.c xsession-child.c xserver.c xsession.c dm.c
+libsources = common.c log.c vt.c xsession-child.c xserver.c xsession.c dm.c
 testlibsources = $(libsources) test.c
 
 AM_CPPFLAGS = $(X11_CFLAGS)
diff --git a/common.c b/common.c
index 656af4b..897f90c 100644
--- a/common.c
+++ b/common.c
@@ -20,6 +20,13 @@
 
 #include "common.h"
 #include <stdlib.h>
+#include <string.h>
+
+const char* basename (const char* str)
+{
+    const char *cp = strrchr (str, '/');
+    return cp ? cp + 1 : str;
+}
 
 const char* getenv_with_default(const char* envname, const char* def)
 {
diff --git a/common.h b/common.h
index 63f791a..fad3de6 100644
--- a/common.h
+++ b/common.h
@@ -38,11 +38,15 @@
 #define E_PAM_ERROR           201   ///< something wrong talking with PAM
 #define E_OS_ERROR            202   ///< something wrong talking with the Operating System
 #define E_XLIB_ERROR          203   ///< Xlib error
+#define E_VT_ALLOC_ERROR      204   ///< VT allocation error
 #define E_X_SERVER_DIED       210   ///< Server died
 #define E_X_SERVER_TIMEOUT    211   ///< Server not ready before timeout
 #define E_X_SERVER_CONNECT    212   ///< Could not connect to X server
 #define E_SESSION_DIED        220   ///< X session died
 
+/// Return the basename of a path, as a pointer inside \a str
+const char* basename (const char* str);
+
 /**
  * Like getenv, but if the variable is not defined it returns \a def
  */
diff --git a/dm.c b/dm.c
index 54e6a36..0c25874 100644
--- a/dm.c
+++ b/dm.c
@@ -1,5 +1,5 @@
 /*
- * session - nodm X display manager
+ * dm - nodm X display manager
  *
  * Copyright 2011  Enrico Zini <enrico at enricozini.org>
  *
@@ -27,12 +27,14 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
+#include <stdio.h>
 
 
 void nodm_display_manager_init(struct nodm_display_manager* dm)
 {
-    nodm_xserver_init(&(dm->srv));
-    nodm_xsession_init(&(dm->session));
+    nodm_xserver_init(&dm->srv);
+    nodm_xsession_init(&dm->session);
+    nodm_vt_init(&dm->vt);
     dm->_srv_split_args = NULL;
     dm->_srv_split_argv = NULL;
 }
@@ -57,7 +59,21 @@ void nodm_display_manager_cleanup(struct nodm_display_manager* dm)
 
 int nodm_display_manager_start(struct nodm_display_manager* dm)
 {
-    int res = nodm_xserver_start(&dm->srv);
+    int res = nodm_vt_start(&dm->vt);
+    if (res != E_SUCCESS) return res;
+
+    if (dm->vt.num != -1)
+    {
+        // Create the vtN argument
+        snprintf(dm->_vtarg, sizeof(dm->_vtarg), "vt%d", dm->vt.num);
+        // Append it to srv args
+        const char** s = dm->srv.argv;
+        while (*s) ++s;
+        *s++ = dm->_vtarg;
+        *s = NULL;
+    }
+
+    res = nodm_xserver_start(&dm->srv);
     if (res != E_SUCCESS) return res;
 
     res = nodm_xsession_start(&dm->session, &dm->srv);
@@ -74,10 +90,12 @@ int nodm_display_manager_stop(struct nodm_display_manager* dm)
     res = nodm_xserver_stop(&dm->srv);
     if (res != E_SUCCESS) return res;
 
+    nodm_vt_stop(&dm->vt);
+
     return E_SUCCESS;
 }
 
-int nodm_display_manager_wait(struct nodm_display_manager* dm)
+int nodm_display_manager_wait(struct nodm_display_manager* dm, int* session_status)
 {
     while (true)
     {
@@ -103,7 +121,8 @@ int nodm_display_manager_wait(struct nodm_display_manager* dm)
         } else if (child == dm->session.pid) {
             // Session died
             log_warn("X session died with status %d", status);
-            return status;
+            *session_status = status;
+            return E_SESSION_DIED;
         }
     }
 }
@@ -128,7 +147,9 @@ int nodm_display_manager_parse_xcmdline(struct nodm_display_manager* s, const ch
 
     unsigned in_arg = 0;
     unsigned argc = 0;
-    char **argv = (char**)malloc((toks->we_wordc + 3) * sizeof(char*));
+    // +1 for the X server pathname, +1 for the display name,
+    // +1 for the VT number, +1 for the trailing NULL
+    char **argv = (char**)malloc((toks->we_wordc + 4) * sizeof(char*));
     if (argv == NULL)
     {
         return_code = E_OS_ERROR;
@@ -159,7 +180,13 @@ int nodm_display_manager_parse_xcmdline(struct nodm_display_manager* s, const ch
 
     // Copy other args
     while (in_arg < toks->we_wordc)
+    {
+        int vtn;
+        if (sscanf(toks->we_wordv[in_arg], "vt%d", &vtn) == 1)
+            // if vtN has been provided by the caller, disable VT allocation
+            s->vt.conf_initial_vt = -1;
         argv[argc++] = toks->we_wordv[in_arg++];
+    }
     argv[argc] = NULL;
 
     s->srv.argv = (const char**)argv;
diff --git a/dm.h b/dm.h
index 04deaa7..e10d504 100644
--- a/dm.h
+++ b/dm.h
@@ -1,5 +1,5 @@
 /*
- * session - nodm X display manager
+ * dm - nodm X display manager
  *
  * Copyright 2011  Enrico Zini <enrico at enricozini.org>
  *
@@ -23,6 +23,7 @@
 
 #include "xserver.h"
 #include "xsession.h"
+#include "vt.h"
 
 struct nodm_display_manager
 {
@@ -32,10 +33,15 @@ struct nodm_display_manager
     /// X session supervision
     struct nodm_xsession session;
 
+    /// VT allocation
+    struct nodm_vt vt;
 
     /// Storage for split server arguments used by nodm_x_cmdline_split
     char** _srv_split_argv;
     void* _srv_split_args;
+
+    /// Storage for vtN argument from dynamic VT allocation
+    char _vtarg[10];
 };
 
 /// Initialise a display_manager structure with default values
@@ -48,7 +54,9 @@ void nodm_display_manager_cleanup(struct nodm_display_manager* dm);
 int nodm_display_manager_start(struct nodm_display_manager* dm);
 
 /// Wait for X or the X session to end
-int nodm_display_manager_wait(struct nodm_display_manager* dm);
+int nodm_display_manager_wait(struct nodm_display_manager* dm, int* session_status);
+
+// TODO: int nodm_display_manager_restart(struct nodm_display_manager* dm);
 
 /// Stop X and the X session
 int nodm_display_manager_stop(struct nodm_display_manager* dm);
diff --git a/nodm.c b/nodm.c
index 46f61d8..9b95a3e 100644
--- a/nodm.c
+++ b/nodm.c
@@ -1,49 +1,22 @@
 /*
- * Copyright 1989 - 1994, Julianne Frances Haugh
- * Copyright 2009, Enrico Zini
- * All rights reserved.
+ * nodm - nodm X display manager
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
+ * Copyright 2009--2011  Enrico Zini <enrico at enricozini.org>
  *
- * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-/* Some parts substantially derived from an ancestor of: */
-/* su for GNU.  Run a shell with substitute user and group IDs.
-   Copyright (C) 1992-2003 Free Software Foundation, Inc.
-
-   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, 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.  */
 
 
 #define NAME "nodm"
@@ -63,105 +36,15 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <sys/wait.h>
-#include <sys/ioctl.h>
 #include <time.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <sys/vt.h>
 
 
 #define _(...) (__VA_ARGS__)
 
-/*
- * Assorted #defines to control su's behavior
- */
-/*
- * Global variables
- */
-
 /* Program name used in error messages */
-static char *Prog;
-
-/*
- * External identifiers
- */
-
-extern char **newenvp;
-extern char **environ;
-extern size_t newenvc;
-
-/* local function prototypes */
-
-static char *Basename (char *str)
-{
-	char *cp = strrchr (str, '/');
-
-	return cp ? cp + 1 : str;
-}
-
-
-static int try_vtstate(const char* dev, struct vt_stat* vtstat)
-{
-	int res = 0;
-	int fd = open(dev, O_WRONLY | O_NOCTTY, 0);
-	if (fd < 0)
-		goto cleanup;
-	if (ioctl (fd, VT_GETSTATE, vtstat) < 0)
-		goto cleanup;
-	res = 1;
-
-cleanup:
-	if (fd >= 0) close(fd);
-	return res;
-}
-
-static int get_vtstate(struct vt_stat* vtstat)
-{
-	if (try_vtstate("/dev/tty", vtstat)) return 1;
-	if (try_vtstate("/dev/tty0", vtstat)) return 1;
-	if (try_vtstate("/dev/console", vtstat)) return 1;
-	return 0;
-}
-
-/*
- * Allocate a new vt, open it and return the file descriptor and the vt number.
- *
- * Searching the vt starts at the initial value of vtnum.
- */
-int open_vt(int *vtnum)
-{
-	char vtname[15];
-	int res = -1;
-	struct vt_stat vtstat;
-	unsigned short vtmask;
-
-	if (!get_vtstate(&vtstat))
-	{
-		fprintf (stderr, _("%s: cannot find or open the console\n"), Prog);
-		goto cleanup;
-	}
-
-	for (vtmask = 1 << *vtnum; vtstat.v_state & vtmask; ++*vtnum, vtmask <<= 1)
-		;
-	if (!vtmask) {
-		fprintf (stderr, _("%s: all VTs seem to be busy\n"), Prog);
-		goto cleanup;
-	}
-
-	snprintf(vtname, 15, "/dev/tty%d", *vtnum);
-
-	res = open(vtname, O_RDWR | O_NOCTTY, 0);
-	if (res < 0) {
-		fprintf (stderr, _("%s: cannot open %s: %m\n"), Prog, vtname);
-		goto cleanup;
-	}
-
-cleanup:
-	return res;
-}
+static const char *Prog;
 
 /*
  * Run the X session
@@ -273,11 +156,8 @@ static int nodm_monitor(int argc, char **argv)
 	};
 	const char* opt_session = NODM_SESSION;
 	char xoptions[BUFSIZ];
-	char xoptions1[BUFSIZ];
 	char* cp;
 	int mst;
-	int vt_fd = -1;
-	int vt_num;
 
 	/* Parse command line options */
 	while (1)
@@ -315,31 +195,13 @@ static int nodm_monitor(int argc, char **argv)
 
 	log_info("starting nodm monitor");
 
-	{
-		char startvt[BUFSIZ];
-		string_from_env(startvt, "NODM_FIRST_VT", "7");
-		vt_num = strtoul(startvt, NULL, 10);
-	}
-	if ((vt_fd = open_vt(&vt_num)) == -1)
-	{
-		fprintf (stderr, _("%s: cannot allocate a virtual terminal\n"), Prog);
-		return 1;
-	}
-
 	/* Read the configuration from the environment */
 	cp = getenv("NODM_MIN_SESSION_TIME");
 	mst = cp ? atoi(cp) : 60;
 	string_from_env(xoptions, "NODM_X_OPTIONS", "");
 
-	if (xoptions[0] == 0)
-		snprintf(xoptions1, BUFSIZ, "vt%d", vt_num);
-	else
-		snprintf(xoptions1, BUFSIZ, "vt%d %s", vt_num, xoptions);
-
 	setenv("NODM_RUN_SESSION", "1", 1);
-	run_and_restart(opt_session, xoptions1, mst);
-
-	close(vt_fd);
+	run_and_restart(opt_session, xoptions, mst);
 
 	return 0;
 }
@@ -359,7 +221,7 @@ int main (int argc, char **argv)
 	 * Get the program name. The program name is used as a prefix to
 	 * most error messages.
 	 */
-	Prog = Basename (argv[0]);
+	Prog = basename(argv[0]);
 
     // TODO: move these after command line parsing, so we can implement
     // --verbose --no-syslog --no-stderr and the like
diff --git a/test-internals.c b/test-internals.c
index 1ddadb5..59a3c26 100644
--- a/test-internals.c
+++ b/test-internals.c
@@ -44,6 +44,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[1], ":0");
     ensure_equals(s.srv.argv[2], NULL);
     ensure_equals(s.srv.name, ":0");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -53,6 +54,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[2], "foo");
     ensure_equals(s.srv.argv[3], NULL);
     ensure_equals(s.srv.name, ":0");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -61,6 +63,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[1], ":0");
     ensure_equals(s.srv.argv[2], NULL);
     ensure_equals(s.srv.name, ":0");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -69,6 +72,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[1], ":1");
     ensure_equals(s.srv.argv[2], NULL);
     ensure_equals(s.srv.name, ":1");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -77,6 +81,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[1], ":1");
     ensure_equals(s.srv.argv[2], NULL);
     ensure_equals(s.srv.name, ":1");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -86,6 +91,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[2], "foo");
     ensure_equals(s.srv.argv[3], NULL);
     ensure_equals(s.srv.name, ":0");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -95,6 +101,7 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[2], "foo");
     ensure_equals(s.srv.argv[3], NULL);
     ensure_equals(s.srv.name, ":1");
+    ensure_equali(s.vt.conf_initial_vt, 7);
     nodm_display_manager_cleanup(&s);
 
     nodm_display_manager_init(&s);
@@ -104,6 +111,28 @@ int main(int argc, char* argv[])
     ensure_equals(s.srv.argv[2], "foo");
     ensure_equals(s.srv.argv[3], NULL);
     ensure_equals(s.srv.name, ":1");
+    ensure_equali(s.vt.conf_initial_vt, 7);
+    nodm_display_manager_cleanup(&s);
+
+    nodm_display_manager_init(&s);
+    nodm_display_manager_parse_xcmdline(&s, "vt2");
+    ensure_equals(s.srv.argv[0], "/usr/bin/X");
+    ensure_equals(s.srv.argv[1], ":0");
+    ensure_equals(s.srv.argv[2], "vt2");
+    ensure_equals(s.srv.argv[3], NULL);
+    ensure_equals(s.srv.name, ":0");
+    ensure_equali(s.vt.conf_initial_vt, -1);
+    nodm_display_manager_cleanup(&s);
+
+    nodm_display_manager_init(&s);
+    nodm_display_manager_parse_xcmdline(&s, "/usr/bin/Xnest :1 vt42 foo");
+    ensure_equals(s.srv.argv[0], "/usr/bin/Xnest");
+    ensure_equals(s.srv.argv[1], ":1");
+    ensure_equals(s.srv.argv[2], "vt42");
+    ensure_equals(s.srv.argv[3], "foo");
+    ensure_equals(s.srv.argv[4], NULL);
+    ensure_equals(s.srv.name, ":1");
+    ensure_equali(s.vt.conf_initial_vt, -1);
     nodm_display_manager_cleanup(&s);
 
     test_ok();
diff --git a/test-xsession.c b/test-xsession.c
index 41eae06..149814f 100644
--- a/test-xsession.c
+++ b/test-xsession.c
@@ -61,9 +61,12 @@ void test_trivial_session()
     dm.session.conf_use_pam = false;
     dm.session.conf_cleanup_xse = false;
     dm.session.conf_run_as[0] = 0;
+    dm.vt.conf_initial_vt = -1;
     dm.session.child_body = test_session;
     ensure_succeeds(nodm_display_manager_start(&dm));
-    ensure_succeeds(nodm_display_manager_wait(&dm));
+    int sstatus;
+    ensure_succeeds(nodm_display_manager_wait(&dm, &sstatus));
+    ensure_equali(sstatus, E_SUCCESS);
     ensure_succeeds(nodm_display_manager_stop(&dm));
     nodm_display_manager_cleanup(&dm);
 }
@@ -77,6 +80,7 @@ void test_bad_x_server()
     dm.session.conf_use_pam = false;
     dm.session.conf_cleanup_xse = false;
     dm.session.conf_run_as[0] = 0;
+    dm.vt.conf_initial_vt = -1;
     dm.session.child_body = test_session;
 
     ensure_equali(nodm_display_manager_start(&dm), E_X_SERVER_DIED);
@@ -101,10 +105,13 @@ void test_failing_x_session()
     dm.session.conf_use_pam = false;
     dm.session.conf_cleanup_xse = false;
     dm.session.conf_run_as[0] = 0;
+    dm.vt.conf_initial_vt = -1;
     dm.session.child_body = test_session_bad;
 
     ensure_succeeds(nodm_display_manager_start(&dm));
-    ensure_succeeds(nodm_display_manager_wait(&dm));
+    int sstatus;
+    ensure_succeeds(nodm_display_manager_wait(&dm, &sstatus));
+    ensure_equali(sstatus, E_SUCCESS);
     ensure_succeeds(nodm_display_manager_stop(&dm));
     nodm_display_manager_cleanup(&dm);
 }
@@ -118,10 +125,13 @@ void test_dying_x_server()
     dm.session.conf_use_pam = false;
     dm.session.conf_cleanup_xse = false;
     dm.session.conf_run_as[0] = 0;
+    dm.vt.conf_initial_vt = -1;
     dm.session.child_body = test_session_x_killer;
 
     ensure_succeeds(nodm_display_manager_start(&dm));
-    ensure_succeeds(nodm_display_manager_wait(&dm));
+    int sstatus;
+    ensure_succeeds(nodm_display_manager_wait(&dm, &sstatus));
+    ensure_equali(sstatus, E_SUCCESS);
     ensure_succeeds(nodm_display_manager_stop(&dm));
     nodm_display_manager_cleanup(&dm);
 }
diff --git a/vt.c b/vt.c
new file mode 100644
index 0000000..b82f201
--- /dev/null
+++ b/vt.c
@@ -0,0 +1,116 @@
+/*
+ * vt - VT allocation
+ *
+ * Copyright 2009--2011  Enrico Zini <enrico at enricozini.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "vt.h"
+#include "common.h"
+#include "log.h"
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/vt.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/**
+ * Issue a VT_GETSTATE ioctl on the given device, if it supports it.
+ *
+ * @return true if it succeeded, false otherwise
+ */
+static bool try_vtstate(const char* dev, struct vt_stat* vtstat)
+{
+    bool res = false;
+    int fd = open(dev, O_WRONLY | O_NOCTTY, 0);
+    if (fd < 0)
+        goto cleanup;
+    if (ioctl (fd, VT_GETSTATE, vtstat) < 0)
+        goto cleanup;
+    res = true;
+
+cleanup:
+    if (fd >= 0) close(fd);
+    return res;
+}
+
+// Find a device that supports the VT_GETSTATE ioctl
+static bool get_vtstate(struct vt_stat* vtstat)
+{
+    if (try_vtstate("/dev/tty", vtstat)) return true;
+    if (try_vtstate("/dev/tty0", vtstat)) return true;
+    if (try_vtstate("/dev/console", vtstat)) return true;
+    return false;
+}
+
+void nodm_vt_init(struct nodm_vt* vt)
+{
+    vt->conf_initial_vt = strtol(getenv_with_default("NODM_FIRST_VT", "7"), NULL, 10);
+    vt->fd = -1;
+    vt->num = -1;
+}
+
+int nodm_vt_start(struct nodm_vt* vt)
+{
+    if (vt->conf_initial_vt == -1)
+        return E_SUCCESS;
+
+    int vtnum = vt->conf_initial_vt;
+
+    struct vt_stat vtstat;
+    if (!get_vtstate(&vtstat))
+    {
+        log_err("cannot find or open the console");
+        return E_VT_ALLOC_ERROR;
+    }
+
+    unsigned short vtmask;
+    for (vtmask = 1 << vtnum; vtstat.v_state & vtmask; ++vtnum, vtmask <<= 1)
+        ;
+    if (!vtmask)
+    {
+        log_err("all VTs seem to be busy");
+        return E_VT_ALLOC_ERROR;
+    }
+
+    char vtname[15];
+    snprintf(vtname, 15, "/dev/tty%d", vtnum);
+
+    vt->fd = open(vtname, O_RDWR | O_NOCTTY, 0);
+    if (vt->fd < 0)
+    {
+        log_err("cannot open %s: %m", vtname);
+        return E_OS_ERROR;
+    }
+
+    vt->num = vtnum;
+
+    return E_SUCCESS;
+}
+
+void nodm_vt_stop(struct nodm_vt* vt)
+{
+    if (vt->fd != -1)
+    {
+        close(vt->fd);
+        vt->fd = -1;
+        vt->num = -1;
+    }
+}
diff --git a/vt.h b/vt.h
new file mode 100644
index 0000000..a397274
--- /dev/null
+++ b/vt.h
@@ -0,0 +1,48 @@
+/*
+ * vt - VT allocation
+ *
+ * Copyright 2009--2011  Enrico Zini <enrico at enricozini.org>
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef NODM_VT_H
+#define NODM_VT_H
+
+/// VT allocation state
+struct nodm_vt
+{
+    /**
+     * First VT to try to allocate. -1 means 'no VT allocation'
+     */
+    int conf_initial_vt;
+
+    /// Number of the VT that has been allocated (-1 for none)
+    int num;
+
+    /// File decriptor pointing to the open VT (-1 for none)
+    int fd;
+};
+
+/// Initialise a vt structure with default values
+void nodm_vt_init(struct nodm_vt* vt);
+
+/// Allocate a virtual terminal and keep it open
+int nodm_vt_start(struct nodm_vt* vt);
+
+/// Release the virtual terminal
+void nodm_vt_stop(struct nodm_vt* vt);
+
+#endif
diff --git a/xsession-child.c b/xsession-child.c
index f5ef518..b472e43 100644
--- a/xsession-child.c
+++ b/xsession-child.c
@@ -1,7 +1,7 @@
 /*
  * xsession-child - child side of X session
  *
- * Copyright 2011  Enrico Zini <enrico at enricozini.org>
+ * Copyright 2009--2011  Enrico Zini <enrico at enricozini.org>
  *
  * 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
@@ -17,6 +17,53 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+/*
+ * Some parts are taken from su(1) which is:
+ * Copyright 1989 - 1994, Julianne Frances Haugh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * With some parts substantially derived from an ancestor of:
+ * su for GNU.  Run a shell with substitute user and group IDs.
+ * Copyright (C) 1992-2003 Free Software Foundation, Inc.
+ *
+ * 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, 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.
+ */
 
 #include "xsession-child.h"
 #include "xserver.h"

-- 
Automatic Display Manager



More information about the pkg-fso-commits mailing list