With regard to the /dev/pts issue on "vserver <name> enter" i have ported the 
vlogin application from vserver-utils to util-vserver-0.30.210

See also http://list.linux-vserver.org/archive/vserver/msg12117.html

Bene
diff -NurpP util-vserver-0.30.210/scripts/Makefile-files util-vserver-0.30.210-vlogin/scripts/Makefile-files
--- util-vserver-0.30.210/scripts/Makefile-files	2005-04-28 19:45:34.000000000 +0200
+++ util-vserver-0.30.210-vlogin/scripts/Makefile-files	2006-03-04 09:48:30.000000000 +0100
@@ -52,7 +52,8 @@ scripts_pkglib_src_DTA =	scripts/functio
 				scripts/vserver.functions \
 				scripts/vserver.start \
 				scripts/vserver.stop \
-				scripts/vserver.suexec
+				scripts/vserver.suexec \
+				scripts/vserver.login
 
 scripts_pkglib_gen_DTA =	scripts/util-vserver-vars
 
diff -NurpP util-vserver-0.30.210/scripts/util-vserver-vars.pathsubst util-vserver-0.30.210-vlogin/scripts/util-vserver-vars.pathsubst
--- util-vserver-0.30.210/scripts/util-vserver-vars.pathsubst	2006-01-22 13:24:25.000000000 +0100
+++ util-vserver-0.30.210-vlogin/scripts/util-vserver-vars.pathsubst	2006-03-04 09:55:46.000000000 +0100
@@ -72,6 +72,7 @@ _VDU="$__SBINDIR/vdu"
 _VHASHIFY="$__PKGLIBDIR/vhashify"
 _VKILL="$__SBINDIR/vkill"
 _VLIMIT="$__SBINDIR/vlimit"
+_VLOGIN="$__SBINDIR/vlogin"
 _VNAMESPACE="$__SBINDIR/vnamespace"
 _VPKG="$__PKGLIBDIR/vpkg"
 _VPROCUNHIDE="$__PKGLIBDIR/vprocunhide"
diff -NurpP util-vserver-0.30.210/scripts/vserver util-vserver-0.30.210-vlogin/scripts/vserver
--- util-vserver-0.30.210/scripts/vserver	2005-10-28 20:29:00.000000000 +0200
+++ util-vserver-0.30.210-vlogin/scripts/vserver	2006-03-04 09:47:52.000000000 +0100
@@ -101,6 +101,11 @@ function suexec()
     . $__PKGLIBDIR/vserver.suexec
 }
 
