[PATCH 4/8] Check virtual console for UTF-8 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Check out a virtual console line for UTF-8 support, also skip
modem specific setups on a virtual console line.

Signed-off-by: Werner Fink <werner@xxxxxxx>
---
 term-utils/agetty.c |  121 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 112 insertions(+), 9 deletions(-)

diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index 6ce7abd..3836ea1 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -38,6 +38,7 @@
 #include "xalloc.h"
 
 #ifdef __linux__
+#  include <sys/kd.h>
 #  include <sys/param.h>
 #  define USE_SYSLOG
 #  ifndef DEFAULT_VCTERM
@@ -150,6 +151,7 @@ struct options {
 #define F_EIGHTBITS	(1<<11)	/* Assume 8bit-clean tty */
 #define F_VCONSOLE	(1<<12)	/* This is a virtual console */
 #define F_NOHANGUP	(1<<13)	/* No not call vhangup(2) */
+#define F_UTF8		(1<<14)	/* We can do UTF8 */
 
 /* Storage for things detected while the login name was read. */
 struct chardata {
@@ -220,6 +222,7 @@ static void parse_speeds(struct options *op, char *arg);
 static void update_utmp(struct options *op);
 static void open_tty(char *tty, struct termios *tp, struct options *op);
 static void termio_init(struct options *op, struct termios *tp);
+static void reset_vc (const struct options *op);
 static void auto_baud(struct termios *tp);
 static void output_special_char (unsigned char c, struct options *op, struct termios *tp);
 static void do_prompt(struct options *op, struct termios *tp);
@@ -307,20 +310,20 @@ int main(int argc, char **argv)
 	termio_init(&options, &termios);
 
 	/* Write the modem init string and DO NOT flush the buffers. */
-	if (options.flags & F_INITSTRING) {
+	if ((options.flags & (F_VCONSOLE|F_INITSTRING)) == F_INITSTRING) {
 		debug("writing init string\n");
 		safe_write(STDIN_FILENO, options.initstring,
 			   strlen(options.initstring));
 	}
 
-	if (!(options.flags & F_LOCAL))
+	if ((options.flags & (F_VCONSOLE|F_LOCAL)) == F_VCONSOLE)
 		/* Go to blocking write mode unless -L is specified. */
 		fcntl(STDOUT_FILENO, F_SETFL,
 		      fcntl(STDOUT_FILENO, F_GETFL, 0) & ~O_NONBLOCK);
 
 	/* Optionally detect the baud rate from the modem status message. */
 	debug("before autobaud\n");
-	if (options.flags & F_PARSE)
+	if ((options.flags & (F_VCONSOLE|F_PARSE)) == F_PARSE)
 		auto_baud(&termios);
 
 	/* Set the optional timer. */
@@ -328,7 +331,7 @@ int main(int argc, char **argv)
 		alarm((unsigned)options.timeout);
 
 	/* Optionally wait for CR or LF before writing /etc/issue */
-	if (options.flags & F_WAITCRLF) {
+	if ((options.flags & (F_VCONSOLE|F_WAITCRLF)) == F_WAITCRLF) {
 		char ch;
 
 		debug("waiting for cr-lf\n");
@@ -349,18 +352,22 @@ int main(int argc, char **argv)
 		debug("reading login name\n");
 		while ((logname =
 			get_logname(&options, &termios, &chardata)) == 0)
-			next_speed(&options, &termios);
+			if ((options.flags & F_VCONSOLE) == 0) {
+				next_speed(&options, &termios);
+			}
 	}
 
 	/* Disable timer. */
 	if (options.timeout)
 		alarm(0);
 
-	/* Finalize the termios settings. */
-	termio_final(&options, &termios, &chardata);
+	if ((options.flags & F_VCONSOLE) == 0) {
+		/* Finalize the termios settings. */
+		termio_final(&options, &termios, &chardata);
 
-	/* Now the newline character should be properly written. */
-	safe_write(STDOUT_FILENO, "\n", 1);
+		/* Now the newline character should be properly written. */
+		safe_write(STDOUT_FILENO, "\r\n", 1);
+	}
 
 	/* Let the login program take care of password validation. */
 	execl(options.login, options.login, "--", logname, NULL);
@@ -785,6 +792,34 @@ static void termio_init(struct options *op, struct termios *tp)
 {
 	speed_t ispeed, ospeed;
 
+	if (op->flags & F_VCONSOLE) {
+#ifdef IUTF8
+		int mode;
+
+		/* Detect mode of current keyboard setup, e.g. for UTF-8 */
+		if (ioctl(0, KDGKBMODE, &mode) < 0)
+			mode = K_RAW;
+		switch(mode) {
+		case K_UNICODE:
+			setlocale(LC_CTYPE, "en_US.UTF-8");
+			op->flags |= F_UTF8;
+			break;
+		case K_RAW:
+		case K_MEDIUMRAW:
+		case K_XLATE:
+		default:
+			setlocale(LC_CTYPE, "POSIX");
+			op->flags &= ~F_UTF8;
+			break;
+		}
+#else
+		setlocale(LC_CTYPE, "POSIX");
+		op->flags &= ~F_UTF8;
+#endif
+		reset_vc(op);
+		return;
+	}
+
 	if (op->flags & F_KEEPSPEED) {
 		/* Save the original setting. */
 		ispeed = cfgetispeed(tp);
@@ -838,6 +873,74 @@ static void termio_init(struct options *op, struct termios *tp)
 	debug("term_io 2\n");
 }
 
+/* Reset virtual console on stdin to its defaults */
+static void reset_vc(const struct options *op)
+{
+	struct termios termios;
+	/*
+	 * The above reset only puts the output things into a sane state.
+	 * The input state is not reset.
+	 */
+	memset (&termios, 0, sizeof termios);
+	if (tcgetattr (0, &termios))
+		warn ("tcgetattr problem: %m");
+
+	/* Use defaults of <sys/ttydefaults.h> for base settings */
+	termios.c_iflag |= TTYDEF_IFLAG;
+	termios.c_oflag |= TTYDEF_OFLAG;
+	termios.c_lflag |= TTYDEF_LFLAG;
+#ifdef CBAUD
+	termios.c_lflag &= ~CBAUD;
+#endif
+	termios.c_cflag |= (B38400 | TTYDEF_CFLAG);
+
+	/* Sane setting, allow eight bit characters, no carriage return delay
+	 * the same result as `stty sane cr0 pass8'
+	 */
+	termios.c_iflag |=  (BRKINT | ICRNL | IMAXBEL);
+	termios.c_iflag &= ~(IGNBRK | INLCR | IGNCR | IXOFF | IUCLC | IXANY | ISTRIP);
+	termios.c_oflag |=  (OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0);
+	termios.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |\
+			    NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
+	termios.c_lflag |=  (ISIG | ICANON | IEXTEN | ECHO|ECHOE|ECHOK|ECHOKE);
+	termios.c_lflag &= ~(ECHONL|ECHOCTL|ECHOPRT | NOFLSH | XCASE | TOSTOP);
+	termios.c_cflag |=  (CREAD | CS8 | HUPCL);
+	termios.c_cflag &= ~(PARODD | PARENB);
+#ifdef IUTF8
+	if (op->flags & F_UTF8)
+		termios.c_iflag |= IUTF8;	    /* Set UTF-8 input flag */
+	else
+		termios.c_iflag &= ~IUTF8;
+#endif
+	/* VTIME and VMIN can overlap with VEOF and VEOL since they are
+	 * only used for non-canonical mode. We just set the at the
+	 * beginning, so nothing bad should happen.
+	 */
+	termios.c_cc[VTIME]    = 0;
+	termios.c_cc[VMIN]     = 1;
+	termios.c_cc[VINTR]    = CINTR;
+	termios.c_cc[VQUIT]    = CQUIT;
+	termios.c_cc[VERASE]   = CERASE; /* ASCII DEL (0177) */
+	termios.c_cc[VKILL]    = CKILL;
+	termios.c_cc[VEOF]     = CEOF;
+#ifdef VSWTC
+	termios.c_cc[VSWTC]    = _POSIX_VDISABLE;
+#else
+	termios.c_cc[VSWTCH]   = _POSIX_VDISABLE;
+#endif
+	termios.c_cc[VSTART]   = CSTART;
+	termios.c_cc[VSTOP]    = CSTOP;
+	termios.c_cc[VSUSP]    = CSUSP;
+	termios.c_cc[VEOL]     = _POSIX_VDISABLE;
+	termios.c_cc[VREPRINT] = CREPRINT;
+	termios.c_cc[VDISCARD] = CDISCARD;
+	termios.c_cc[VWERASE]  = CWERASE;
+	termios.c_cc[VLNEXT]   = CLNEXT;
+	termios.c_cc[VEOL2]    = _POSIX_VDISABLE;
+	if (tcsetattr (0, TCSADRAIN, &termios))
+		warn ("tcsetattr problem: %m");
+}
+
 /* Extract baud rate from modem status message. */
 static void auto_baud(struct termios *tp)
 {
-- 
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux