summarylogtreecommitdiffstats
path: root/mingetty-utf8.patch
blob: c269039ac3e8774d5649503bf2aef0aac67347e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
diff -Nru mingetty-1.07.orig/mingetty.c mingetty-1.07/mingetty.c
--- mingetty-1.07.orig/mingetty.c	2004-01-03 15:15:56.000000000 +0200
+++ mingetty-1.07/mingetty.c	2006-11-22 22:13:26.967910100 +0200
@@ -16,10 +16,15 @@
  * - autologin only at first login
  * - /etc/mingetty.conf that can be used instead of /etc/inittab for
  *   command line options
- * - Can UTF-8 setup be done within mingetty?
+ * - Can UTF-8 setup be done within mingetty? Let's try now :-) (VinzC)
  * - Also add /bin/login-type functionality in here?
  */
 
+/* Additional comments: Vincent Cadet <vcadet@hotmail.com> (2006-11-21)
+ * - Attempt to make mingetty support UTF-8. Modifications were imported
+ *   from Suse migetty.c 0.9.6s.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -39,6 +44,19 @@
 #include <syslog.h>
 #include <sys/utsname.h>
 #include <time.h>
+#include <locale.h>
+#include <iconv.h>
+#include <wctype.h>
+#include <sys/kd.h>
+#include <sys/ttydefaults.h>
+
+#ifndef IUTF8
+# ifndef ASM_IUTF8
+#  error ASM_IUTF8 input flag not defined - Cannot define IUTF8
+# else
+#  define IUTF8	ASM_IUTF8
+# endif
+#endif
 
 /* name of this program (argv[0]) */
 static char *progname;
@@ -74,6 +92,8 @@
 static char *autologin = NULL;
 /* try to read a char before dropping to login prompt */
 static int loginpause = 0;
+/* terminal mode */
+static int mode = K_RAW;
 
 /* error() - output error messages */
 static void error (const char *fmt, ...)
@@ -187,10 +207,21 @@
 	if (fd > 2)
 		close (fd);
 
+	/* Detect mode of current keyboard setup, e.g. for UTF-8 */
+	if (ioctl(0, KDGKBMODE, &mode) < 0)
+		mode = K_RAW;
+
 	/* Write a reset string to the terminal. This is very linux-specific
 	   and should be checked for other systems. */
 	if (noclear == 0)
-		write (0, "\033c", 2);
+		/* don't write a full reset (ESC c) because this leaves the 
+		   unicode mode again if the terminal was in unicode mode
+		   and also undos the ESC sequences in CONSOLE_MAGIC which
+		   are needed for some languages/console-fonts.
+		   Just put the cursor to the home position (ESC [ H),
+		   erase everything below the cursor (ESC [ J), and set the
+		   scrolling region to the full window (ESC [ r) */
+		write (0, "\033[r\033[H\033[J", 9);
 
 	sigaction (SIGHUP, &sa_old, NULL);
 }
@@ -292,32 +323,75 @@
 
 static char *get_logname (void)
 {
-	static char logname[40];
+	static char logname[4*UT_NAMESIZE];
 	char *bp;
 	unsigned char c;
+	int ascii;
+	iconv_t ic;
 
 	tcflush (0, TCIFLUSH);		/* flush pending input */
+
+	/* Check for UTF-8 mode */
+	switch(mode) {
+		case K_UNICODE:
+			ascii = 0;
+			setlocale(LC_CTYPE, "en_US.UTF-8");
+			break;
+		case K_RAW:
+		case K_MEDIUMRAW:
+		case K_XLATE:
+		default:
+			ascii = 1;
+			setlocale(LC_CTYPE, "POSIX");
+			break;
+	}
+
 	for (*logname = 0; *logname == 0;) {
 		do_prompt (1);
 		for (bp = logname;;) {
 			if (read (0, &c, 1) < 1) {
-				if (errno == EINTR || errno == EIO
-					|| errno == ENOENT)
+				if (errno == EINTR || errno == EAGAIN) {
+					usleep(1000);
+					continue;
+				}
+				if (errno == EIO || errno == ENOENT)
 					exit (EXIT_SUCCESS);
 				error ("%s: read: %s", tty, strerror (errno));
 			}
 			if (c == '\n' || c == '\r') {
 				*bp = 0;
 				break;
-			} else if (!isprint (c))
-				error ("%s: invalid character 0x%x in login"
-					" name", tty, c);
+			}
+
+			if (ascii && !isprint (c))
+				error ("%s: invalid character 0x%x in login name", tty, c);
 			else if ((size_t)(bp - logname) >= sizeof (logname) - 1)
 				error ("%s: too long login name", tty);
-			else
-				*bp++ = c;
+
+			*bp++ = c;
 		}
 	}
+
+	if (!ascii && (ic = iconv_open("WCHAR_T", "UTF-8"))) {
+		char tmpbuf[4*sizeof(logname)], *op, *lp;
+		size_t len = bp - logname;
+		size_t out = sizeof(tmpbuf) - 1;
+		size_t wcl;
+		wint_t *wcp;
+
+		op = tmpbuf;
+		lp = logname;
+		if ((wcl = iconv(ic , &lp, &len, &op, &out)) == (size_t)-1)
+			error ("%s: invalid character conversion for login name", tty);
+		iconv_close(ic);
+
+		wcp = (wint_t*)tmpbuf;
+		wcp[wcl] = (wint_t)0;
+		while (*wcp) {
+			if (!iswprint(*wcp++))
+				error ("%s: invalid character for login name found", tty);
+ 		}
+ 	}
 	return logname;
 }