+function vlogin()
+{
+    . $__PKGLIBDIR/vserver.login
+}
+
 function restart()
 {
     "[EMAIL PROTECTED]" --sync "$vserver" stop
@@ -220,7 +225,7 @@ case "$2" in
 	;;
     (enter)
 	getEnterShell "$VSERVER_DIR"
-	suexec root "[EMAIL PROTECTED]"
+	vlogin "[EMAIL PROTECTED]"
 	;;
     (running)
 	isVserverRunning "$VSERVER_DIR"
diff -NurpP util-vserver-0.30.210/scripts/vserver.login util-vserver-0.30.210-vlogin/scripts/vserver.login
--- util-vserver-0.30.210/scripts/vserver.login	1970-01-01 01:00:00.000000000 +0100
+++ util-vserver-0.30.210-vlogin/scripts/vserver.login	2006-03-04 09:46:19.000000000 +0100
@@ -0,0 +1,32 @@
+# $Id: vserver.suexec,v 1.14 2005/07/15 19:01:06 ensc Exp $  --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <[EMAIL PROTECTED]>
+#  
+# 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; version 2 of the License.
+#  
+# 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.
+
+is_stopped=
+isVserverRunning "$VSERVER_DIR" S_CONTEXT || is_stopped=1
+test -z "$is_stopped" || {
+    echo $"'vserver ... suexec' is supported for running vservers only; aborting..." >&2
+    exit 1
+}
+
+generateOptions  "$VSERVER_DIR"
+
+pushd "$VSERVER_DIR"/vdir/ >/dev/null
+
+${USE_VNAMESPACE:+$_VNAMESPACE --enter "$S_CONTEXT" -- } \
+${_VLOGIN} -n ${S_CONTEXT} -x ${S_CONTEXT} -- "$@"
+
+popd >/dev/null
diff -NurpP util-vserver-0.30.210/src/Makefile-files util-vserver-0.30.210-vlogin/src/Makefile-files
--- util-vserver-0.30.210/src/Makefile-files	2006-01-22 12:28:00.000000000 +0100
+++ util-vserver-0.30.210-vlogin/src/Makefile-files	2006-03-04 09:34:00.000000000 +0100
@@ -67,6 +67,7 @@ DIETPROGS +=		src/chcontext-compat \
 			src/vcontext \
 			src/vcopy \
 			src/vkill \
+			src/vlogin \
 			src/vsched \
 			src/vshelper-sync \
 			src/vrsetup \
@@ -141,6 +142,7 @@ sbin_PROGRAMS +=	src/chbind \
 			src/vcontext \
 			src/vlimit \
 			src/vkill \
+			src/vlogin \
 			src/vnamespace \
 			src/vrsetup \
 			src/vsched \
@@ -201,6 +203,10 @@ src_vkill_LDADD			=  $(VSERVER_LDADDS)
 src_vkill_LDFLAGS		=  $(VSERVER_LDFLGS)
 src_vkill_CPPFLAGS		=  $(AM_CPPFLAGS) -DLEGACYDIR=\"$(legacydir)\"
 
+src_vlogin_SOURCES		=  src/vlogin.c
+src_vlogin_LDADD			=  $(VSERVER_LDADDS)
+src_vlogin_LDFLAGS		=  $(VSERVER_LDFLGS)
+
 src_vlimit_SOURCES		=  src/vlimit.c
 src_vlimit_LDADD		=  $(VSERVER_LDADDS)
 src_vlimit_LDFLAGS		=  $(VSERVER_LDFLGS)
diff -NurpP util-vserver-0.30.210/src/vlogin.c util-vserver-0.30.210-vlogin/src/vlogin.c
--- util-vserver-0.30.210/src/vlogin.c	1970-01-01 01:00:00.000000000 +0100
+++ util-vserver-0.30.210-vlogin/src/vlogin.c	2006-03-04 09:56:27.000000000 +0100
@@ -0,0 +1,450 @@
+/***************************************************************************
+ *   Copyright 2005 by the vserver-utils team                              *
+ *   See AUTHORS for details                                               *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <string.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pty.h>
+
+#include "vserver.h"
+
+#define GLOBAL_CMDS "hV"
+
+#define GLOBAL_CMDS_GETOPT \
+case 'h': \
+	cmd_help(); \
+	break; \
+\
+case 'V': \
+	CMD_VERSION(NAME, DESCR); \
+	break; \
+
+#define DEFAULT_GETOPT \
+default: \
+	printf("Try '%s -h' for more information\n", argv[0]); \
+	exit(EXIT_USAGE); \
+	break; \
+
+
+#define CMD_VERSION(name, desc) do { \
+	printf("%s -- %s\n", name, desc); \
+	printf("This program is part of %s\n\n", PACKAGE_STRING); \
+	printf("Copyright (c) 2005 The vserver-utils Team\n"); \
+	printf("This program is free software; you can redistribute it and/or\n"); \
+	printf("modify it under the terms of the GNU General Public License\n"); \
+	exit(0); \
+}	while(0)
+
+/* exit, silent exit, perror exit
+ *
+ * exit code conventions:
+ * 
+ * 0 = OK
+ * 1 = Wrong usage
+ * 2 = A command failed
+ * 3 = An opts specific function failed
+ */
+#define EXIT_USAGE   1
+#define EXIT_COMMAND 2
+#define EXIT_OPTS    3
+
+#define EXIT(MSG,RC) { \
+	printf(MSG"; try '%s -h' for more information\n", argv[0]); \
+	exit(RC); \
+}
+
+#define SEXIT(MSG,RC) { \
+	printf(MSG"\n"); \
+	exit(RC); \
+}
+
+#define PEXIT(MSG,RC) { \
+	perror(MSG); \
+	exit(RC); \
+}
+
+#define NAME  "vlogin"
+#define DESCR "Context Login"
+
+#define SHORT_OPTS "n:x:"
+
+struct options {
+	nid_t nid;
+	xid_t xid;
+};
+
+#define TS_RESET 0
+#define TS_RAW   1
+
+struct terminal {
+	int fd;                /* terminal file descriptor */
+	struct termios term;   /* terminal settings */
+	struct winsize ws;     /* terminal size */
+	pid_t pid;             /* terminal process id */
+	struct termios termo;  /* original terminal settings */
+	int state;             /* terminal state */
+};
+
+static struct terminal t;
+
+static inline
+void cmd_help()
+{
+	printf("Usage: %s <opts>* [-- <shell> <args>*]\n"
+	       "\n"
+	       "Available options:\n"
+	       "    -n <xid>      Network Context ID\n"
+	       "    -x <xid>      Context ID\n"
+	       "\n",
+	       NAME);
+	exit(EXIT_SUCCESS);
+}
+
+/* set terminal to raw mode */
+static
+int terminal_raw(void)
+{
+	struct termios buf;
+	
+	/* save original terminal settings */
+	if (tcgetattr(STDIN_FILENO, &t.termo) == -1)
+		return -1;
+	
+	buf = t.termo;
+	
+	/* echo off
+	** canonical mode off
+	** extended input processing off
+	** signal chars off */
+	buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+	
+	/* no SIGINT on BREAK
+	** CR-to-NL off
+	** input parity check off
+	** don't strip 8th bit on input
+	** output flow control off */
+	buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+	
+	/* clear size bits
+	** parity checking off */
+	buf.c_cflag &= ~(CSIZE | PARENB);
+	
+	/* set 8 bits/char */
+	buf.c_cflag |= CS8;
+	
+	/* output processing off */
+	buf.c_oflag &= ~(OPOST);
+	
+	/* 1 byte at a time
+	** no timer */
+	buf.c_cc[VMIN] = 1;
+	buf.c_cc[VTIME] = 0;
+	
+	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &buf) == -1)
+		return -1;
+	
+	t.state = TS_RAW;
+	
+	return 0;
+}
+
+/* reset terminal to original state */
+static
+int terminal_reset(void)
+{
+	if (t.state != TS_RAW)
+		return 0;
+	
+	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t.termo) == -1)
+		return -1;
+	
+	t.state = TS_RESET;
+	
+	return 0;
+}
+
+/* exit handler */
+static
+void terminal_atexit(void)
+{
+	terminal_reset();
+	printf("\n"); /* for cosmetic reasons */
+}
+
+/* send signal to terminal */
+static
+void terminal_kill(int sig)
+{
+	pid_t pgrp = -1;
+	
+	/* try to get process group leader */
+	if (ioctl(t.fd, TIOCGPGRP, &pgrp) >= 0 &&
+	    pgrp != -1 &&
+	    kill(-pgrp, sig) != -1)
+		return;
+	
+	/* fallback using terminal pid */
+	kill(-t.pid, sig);
+}
+
+/* redraw the terminal screen */
+static
+void terminal_redraw(void)
+{
+	/* get winsize from stdin */
+	ioctl(0, TIOCGWINSZ, &t.ws);
+	
+	/* set winsize in terminal */
+	ioctl(t.fd, TIOCSWINSZ, &t.ws);
+	
+	/* set winsize change signal to terminal */
+	terminal_kill(SIGWINCH);
+}
+
+/* copy terminal activity to user */
+static
+void terminal_activity(void)
+{
+	char buf[64];
+	int len;
+	
+	/* read terminal activity */
+	len = read(t.fd, buf, sizeof(buf));
+	
+	/* terminal died or strange things happened */
+	if (len == -1)
+		PEXIT("Failed to read from terminal", EXIT_COMMAND);
+	
+	/* get the current terminal settings */
+	if (tcgetattr(t.fd, &t.term) == -1)
+		PEXIT("Failed to get terminal attributes", EXIT_COMMAND);
+	
+	/* set the current terminal settings */
+	if (tcsetattr(STDIN_FILENO, TCSANOW, &t.term) == -1)
+		PEXIT("Failed to set terminal attributes", EXIT_COMMAND);
+	
+	/* write activity to user */
+	if (write(STDOUT_FILENO, buf, len) == -1)
+		PEXIT("Failed to write to stdout", EXIT_COMMAND);
+}
+
+/* copy user activity to terminal */
+static
+void user_activity(void)
+{
+	char buf[64];
+	int len;
+	
+	/* read user activity */
+	len = read(STDIN_FILENO, buf, sizeof(buf));
+	
+	/* the user process died or strange thins happened */
+	if (len == -1)
+		PEXIT("Failed to read from stdin", EXIT_COMMAND);
+	
+	/* write activity to terminal */
+	if (write(t.fd, buf, len) == -1)
+		PEXIT("Failed to write to terminal", EXIT_COMMAND);
+}
+
+/* catch signals */
+static
+void signal_handler(int sig)
+{
+	int status;
+	
+	switch(sig) {
+		/* catch interrupt */
+		case SIGINT:
+			terminal_kill(sig);
+			break;
+		
+		/* terminal died */
+		case SIGCHLD:
+			wait(&status);
+			exit(status);
+			break;
+		
+		/* window size has changed */
+		case SIGWINCH:
+			signal(SIGWINCH, signal_handler);
+			terminal_redraw();
+			break;
+		
+		default:
+			exit(0);
+	}
+	
+}
+
+int main(int argc, char *argv[])
+{
+	/* init program data */
+	struct options opts = {
+		.nid = 0,
+		.xid = 0,
+	};
+	
+	int c;
+	
+	/* parse command line */
+	while (1) {
+		c = getopt(argc, argv, GLOBAL_CMDS SHORT_OPTS);
+		if (c == -1) break;
+		
+		switch (c) {
+			GLOBAL_CMDS_GETOPT
+			
+			case 'n':
+				opts.nid = (nid_t) atoi(optarg);
+				break;
+			
+			case 'x':
+				opts.xid = (xid_t) atoi(optarg);
+				break;
+			
+			DEFAULT_GETOPT
+		}
+	}
+	
+	if (opts.xid == 0)
+		EXIT("Invalid xid", EXIT_USAGE);
+	
+	/* enter context */
+	if (opts.nid > 1 && vc_net_migrate(opts.nid) == -1)
+		PEXIT("Failed to migrate to network context", EXIT_COMMAND);
+	
+	if (vc_ctx_migrate(opts.xid) == -1)
+		PEXIT("Failed to migrate to context", EXIT_COMMAND);
+	
+	/* set terminal to raw mode */
+	atexit(terminal_atexit);
+	if (terminal_raw() == -1)
+		PEXIT("Failed to set terminal to raw mode", EXIT_COMMAND);
+	
+	/* fork new pseudo terminal */
+	int slave;
+	
+	if (openpty(&t.fd, &slave, NULL, NULL, NULL) == -1)
+		PEXIT("Failed to open new pseudo terminal", EXIT_COMMAND);
+	
+	/* chroot to cwd */
+	if (chdir(".") == -1)
+		PEXIT("Failed to chdir to cwd", EXIT_COMMAND);
+	
+	if (chroot(".") == -1)
+		PEXIT("Failed to chroot to cwd", EXIT_COMMAND);
+	
+	pid_t pid;
+	pid = fork();
+	
+	/* setup some signal handlers */
+	signal(SIGINT, signal_handler);
+	signal(SIGCHLD, signal_handler);
+	signal(SIGWINCH, signal_handler);
+	
+	if (pid == -1)
+		PEXIT("Failed to fork new pseudo terminal", EXIT_COMMAND);
+	
+	if (pid == 0) {
+		/* we don't need the master side of the terminal */
+		close(t.fd);
+		
+		/* login_tty() stupid dietlibc doesn't have it */
+		setsid();
+		
+		if (ioctl(slave, TIOCSCTTY, NULL) == -1)
+			PEXIT("Failed to set controlling terminal", EXIT_COMMAND);
+		
+		dup2(slave, 0);
+		dup2(slave, 1);
+		dup2(slave, 2);
+		
+		if (slave > 2)
+			close(slave);
+		
+		/* check shell */
+		if (argc > optind) {
+			if (execv(argv[optind], argv+optind) == -1) {
+				PEXIT("Failed to execute shell", EXIT_COMMAND);
+			}
+		}
+		else {
+			if (execl("/bin/sh", "/bin/sh", "-l", NULL) == -1) {
+				PEXIT("Failed to execute default shell", EXIT_COMMAND);
+			}
+		}
+	}
+	
+	/* save terminals pid */
+	t.pid = pid;
+	
+	/* set process title for ps */
+	int i, len;
+	
+	for (i = 1; i < argc; i++) {
+		memset(argv[i], '\0', strlen(argv[i]));
+	}
+	
+	len = strlen(argv[0]);
+	memset(argv[0], '\0', len);
+	strncpy(argv[0], "VLOGIN", len);
+	
+	/* we want a redraw */
+	terminal_redraw();
+	
+	/* main loop */
+	fd_set rfds;
+	int n = 0;
+	
+	for(;;) {
+		/* init file descriptors for select */
+		FD_ZERO(&rfds);
+		FD_SET(STDIN_FILENO, &rfds);
+		FD_SET(t.fd, &rfds);
+		n = t.fd;
+		
+		/* wait for something to happen */
+		while (select(n + 1, &rfds, NULL, NULL, NULL) == -1) {
+			if (errno == EINTR || errno == EAGAIN) continue;
+			PEXIT("Failed to select", EXIT_COMMAND);
+		}
+		
+		if (FD_ISSET(STDIN_FILENO, &rfds))
+			user_activity();
+		
+		if (FD_ISSET(t.fd, &rfds))
+			terminal_activity();
+	}
+	
+	/* never get here */
+	return -1;
+}
_______________________________________________
Vserver mailing list
Vserver@list.linux-vserver.org
http://list.linux-vserver.org/mailman/listinfo/vserver

Reply via email to