xref: /illumos-gate/usr/src/uts/common/io/ldterm.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /* All Rights Reserved					*/
28 
29 /*
30  * University Copyright- Copyright (c) 1982, 1986, 1988
31  * The Regents of the University of California
32  * All Rights Reserved
33  *
34  * University Acknowledgment- Portions of this document are derived from
35  * software developed by the University of California, Berkeley, and its
36  * contributors.
37  */
38 
39 #pragma ident	"%Z%%M%	%I%	%E% SMI"
40 
41 /*
42  * Standard Streams Terminal Line Discipline module.
43  */
44 
45 #include <sys/param.h>
46 #include <sys/types.h>
47 #include <sys/termio.h>
48 #include <sys/stream.h>
49 #include <sys/conf.h>
50 #include <sys/stropts.h>
51 #include <sys/strsubr.h>
52 #include <sys/strsun.h>
53 #include <sys/strtty.h>
54 #include <sys/signal.h>
55 #include <sys/file.h>
56 #include <sys/errno.h>
57 #include <sys/debug.h>
58 #include <sys/cmn_err.h>
59 #include <sys/euc.h>
60 #include <sys/eucioctl.h>
61 #include <sys/csiioctl.h>
62 #include <sys/ptms.h>
63 #include <sys/ldterm.h>
64 #include <sys/cred.h>
65 #include <sys/ddi.h>
66 #include <sys/sunddi.h>
67 #include <sys/kmem.h>
68 #include <sys/modctl.h>
69 
70 /* Time limit when draining during a close(9E) invoked by exit(2) */
71 /* Can be set to zero to emulate the old, broken behavior */
72 int ldterm_drain_limit = 15000000;
73 
74 /*
75  * Character types.
76  */
77 #define	ORDINARY	0
78 #define	CONTROL		1
79 #define	BACKSPACE	2
80 #define	NEWLINE		3
81 #define	TAB		4
82 #define	VTAB		5
83 #define	RETURN		6
84 
85 /*
86  * The following for EUC handling:
87  */
88 #define	T_SS2		7
89 #define	T_SS3		8
90 
91 /*
92  * Table indicating character classes to tty driver.  In particular,
93  * if the class is ORDINARY, then the character needs no special
94  * processing on output.
95  *
96  * Characters in the C1 set are all considered CONTROL; this will
97  * work with terminals that properly use the ANSI/ISO extensions,
98  * but might cause distress with terminals that put graphics in
99  * the range 0200-0237.  On the other hand, characters in that
100  * range cause even greater distress to other UNIX terminal drivers....
101  */
102 
103 static char typetab[256] = {
104 /* 000 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
105 /* 004 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
106 /* 010 */	BACKSPACE,	TAB,		NEWLINE,	CONTROL,
107 /* 014 */	VTAB,		RETURN,		CONTROL,	CONTROL,
108 /* 020 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
109 /* 024 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
110 /* 030 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
111 /* 034 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
112 /* 040 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
113 /* 044 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
114 /* 050 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
115 /* 054 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
116 /* 060 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
117 /* 064 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
118 /* 070 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
119 /* 074 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
120 /* 100 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
121 /* 104 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
122 /* 110 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
123 /* 114 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
124 /* 120 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
125 /* 124 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
126 /* 130 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
127 /* 134 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
128 /* 140 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
129 /* 144 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
130 /* 150 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
131 /* 154 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
132 /* 160 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
133 /* 164 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
134 /* 170 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
135 /* 174 */	ORDINARY,	ORDINARY,	ORDINARY,	CONTROL,
136 /* 200 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
137 /* 204 */	CONTROL,	CONTROL,	T_SS2,		T_SS3,
138 /* 210 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
139 /* 214 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
140 /* 220 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
141 /* 224 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
142 /* 230 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
143 /* 234 */	CONTROL,	CONTROL,	CONTROL,	CONTROL,
144 /* 240 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
145 /* 244 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
146 /* 250 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
147 /* 254 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
148 /* 260 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
149 /* 264 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
150 /* 270 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
151 /* 274 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
152 /* 300 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
153 /* 304 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
154 /* 310 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
155 /* 314 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
156 /* 320 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
157 /* 324 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
158 /* 330 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
159 /* 334 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
160 /* 340 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
161 /* 344 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
162 /* 350 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
163 /* 354 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
164 /* 360 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
165 /* 364 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
166 /* 370 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
167 /*
168  * WARNING:  For EUC, 0xFF must be an ordinary character.  It is used with
169  * single-byte EUC in some of the "ISO Latin Alphabet" codesets, and occupies
170  * a screen position; in those ISO sets where that position isn't used, it
171  * shouldn't make any difference.
172  */
173 /* 374 */	ORDINARY,	ORDINARY,	ORDINARY,	ORDINARY,
174 };
175 
176 /*
177  * Translation table for output without OLCUC.  All ORDINARY-class characters
178  * translate to themselves.  All other characters have a zero in the table,
179  * which stops the copying.
180  */
181 static unsigned char notrantab[256] = {
182 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
183 /* 010 */	0,	0,	0,	0,	0,	0,	0,	0,
184 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
185 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
186 /* 040 */	' ',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
187 /* 050 */	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
188 /* 060 */	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
189 /* 070 */	'8',	'9',	':',	';',	'<',	'=',	'>',	'?',
190 /* 100 */	'@',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
191 /* 110 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
192 /* 120 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
193 /* 130 */	'X',	'Y',	'Z',	'[',	'\\',	']',	'^',	'_',
194 /* 140 */	'`',	'a',	'b',	'c',	'd',	'e',	'f',	'g',
195 /* 150 */	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
196 /* 160 */	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
197 /* 170 */	'x',	'y',	'z',	'{',	'|',	'}',	'~',	0,
198 /* 200 */	0,	0,	0,	0,	0,	0,	0,	0,
199 /* 210 */	0,	0,	0,	0,	0,	0,	0,	0,
200 /* 220 */	0,	0,	0,	0,	0,	0,	0,	0,
201 /* 230 */	0,	0,	0,	0,	0,	0,	0,	0,
202 /* 240 */	0240,	0241,	0242,	0243,	0244,	0245,	0246,	0247,
203 /* 250 */	0250,	0251,	0252,	0253,	0254,	0255,	0256,	0257,
204 /* 260 */	0260,	0261,	0262,	0263,	0264,	0265,	0266,	0267,
205 /* 270 */	0270,	0271,	0272,	0273,	0274,	0275,	0276,	0277,
206 /* 300 */	0300,	0301,	0302,	0303,	0304,	0305,	0306,	0307,
207 /* 310 */	0310,	0311,	0312,	0313,	0314,	0315,	0316,	0317,
208 /* 320 */	0320,	0321,	0322,	0323,	0324,	0325,	0326,	0327,
209 /* 330 */	0330,	0331,	0332,	0333,	0334,	0335,	0336,	0337,
210 /* 340 */	0340,	0341,	0342,	0343,	0344,	0345,	0346,	0347,
211 /* 350 */	0350,	0351,	0352,	0353,	0354,	0355,	0356,	0357,
212 /* 360 */	0360,	0361,	0362,	0363,	0364,	0365,	0366,	0367,
213 /*
214  * WARNING: as for above ISO sets, \377 may be used.  Translate it to
215  * itself.
216  */
217 /* 370 */	0370,	0371,	0372,	0373,	0374,	0375,	0376,	0377,
218 };
219 
220 /*
221  * Translation table for output with OLCUC.  All ORDINARY-class characters
222  * translate to themselves, except for lower-case letters which translate
223  * to their upper-case equivalents.  All other characters have a zero in
224  * the table, which stops the copying.
225  */
226 static unsigned char lcuctab[256] = {
227 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
228 /* 010 */	0,	0,	0,	0,	0,	0,	0,	0,
229 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
230 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
231 /* 040 */	' ',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
232 /* 050 */	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
233 /* 060 */	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
234 /* 070 */	'8',	'9',	':',	';',	'<',	'=',	'>',	'?',
235 /* 100 */	'@',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
236 /* 110 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
237 /* 120 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
238 /* 130 */	'X',	'Y',	'Z',	'[',	'\\',	']',	'^',	'_',
239 /* 140 */	'`',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
240 /* 150 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
241 /* 160 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
242 /* 170 */	'X',	'Y',	'Z',	'{',	'|',	'}',	'~',	0,
243 /* 200 */	0,	0,	0,	0,	0,	0,	0,	0,
244 /* 210 */	0,	0,	0,	0,	0,	0,	0,	0,
245 /* 220 */	0,	0,	0,	0,	0,	0,	0,	0,
246 /* 230 */	0,	0,	0,	0,	0,	0,	0,	0,
247 /* 240 */	0240,	0241,	0242,	0243,	0244,	0245,	0246,	0247,
248 /* 250 */	0250,	0251,	0252,	0253,	0254,	0255,	0256,	0257,
249 /* 260 */	0260,	0261,	0262,	0263,	0264,	0265,	0266,	0267,
250 /* 270 */	0270,	0271,	0272,	0273,	0274,	0275,	0276,	0277,
251 /* 300 */	0300,	0301,	0302,	0303,	0304,	0305,	0306,	0307,
252 /* 310 */	0310,	0311,	0312,	0313,	0314,	0315,	0316,	0317,
253 /* 320 */	0320,	0321,	0322,	0323,	0324,	0325,	0326,	0327,
254 /* 330 */	0330,	0331,	0332,	0333,	0334,	0335,	0336,	0337,
255 /* 340 */	0340,	0341,	0342,	0343,	0344,	0345,	0346,	0347,
256 /* 350 */	0350,	0351,	0352,	0353,	0354,	0355,	0356,	0357,
257 /* 360 */	0360,	0361,	0362,	0363,	0364,	0365,	0366,	0367,
258 /*
259  * WARNING: as for above ISO sets, \377 may be used.  Translate it to
260  * itself.
261  */
262 /* 370 */	0370,	0371,	0372,	0373,	0374,	0375,	0376,	0377,
263 };
264 
265 /*
266  * Input mapping table -- if an entry is non-zero, and XCASE is set,
267  * when the corresponding character is typed preceded by "\" the escape
268  * sequence is replaced by the table value.  Mostly used for
269  * upper-case only terminals.
270  */
271 static char	imaptab[256] = {
272 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
273 /* 010 */	0,	0,	0,	0,	0,	0,	0,	0,
274 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
275 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
276 /* 040 */	0,	'|',	0,	0,	0,	0,	0,	'`',
277 /* 050 */	'{',	'}',	0,	0,	0,	0,	0,	0,
278 /* 060 */	0,	0,	0,	0,	0,	0,	0,	0,
279 /* 070 */	0,	0,	0,	0,	0,	0,	0,	0,
280 /* 100 */	0,	0,	0,	0,	0,	0,	0,	0,
281 /* 110 */	0,	0,	0,	0,	0,	0,	0,	0,
282 /* 120 */	0,	0,	0,	0,	0,	0,	0,	0,
283 /* 130 */	0,	0,	0,	0,	'\\',	0,	'~',	0,
284 /* 140 */	0,	'A',	'B',	'C',	'D',	'E',	'F',	'G',
285 /* 150 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
286 /* 160 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
287 /* 170 */	'X',	'Y',	'Z',	0,	0,	0,	0,	0,
288 /* 200-377 aren't mapped */
289 };
290 
291 /*
292  * Output mapping table -- if an entry is non-zero, and XCASE is set,
293  * the corresponding character is printed as "\" followed by the table
294  * value.  Mostly used for upper-case only terminals.
295  */
296 static char	omaptab[256] = {
297 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
298 /* 010 */	0,	0,	0,	0,	0,	0,	0,	0,
299 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
300 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
301 /* 040 */	0,	0,	0,	0,	0,	0,	0,	0,
302 /* 050 */	0,	0,	0,	0,	0,	0,	0,	0,
303 /* 060 */	0,	0,	0,	0,	0,	0,	0,	0,
304 /* 070 */	0,	0,	0,	0,	0,	0,	0,	0,
305 /* 100 */	0,	'A',	'B',	'C',	'D',	'E',	'F',	'G',
306 /* 110 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
307 /* 120 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
308 /* 130 */	'X',	'Y',	'Z',	0,	0,	0,	0,	0,
309 /* 140 */	'\'',	0,	0,	0,	0,	0,	0,	0,
310 /* 150 */	0,	0,	0,	0,	0,	0,	0,	0,
311 /* 160 */	0,	0,	0,	0,	0,	0,	0,	0,
312 /* 170 */	0,	0,	0,	'(',	'!',	')',	'^',	0,
313 /* 200-377 aren't mapped */
314 };
315 
316 /*
317  * Translation table for TS_MEUC output without OLCUC.  All printing ASCII
318  * characters translate to themselves.  All other _bytes_ have a zero in
319  * the table, which stops the copying.  This and the following table exist
320  * only so we can use the existing movtuc processing with or without OLCUC.
321  * Maybe it speeds up something...because we can copy a block of characters
322  * by only looking for zeros in the table.
323  *
324  * If we took the simple expedient of DISALLOWING "olcuc" with multi-byte
325  * processing, we could rid ourselves of both these tables and save 512 bytes;
326  * seriously, it doesn't make much sense to use olcuc with multi-byte, and
327  * it will probably never be used.  Consideration should be given to disallowing
328  * the combination TS_MEUC & OLCUC.
329  */
330 static unsigned char enotrantab[256] = {
331 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
332 /* 010 */	0,	0,	0,	0,	0,	0,	0,	0,
333 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
334 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
335 /* 040 */	' ',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
336 /* 050 */	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
337 /* 060 */	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
338 /* 070 */	'8',	'9',	':',	';',	'<',	'=',	'>',	'?',
339 /* 100 */	'@',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
340 /* 110 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
341 /* 120 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
342 /* 130 */	'X',	'Y',	'Z',	'[',	'\\',	']',	'^',	'_',
343 /* 140 */	'`',	'a',	'b',	'c',	'd',	'e',	'f',	'g',
344 /* 150 */	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
345 /* 160 */	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
346 /* 170 */	'x',	'y',	'z',	'{',	'|',	'}',	'~',	0,
347 /* 200 - 377 aren't mapped (they're stoppers). */
348 };
349 
350 /*
351  * Translation table for TS_MEUC output with OLCUC.  All printing ASCII
352  * translate to themselves, except for lower-case letters which translate
353  * to their upper-case equivalents.  All other bytes have a zero in
354  * the table, which stops the copying.  Useless for ISO Latin Alphabet
355  * translations, but *sigh* OLCUC is really only defined for ASCII anyway.
356  * We only have this table so we can use the existing OLCUC processing with
357  * TS_MEUC set (multi-byte mode).  Nobody would ever think of actually
358  * _using_ it...would they?
359  */
360 static unsigned char elcuctab[256] = {
361 /* 000 */	0,	0,	0,	0,	0,	0,	0,	0,
362 /* 010 */	0,	0,	0,	0,	0,	0,	0,	0,
363 /* 020 */	0,	0,	0,	0,	0,	0,	0,	0,
364 /* 030 */	0,	0,	0,	0,	0,	0,	0,	0,
365 /* 040 */	' ',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
366 /* 050 */	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
367 /* 060 */	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
368 /* 070 */	'8',	'9',	':',	';',	'<',	'=',	'>',	'?',
369 /* 100 */	'@',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
370 /* 110 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
371 /* 120 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
372 /* 130 */	'X',	'Y',	'Z',	'[',	'\\',	']',	'^',	'_',
373 /* 140 */	'`',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
374 /* 150 */	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
375 /* 160 */	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
376 /* 170 */	'X',	'Y',	'Z',	'{',	'|',	'}',	'~',	0,
377 /* 200 - 377 aren't mapped (they're stoppers). */
378 };
379 
380 static struct streamtab ldtrinfo;
381 
382 static struct fmodsw fsw = {
383 	"ldterm",
384 	&ldtrinfo,
385 	D_MTQPAIR | D_MP
386 };
387 
388 static struct modlstrmod modlstrmod = {
389 	&mod_strmodops, "terminal line discipline", &fsw
390 };
391 
392 
393 static struct modlinkage modlinkage = {
394 	MODREV_1, &modlstrmod, NULL
395 };
396 
397 
398 int
399 _init(void)
400 {
401 	return (mod_install(&modlinkage));
402 }
403 
404 int
405 _fini(void)
406 {
407 	return (mod_remove(&modlinkage));
408 }
409 
410 int
411 _info(struct modinfo *modinfop)
412 {
413 	return (mod_info(&modlinkage, modinfop));
414 }
415 
416 
417 static int	ldtermopen(queue_t *, dev_t *, int, int, cred_t *);
418 static int	ldtermclose(queue_t *, int, cred_t *);
419 static void	ldtermrput(queue_t *, mblk_t *);
420 static void	ldtermrsrv(queue_t *);
421 static int	ldtermrmsg(queue_t *, mblk_t *);
422 static void	ldtermwput(queue_t *, mblk_t *);
423 static void	ldtermwsrv(queue_t *);
424 static int	ldtermwmsg(queue_t *, mblk_t *);
425 static mblk_t	*ldterm_docanon(unsigned char, mblk_t *, size_t, queue_t *,
426 				ldtermstd_state_t *, int *);
427 static int	ldterm_unget(ldtermstd_state_t *);
428 static void	ldterm_trim(ldtermstd_state_t *);
429 static void	ldterm_rubout(unsigned char, queue_t *, size_t,
430 				ldtermstd_state_t *);
431 static int	ldterm_tabcols(ldtermstd_state_t *);
432 static void	ldterm_erase(queue_t *, size_t, ldtermstd_state_t *);
433 static void	ldterm_werase(queue_t *, size_t, ldtermstd_state_t *);
434 static void	ldterm_kill(queue_t *, size_t, ldtermstd_state_t *);
435 static void	ldterm_reprint(queue_t *, size_t, ldtermstd_state_t *);
436 static mblk_t	*ldterm_dononcanon(mblk_t *, mblk_t *, size_t, queue_t *,
437 					ldtermstd_state_t *);
438 static int	ldterm_echo(unsigned char, queue_t *, size_t,
439 				ldtermstd_state_t *);
440 static void	ldterm_outchar(unsigned char, queue_t *, size_t,
441 				ldtermstd_state_t *);
442 static void	ldterm_outstring(unsigned char *, int, queue_t *, size_t,
443 					ldtermstd_state_t *tp);
444 static mblk_t	*newmsg(ldtermstd_state_t *);
445 static void	ldterm_msg_upstream(queue_t *, ldtermstd_state_t *);
446 static void	ldterm_wenable(void *);
447 static mblk_t	*ldterm_output_msg(queue_t *, mblk_t *, mblk_t **,
448 				ldtermstd_state_t *, size_t, int);
449 static void	ldterm_flush_output(unsigned char, queue_t *,
450 					ldtermstd_state_t *);
451 static void	ldterm_dosig(queue_t *, int, unsigned char, int, int);
452 static void	ldterm_do_ioctl(queue_t *, mblk_t *);
453 static int	chgstropts(struct termios *, ldtermstd_state_t *, queue_t *);
454 static void	ldterm_ioctl_reply(queue_t *, mblk_t *);
455 static void	vmin_satisfied(queue_t *, ldtermstd_state_t *, int);
456 static void	vmin_settimer(queue_t *);
457 static void	vmin_timed_out(void *);
458 static void	ldterm_adjust_modes(ldtermstd_state_t *);
459 static void	ldterm_eucwarn(ldtermstd_state_t *);
460 static void	cp_eucwioc(eucioc_t *, eucioc_t *, int);
461 static int	ldterm_codeset(uchar_t, uchar_t);
462 
463 static void	ldterm_csi_erase(queue_t *, size_t, ldtermstd_state_t *);
464 static void	ldterm_csi_werase(queue_t *, size_t, ldtermstd_state_t *);
465 
466 static uchar_t	ldterm_utf8_width(uchar_t *, int);
467 
468 /* Codeset type specific methods for EUC, PCCS, and, UTF-8 codeset types. */
469 static int	__ldterm_dispwidth_euc(uchar_t, void *, int);
470 static int	__ldterm_memwidth_euc(uchar_t, void *);
471 
472 static int	__ldterm_dispwidth_pccs(uchar_t, void *, int);
473 static int	__ldterm_memwidth_pccs(uchar_t, void *);
474 
475 static int	__ldterm_dispwidth_utf8(uchar_t, void *, int);
476 static int	__ldterm_memwidth_utf8(uchar_t, void *);
477 
478 static const ldterm_cs_methods_t cs_methods[LDTERM_CS_TYPE_MAX + 1] = {
479 	{
480 		NULL,
481 		NULL
482 	},
483 	{
484 		__ldterm_dispwidth_euc,
485 		__ldterm_memwidth_euc
486 	},
487 	{
488 		__ldterm_dispwidth_pccs,
489 		__ldterm_memwidth_pccs
490 	},
491 	{
492 		__ldterm_dispwidth_utf8,
493 		__ldterm_memwidth_utf8
494 	}
495 };
496 
497 /*
498  * The default codeset is presumably C locale's ISO 646 in EUC but
499  * the data structure at below defined as the default codeset data also
500  * support any single byte (EUC) locales.
501  */
502 static const ldterm_cs_data_t default_cs_data = {
503 	LDTERM_DATA_VERSION,
504 	LDTERM_CS_TYPE_EUC,
505 	(uchar_t)0,
506 	(uchar_t)0,
507 	(char *)NULL,
508 	{
509 		'\0', '\0', '\0', '\0',
510 		'\0', '\0', '\0', '\0',
511 		'\0', '\0', '\0', '\0',
512 		'\0', '\0', '\0', '\0',
513 		'\0', '\0', '\0', '\0',
514 		'\0', '\0', '\0', '\0',
515 		'\0', '\0', '\0', '\0',
516 		'\0', '\0', '\0', '\0',
517 		'\0', '\0', '\0', '\0',
518 		'\0', '\0', '\0', '\0'
519 	}
520 };
521 
522 /*
523  * The following tables are from either u8_textprep.c or uconv.c at
524  * usr/src/common/unicode/. The tables are used to figure out corresponding
525  * UTF-8 character byte lengths and also the validity of given character bytes.
526  */
527 extern const int8_t u8_number_of_bytes[];
528 extern const uchar_t u8_masks_tbl[];
529 extern const uint8_t u8_valid_min_2nd_byte[];
530 extern const uint8_t u8_valid_max_2nd_byte[];
531 
532 /*
533  * Unicode character width definition tables from uwidth.c:
534  */
535 extern const ldterm_unicode_data_cell_t ldterm_ucode[][16384];
536 
537 #ifdef LDDEBUG
538 int	ldterm_debug = 0;
539 #define	DEBUG1(a)	if (ldterm_debug == 1) printf a
540 #define	DEBUG2(a)	if (ldterm_debug >= 2) printf a	/* allocations */
541 #define	DEBUG3(a)	if (ldterm_debug >= 3) printf a	/* M_CTL Stuff */
542 #define	DEBUG4(a)	if (ldterm_debug >= 4) printf a	/* M_READ Stuff */
543 #define	DEBUG5(a)	if (ldterm_debug >= 5) printf a
544 #define	DEBUG6(a)	if (ldterm_debug >= 6) printf a
545 #define	DEBUG7(a)	if (ldterm_debug >= 7) printf a
546 #else
547 #define	DEBUG1(a)
548 #define	DEBUG2(a)
549 #define	DEBUG3(a)
550 #define	DEBUG4(a)
551 #define	DEBUG5(a)
552 #define	DEBUG6(a)
553 #define	DEBUG7(a)
554 #endif		/* LDDEBUG */
555 
556 
557 /*
558  * Since most of the buffering occurs either at the stream head or in
559  * the "message currently being assembled" buffer, we have a
560  * relatively small input queue, so that blockages above us get
561  * reflected fairly quickly to the module below us.  We also have a
562  * small maximum packet size, since you can put a message of that
563  * size on an empty queue no matter how much bigger than the high
564  * water mark it is.
565  */
566 static struct module_info ldtermmiinfo = {
567 	0x0bad,
568 	"ldterm",
569 	0,
570 	256,
571 	HIWAT,
572 	LOWAT
573 };
574 
575 
576 static struct qinit ldtermrinit = {
577 	(int (*)())ldtermrput,
578 	(int (*)())ldtermrsrv,
579 	ldtermopen,
580 	ldtermclose,
581 	NULL,
582 	&ldtermmiinfo
583 };
584 
585 
586 static struct module_info ldtermmoinfo = {
587 	0x0bad,
588 	"ldterm",
589 	0,
590 	INFPSZ,
591 	1,
592 	0
593 };
594 
595 
596 static struct qinit ldtermwinit = {
597 	(int (*)())ldtermwput,
598 	(int (*)())ldtermwsrv,
599 	ldtermopen,
600 	ldtermclose,
601 	NULL,
602 	&ldtermmoinfo
603 };
604 
605 
606 static struct streamtab ldtrinfo = {
607 	&ldtermrinit,
608 	&ldtermwinit,
609 	NULL,
610 	NULL
611 };
612 
613 /*
614  * Dummy qbufcall callback routine used by open and close.
615  * The framework will wake up qwait_sig when we return from
616  * this routine (as part of leaving the perimeters.)
617  * (The framework enters the perimeters before calling the qbufcall() callback
618  * and leaves the perimeters after the callback routine has executed. The
619  * framework performs an implicit wakeup of any thread in qwait/qwait_sig
620  * when it leaves the perimeter. See qwait(9E).)
621  */
622 /* ARGSUSED */
623 static void
624 dummy_callback(void *arg)
625 {}
626 
627 
628 static mblk_t *
629 open_ioctl(queue_t *q, uint_t cmd)
630 {
631 	mblk_t *mp;
632 	bufcall_id_t id;
633 	int retv;
634 
635 	while ((mp = mkiocb(cmd)) == NULL) {
636 		id = qbufcall(q, sizeof (struct iocblk), BPRI_MED,
637 		    dummy_callback, NULL);
638 		retv = qwait_sig(q);
639 		qunbufcall(q, id);
640 		if (retv == 0)
641 			break;
642 	}
643 	return (mp);
644 }
645 
646 static mblk_t *
647 open_mblk(queue_t *q, size_t len)
648 {
649 	mblk_t *mp;
650 	bufcall_id_t id;
651 	int retv;
652 
653 	while ((mp = allocb(len, BPRI_MED)) == NULL) {
654 		id = qbufcall(q, len, BPRI_MED, dummy_callback, NULL);
655 		retv = qwait_sig(q);
656 		qunbufcall(q, id);
657 		if (retv == 0)
658 			break;
659 	}
660 	return (mp);
661 }
662 
663 /*
664  * Line discipline open.
665  */
666 /* ARGSUSED1 */
667 static int
668 ldtermopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
669 {
670 	ldtermstd_state_t *tp;
671 	mblk_t *bp, *qryp;
672 	int len;
673 	struct stroptions *strop;
674 	struct termios *termiosp;
675 	queue_t *wq;
676 
677 	if (q->q_ptr != NULL) {
678 		return (0);	/* already attached */
679 	}
680 
681 	tp = (ldtermstd_state_t *)kmem_zalloc(sizeof (ldtermstd_state_t),
682 	    KM_SLEEP);
683 
684 	/*
685 	 * Get termios defaults.  These are stored as
686 	 * a property in the "options" node.
687 	 */
688 	if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_NOTPROM,
689 	    "ttymodes", (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS &&
690 	    len == sizeof (struct termios)) {
691 		tp->t_modes = *termiosp;
692 		tp->t_amodes = *termiosp;
693 		kmem_free(termiosp, len);
694 	} else {
695 		/*
696 		 * Gack!  Whine about it.
697 		 */
698 		cmn_err(CE_WARN, "ldterm: Couldn't get ttymodes property!");
699 	}
700 	bzero(&tp->t_dmodes, sizeof (struct termios));
701 
702 	tp->t_state = 0;
703 
704 	tp->t_line = 0;
705 	tp->t_col = 0;
706 
707 	tp->t_rocount = 0;
708 	tp->t_rocol = 0;
709 
710 	tp->t_message = NULL;
711 	tp->t_endmsg = NULL;
712 	tp->t_msglen = 0;
713 	tp->t_rd_request = 0;
714 
715 	tp->t_echomp = NULL;
716 	tp->t_iocid = 0;
717 	tp->t_wbufcid = 0;
718 	tp->t_vtid = 0;
719 
720 	q->q_ptr = (caddr_t)tp;
721 	WR(q)->q_ptr = (caddr_t)tp;
722 	/*
723 	 * The following for EUC and also non-EUC codesets:
724 	 */
725 	tp->t_codeset = tp->t_eucleft = tp->t_eucign = tp->t_scratch_len = 0;
726 	bzero(&tp->eucwioc, EUCSIZE);
727 	tp->eucwioc.eucw[0] = 1;	/* ASCII mem & screen width */
728 	tp->eucwioc.scrw[0] = 1;
729 	tp->t_maxeuc = 1;	/* the max len in bytes of an EUC char */
730 	tp->t_eucp = NULL;
731 	tp->t_eucp_mp = NULL;
732 	tp->t_eucwarn = 0;	/* no bad chars seen yet */
733 
734 	tp->t_csdata = default_cs_data;
735 	tp->t_csmethods = cs_methods[LDTERM_CS_TYPE_EUC];
736 
737 	qprocson(q);
738 
739 	/*
740 	 * Find out if the module below us does canonicalization; if
741 	 * so, we won't do it ourselves.
742 	 */
743 
744 	if ((qryp = open_ioctl(q, MC_CANONQUERY)) == NULL)
745 		goto open_abort;
746 
747 	/*
748 	 * Reformulate as an M_CTL message. The actual data will
749 	 * be in the b_cont field.
750 	 */
751 	qryp->b_datap->db_type = M_CTL;
752 	wq = OTHERQ(q);
753 	putnext(wq, qryp);
754 
755 	/* allocate a TCSBRK ioctl in case we'll need it on close */
756 	if ((qryp = open_ioctl(q, TCSBRK)) == NULL)
757 		goto open_abort;
758 	tp->t_drainmsg = qryp;
759 	if ((bp = open_mblk(q, sizeof (int))) == NULL)
760 		goto open_abort;
761 	qryp->b_cont = bp;
762 
763 	/*
764 	 * Find out if the underlying driver supports proper POSIX close
765 	 * semantics.  If not, we'll have to approximate it using TCSBRK.  If
766 	 * it does, it will respond with MC_HAS_POSIX, and we'll catch that in
767 	 * the ldtermrput routine.
768 	 *
769 	 * When the ldterm_drain_limit tunable is set to zero, we behave the
770 	 * same as old ldterm: don't send this new message, and always use
771 	 * TCSBRK during close.
772 	 */
773 	if (ldterm_drain_limit != 0) {
774 		if ((qryp = open_ioctl(q, MC_POSIXQUERY)) == NULL)
775 			goto open_abort;
776 		qryp->b_datap->db_type = M_CTL;
777 		putnext(wq, qryp);
778 	}
779 
780 	/* prepare to clear the water marks on close */
781 	if ((bp = open_mblk(q, sizeof (struct stroptions))) == NULL)
782 		goto open_abort;
783 	tp->t_closeopts = bp;
784 
785 	/*
786 	 * Set the high-water and low-water marks on the stream head
787 	 * to values appropriate for a terminal.  Also set the "vmin"
788 	 * and "vtime" values to 1 and 0, turn on message-nondiscard
789 	 * mode (as we're in ICANON mode), and turn on "old-style
790 	 * NODELAY" mode.
791 	 */
792 	if ((bp = open_mblk(q, sizeof (struct stroptions))) == NULL)
793 		goto open_abort;
794 	strop = (struct stroptions *)bp->b_wptr;
795 	strop->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT|SO_NDELON|SO_ISTTY;
796 	strop->so_readopt = RMSGN;
797 	strop->so_hiwat = HIWAT;
798 	strop->so_lowat = LOWAT;
799 	bp->b_wptr += sizeof (struct stroptions);
800 	bp->b_datap->db_type = M_SETOPTS;
801 	putnext(q, bp);
802 
803 	return (0);		/* this can become a controlling TTY */
804 
805 open_abort:
806 	qprocsoff(q);
807 	q->q_ptr = NULL;
808 	WR(q)->q_ptr = NULL;
809 	freemsg(tp->t_closeopts);
810 	freemsg(tp->t_drainmsg);
811 	/* Dump the state structure */
812 	kmem_free(tp, sizeof (ldtermstd_state_t));
813 	return (EINTR);
814 }
815 
816 struct close_timer {
817 	timeout_id_t id;
818 	ldtermstd_state_t *tp;
819 };
820 
821 static void
822 drain_timed_out(void *arg)
823 {
824 	struct close_timer *ctp = arg;
825 
826 	ctp->id = 0;
827 	ctp->tp->t_state &= ~TS_IOCWAIT;
828 }
829 
830 /* ARGSUSED2 */
831 static int
832 ldtermclose(queue_t *q, int cflag, cred_t *crp)
833 {
834 	ldtermstd_state_t *tp = (ldtermstd_state_t *)q->q_ptr;
835 	struct stroptions *strop;
836 	mblk_t *bp;
837 	struct close_timer cltimer;
838 
839 	/*
840 	 * If we have an outstanding vmin timeout, cancel it.
841 	 */
842 	tp->t_state |= TS_CLOSE;
843 	if (tp->t_vtid != 0)
844 		(void) quntimeout(q, tp->t_vtid);
845 	tp->t_vtid = 0;
846 
847 	/*
848 	 * Cancel outstanding qbufcall request.
849 	 */
850 	if (tp->t_wbufcid != 0)
851 		qunbufcall(q, tp->t_wbufcid);
852 
853 	/*
854 	 * Reset the high-water and low-water marks on the stream
855 	 * head (?), turn on byte-stream mode, and turn off
856 	 * "old-style NODELAY" mode.
857 	 */
858 	bp = tp->t_closeopts;
859 	strop = (struct stroptions *)bp->b_wptr;
860 	strop->so_flags = SO_READOPT|SO_NDELOFF;
861 	strop->so_readopt = RNORM;
862 	bp->b_wptr += sizeof (struct stroptions);
863 	bp->b_datap->db_type = M_SETOPTS;
864 	putnext(q, bp);
865 
866 	if (cflag & (FNDELAY|FNONBLOCK)) {
867 		freemsg(tp->t_drainmsg);
868 	} else if ((bp = tp->t_drainmsg) != NULL) {
869 		struct iocblk *iocb;
870 
871 		/*
872 		 * If the driver isn't known to have POSIX close semantics,
873 		 * then we have to emulate this the old way.  This is done by
874 		 * sending down TCSBRK,1 to drain the output and waiting for
875 		 * the reply.
876 		 */
877 		iocb = (struct iocblk *)bp->b_rptr;
878 		iocb->ioc_count = sizeof (int);
879 		*(int *)bp->b_cont->b_rptr = 1;
880 		bp->b_cont->b_wptr += sizeof (int);
881 		tp->t_state |= TS_IOCWAIT;
882 		tp->t_iocid = iocb->ioc_id;
883 		if (!putq(WR(q), bp))
884 			putnext(WR(q), bp);
885 
886 		/*
887 		 * If we're not able to receive signals at this point, then
888 		 * launch a timer.  This timer will prevent us from waiting
889 		 * forever for a signal that won't arrive.
890 		 */
891 		cltimer.id = 0;
892 		if (!ddi_can_receive_sig() && ldterm_drain_limit != 0) {
893 			cltimer.tp = tp;
894 			cltimer.id = qtimeout(q, drain_timed_out, &cltimer,
895 			    drv_usectohz(ldterm_drain_limit));
896 		}
897 
898 		/*
899 		 * Note that the read side of ldterm and the qtimeout are
900 		 * protected by D_MTQPAIR, so no additional locking is needed
901 		 * here.
902 		 */
903 		while (tp->t_state & TS_IOCWAIT) {
904 			if (qwait_sig(q) == 0)
905 				break;
906 		}
907 		if (cltimer.id != 0)
908 			(void) quntimeout(q, cltimer.id);
909 	}
910 
911 	/*
912 	 * From here to the end, the routine does not sleep and does not
913 	 * reference STREAMS, so it's guaranteed to run to completion.
914 	 */
915 
916 	qprocsoff(q);
917 
918 	freemsg(tp->t_message);
919 	freemsg(tp->t_eucp_mp);
920 
921 	/* Dump the state structure, then unlink it */
922 	if (tp->t_csdata.locale_name != NULL)
923 		kmem_free(tp->t_csdata.locale_name,
924 		    strlen(tp->t_csdata.locale_name) + 1);
925 	kmem_free(tp, sizeof (ldtermstd_state_t));
926 	q->q_ptr = NULL;
927 	return (0);
928 }
929 
930 
931 /*
932  * Put procedure for input from driver end of stream (read queue).
933  */
934 static void
935 ldtermrput(queue_t *q, mblk_t *mp)
936 {
937 	ldtermstd_state_t *tp;
938 	unsigned char c;
939 	queue_t *wrq = WR(q);		/* write queue of ldterm mod */
940 	queue_t *nextq = q->q_next;	/* queue below us */
941 	mblk_t *bp;
942 	struct iocblk *qryp;
943 	unsigned char *readp;
944 	unsigned char *writep;
945 	struct termios *emodes;		/* effective modes set by driver */
946 	int dbtype;
947 
948 	tp = (ldtermstd_state_t *)q->q_ptr;
949 	/*
950 	 * We received our ack from the driver saying there is nothing left to
951 	 * shovel out, so wake up the close routine.
952 	 */
953 	dbtype = DB_TYPE(mp);
954 	if ((dbtype == M_IOCACK || dbtype == M_IOCNAK) &&
955 	    (tp->t_state & (TS_CLOSE|TS_IOCWAIT)) == (TS_CLOSE|TS_IOCWAIT)) {
956 		struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
957 
958 		if (iocp->ioc_id == tp->t_iocid) {
959 			tp->t_state &= ~TS_IOCWAIT;
960 			freemsg(mp);
961 			return;
962 		}
963 	}
964 
965 	switch (dbtype) {
966 
967 	default:
968 		(void) putq(q, mp);
969 		return;
970 
971 		/*
972 		 * Send these up unmolested
973 		 *
974 		 */
975 	case M_PCSIG:
976 	case M_SIG:
977 	case M_IOCNAK:
978 
979 		putnext(q, mp);
980 		return;
981 
982 	case M_IOCACK:
983 
984 		ldterm_ioctl_reply(q, mp);
985 		return;
986 
987 	case M_BREAK:
988 
989 		/*
990 		 * Parity errors are sent up as M_BREAKS with single
991 		 * character data (formerly handled in the driver)
992 		 */
993 		if (mp->b_wptr - mp->b_rptr == 1) {
994 			/*
995 			 * IGNPAR	PARMRK		RESULT
996 			 * off		off		0
997 			 * off		on		3 byte sequence
998 			 * on		either		ignored
999 			 */
1000 			if (!(tp->t_amodes.c_iflag & IGNPAR)) {
1001 				mp->b_wptr = mp->b_rptr;
1002 				if (tp->t_amodes.c_iflag & PARMRK) {
1003 					unsigned char c;
1004 
1005 					c = *mp->b_rptr;
1006 					freemsg(mp);
1007 					if ((mp = allocb(3, BPRI_HI)) == NULL) {
1008 						cmn_err(CE_WARN,
1009 						    "ldtermrput: no blocks");
1010 						return;
1011 					}
1012 					mp->b_datap->db_type = M_DATA;
1013 					*mp->b_wptr++ = (uchar_t)'\377';
1014 					*mp->b_wptr++ = '\0';
1015 					*mp->b_wptr++ = c;
1016 					putnext(q, mp);
1017 				} else {
1018 					mp->b_datap->db_type = M_DATA;
1019 					*mp->b_wptr++ = '\0';
1020 					putnext(q, mp);
1021 				}
1022 			} else {
1023 				freemsg(mp);
1024 			}
1025 			return;
1026 		}
1027 		/*
1028 		 * We look at the apparent modes here instead of the
1029 		 * effective modes. Effective modes cannot be used if
1030 		 * IGNBRK, BRINT and PARMRK have been negotiated to
1031 		 * be handled by the driver. Since M_BREAK should be
1032 		 * sent upstream only if break processing was not
1033 		 * already done, it should be ok to use the apparent
1034 		 * modes.
1035 		 */
1036 
1037 		if (!(tp->t_amodes.c_iflag & IGNBRK)) {
1038 			if (tp->t_amodes.c_iflag & BRKINT) {
1039 				ldterm_dosig(q, SIGINT, '\0', M_PCSIG, FLUSHRW);
1040 				freemsg(mp);
1041 			} else if (tp->t_amodes.c_iflag & PARMRK) {
1042 				/*
1043 				 * Send '\377','\0', '\0'.
1044 				 */
1045 				freemsg(mp);
1046 				if ((mp = allocb(3, BPRI_HI)) == NULL) {
1047 					cmn_err(CE_WARN,
1048 					    "ldtermrput: no blocks");
1049 					return;
1050 				}
1051 				mp->b_datap->db_type = M_DATA;
1052 				*mp->b_wptr++ = (uchar_t)'\377';
1053 				*mp->b_wptr++ = '\0';
1054 				*mp->b_wptr++ = '\0';
1055 				putnext(q, mp);
1056 			} else {
1057 				/*
1058 				 * Act as if a '\0' came in.
1059 				 */
1060 				freemsg(mp);
1061 				if ((mp = allocb(1, BPRI_HI)) == NULL) {
1062 					cmn_err(CE_WARN,
1063 					    "ldtermrput: no blocks");
1064 					return;
1065 				}
1066 				mp->b_datap->db_type = M_DATA;
1067 				*mp->b_wptr++ = '\0';
1068 				putnext(q, mp);
1069 			}
1070 		} else {
1071 			freemsg(mp);
1072 		}
1073 		return;
1074 
1075 	case M_CTL:
1076 		DEBUG3(("ldtermrput: M_CTL received\n"));
1077 		/*
1078 		 * The M_CTL has been standardized to look like an
1079 		 * M_IOCTL message.
1080 		 */
1081 
1082 		if ((mp->b_wptr - mp->b_rptr) != sizeof (struct iocblk)) {
1083 			DEBUG3((
1084 			    "Non standard M_CTL received by ldterm module\n"));
1085 			/* May be for someone else; pass it on */
1086 			putnext(q, mp);
1087 			return;
1088 		}
1089 		qryp = (struct iocblk *)mp->b_rptr;
1090 
1091 		switch (qryp->ioc_cmd) {
1092 
1093 		case MC_PART_CANON:
1094 
1095 			DEBUG3(("ldtermrput: M_CTL Query Reply\n"));
1096 			if (!mp->b_cont) {
1097 				DEBUG3(("No information in Query Message\n"));
1098 				break;
1099 			}
1100 			if ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) ==
1101 			    sizeof (struct termios)) {
1102 				DEBUG3(("ldtermrput: M_CTL GrandScheme\n"));
1103 				/* elaborate turning off scheme */
1104 				emodes = (struct termios *)mp->b_cont->b_rptr;
1105 				bcopy(emodes, &tp->t_dmodes,
1106 					sizeof (struct termios));
1107 				ldterm_adjust_modes(tp);
1108 				break;
1109 			} else {
1110 				DEBUG3(("Incorrect query replysize\n"));
1111 				break;
1112 			}
1113 
1114 		case MC_NO_CANON:
1115 			tp->t_state |= TS_NOCANON;
1116 			/*
1117 			 * Note: this is very nasty.  It's not clear
1118 			 * what the right thing to do with a partial
1119 			 * message is; We throw it out
1120 			 */
1121 			if (tp->t_message != NULL) {
1122 				freemsg(tp->t_message);
1123 				tp->t_message = NULL;
1124 				tp->t_endmsg = NULL;
1125 				tp->t_msglen = 0;
1126 				tp->t_rocount = 0;
1127 				tp->t_rocol = 0;
1128 				if (tp->t_state & TS_MEUC) {
1129 					ASSERT(tp->t_eucp_mp);
1130 					tp->t_eucp = tp->t_eucp_mp->b_rptr;
1131 					tp->t_codeset = 0;
1132 					tp->t_eucleft = 0;
1133 				}
1134 			}
1135 			break;
1136 
1137 		case MC_DO_CANON:
1138 			tp->t_state &= ~TS_NOCANON;
1139 			break;
1140 
1141 		case MC_HAS_POSIX:
1142 			/* no longer any reason to drain from ldterm */
1143 			if (ldterm_drain_limit != 0) {
1144 				freemsg(tp->t_drainmsg);
1145 				tp->t_drainmsg = NULL;
1146 			}
1147 			break;
1148 
1149 		default:
1150 			DEBUG3(("Unknown M_CTL Message\n"));
1151 			break;
1152 		}
1153 		putnext(q, mp);	/* In case anyone else has to see it */
1154 		return;
1155 
1156 	case M_FLUSH:
1157 		/*
1158 		 * Flush everything we haven't looked at yet.
1159 		 */
1160 
1161 		if ((tp->t_state & TS_ISPTSTTY) && (*mp->b_rptr & FLUSHBAND))
1162 			flushband(q, *(mp->b_rptr + 1), FLUSHDATA);
1163 		else
1164 			flushq(q, FLUSHDATA);
1165 
1166 		/*
1167 		 * Flush everything we have looked at.
1168 		 */
1169 		freemsg(tp->t_message);
1170 		tp->t_message = NULL;
1171 		tp->t_endmsg = NULL;
1172 		tp->t_msglen = 0;
1173 		tp->t_rocount = 0;
1174 		tp->t_rocol = 0;
1175 		if (tp->t_state & TS_MEUC) {	/* EUC multi-byte */
1176 			ASSERT(tp->t_eucp_mp);
1177 			tp->t_eucp = tp->t_eucp_mp->b_rptr;
1178 		}
1179 		putnext(q, mp);	/* pass it on */
1180 
1181 		/*
1182 		 * Relieve input flow control
1183 		 */
1184 		if ((tp->t_modes.c_iflag & IXOFF) &&
1185 		    (tp->t_state & TS_TBLOCK) &&
1186 		    !(tp->t_state & TS_IFBLOCK) && q->q_count <= TTXOLO) {
1187 			tp->t_state &= ~TS_TBLOCK;
1188 			(void) putnextctl(wrq, M_STARTI);
1189 			DEBUG1(("M_STARTI down\n"));
1190 		}
1191 		return;
1192 
1193 	case M_DATA:
1194 		break;
1195 	}
1196 	(void) drv_setparm(SYSRAWC, msgdsize(mp));
1197 
1198 	/*
1199 	 * Flow control: send "start input" message if blocked and
1200 	 * our queue is below its low water mark.
1201 	 */
1202 	if ((tp->t_modes.c_iflag & IXOFF) && (tp->t_state & TS_TBLOCK) &&
1203 	    !(tp->t_state & TS_IFBLOCK) && q->q_count <= TTXOLO) {
1204 		tp->t_state &= ~TS_TBLOCK;
1205 		(void) putnextctl(wrq, M_STARTI);
1206 		DEBUG1(("M_STARTI down\n"));
1207 	}
1208 	/*
1209 	 * If somebody below us ("intelligent" communications
1210 	 * board, pseudo-tty controlled by an editor) is doing
1211 	 * canonicalization, don't scan it for special characters.
1212 	 */
1213 	if (tp->t_state & TS_NOCANON) {
1214 		(void) putq(q, mp);
1215 		return;
1216 	}
1217 	bp = mp;
1218 
1219 	do {
1220 		readp = bp->b_rptr;
1221 		writep = readp;
1222 		if (tp->t_modes.c_iflag & (INLCR|IGNCR|ICRNL|IUCLC|IXON) ||
1223 		    tp->t_modes.c_lflag & (ISIG|ICANON)) {
1224 			/*
1225 			 * We're doing some sort of non-trivial
1226 			 * processing of input; look at every
1227 			 * character.
1228 			 */
1229 			while (readp < bp->b_wptr) {
1230 				c = *readp++;
1231 
1232 				if (tp->t_modes.c_iflag & ISTRIP)
1233 					c &= 0177;
1234 
1235 				/*
1236 				 * First, check that this hasn't been
1237 				 * escaped with the "literal next"
1238 				 * character.
1239 				 */
1240 				if (tp->t_state & TS_PLNCH) {
1241 					tp->t_state &= ~TS_PLNCH;
1242 					tp->t_modes.c_lflag &= ~FLUSHO;
1243 					*writep++ = c;
1244 					continue;
1245 				}
1246 				/*
1247 				 * Setting a special character to NUL
1248 				 * disables it, so if this character
1249 				 * is NUL, it should not be compared
1250 				 * with any of the special characters.
1251 				 * It should, however, restart frozen
1252 				 * output if IXON and IXANY are set.
1253 				 */
1254 				if (c == _POSIX_VDISABLE) {
1255 					if (tp->t_modes.c_iflag & IXON &&
1256 					    tp->t_state & TS_TTSTOP &&
1257 					    tp->t_modes.c_lflag & IEXTEN &&
1258 					    tp->t_modes.c_iflag & IXANY) {
1259 						tp->t_state &=
1260 						    ~(TS_TTSTOP|TS_OFBLOCK);
1261 						(void) putnextctl(wrq, M_START);
1262 					}
1263 					tp->t_modes.c_lflag &= ~FLUSHO;
1264 					*writep++ = c;
1265 					continue;
1266 				}
1267 				/*
1268 				 * If stopped, start if you can; if
1269 				 * running, stop if you must.
1270 				 */
1271 				if (tp->t_modes.c_iflag & IXON) {
1272 					if (tp->t_state & TS_TTSTOP) {
1273 						if (c ==
1274 						    tp->t_modes.c_cc[VSTART] ||
1275 						    (tp->t_modes.c_lflag &
1276 						    IEXTEN &&
1277 						    tp->t_modes.c_iflag &
1278 						    IXANY)) {
1279 							tp->t_state &=
1280 							    ~(TS_TTSTOP |
1281 							    TS_OFBLOCK);
1282 							(void) putnextctl(wrq,
1283 							    M_START);
1284 						}
1285 					} else {
1286 						if (c ==
1287 						    tp->t_modes.c_cc[VSTOP]) {
1288 							tp->t_state |=
1289 							    TS_TTSTOP;
1290 							(void) putnextctl(wrq,
1291 							    M_STOP);
1292 						}
1293 					}
1294 					if (c == tp->t_modes.c_cc[VSTOP] ||
1295 					    c == tp->t_modes.c_cc[VSTART])
1296 						continue;
1297 				}
1298 				/*
1299 				 * Check for "literal next" character
1300 				 * and "flush output" character.
1301 				 * Note that we omit checks for ISIG
1302 				 * and ICANON, since the IEXTEN
1303 				 * setting subsumes them.
1304 				 */
1305 				if (tp->t_modes.c_lflag & IEXTEN) {
1306 					if (c == tp->t_modes.c_cc[VLNEXT]) {
1307 						/*
1308 						 * Remember that we saw a
1309 						 * "literal next" while
1310 						 * scanning input, but leave
1311 						 * leave it in the message so
1312 						 * that the service routine
1313 						 * can see it too.
1314 						 */
1315 						tp->t_state |= TS_PLNCH;
1316 						tp->t_modes.c_lflag &= ~FLUSHO;
1317 						*writep++ = c;
1318 						continue;
1319 					}
1320 					if (c == tp->t_modes.c_cc[VDISCARD]) {
1321 						ldterm_flush_output(c, wrq, tp);
1322 						continue;
1323 					}
1324 				}
1325 				tp->t_modes.c_lflag &= ~FLUSHO;
1326 
1327 				/*
1328 				 * Check for signal-generating
1329 				 * characters.
1330 				 */
1331 				if (tp->t_modes.c_lflag & ISIG) {
1332 					if (c == tp->t_modes.c_cc[VINTR]) {
1333 						ldterm_dosig(q, SIGINT, c,
1334 						    M_PCSIG, FLUSHRW);
1335 						continue;
1336 					}
1337 					if (c == tp->t_modes.c_cc[VQUIT]) {
1338 						ldterm_dosig(q, SIGQUIT, c,
1339 						    M_PCSIG, FLUSHRW);
1340 						continue;
1341 					}
1342 					if (c == tp->t_modes.c_cc[VSWTCH]) {
1343 						/*
1344 						 * Ancient SXT support; discard
1345 						 * character without action.
1346 						 */
1347 						continue;
1348 					}
1349 					if (c == tp->t_modes.c_cc[VSUSP]) {
1350 						ldterm_dosig(q, SIGTSTP, c,
1351 						    M_PCSIG, FLUSHRW);
1352 						continue;
1353 					}
1354 					if ((tp->t_modes.c_lflag & IEXTEN) &&
1355 					    (c == tp->t_modes.c_cc[VDSUSP])) {
1356 						ldterm_dosig(q, SIGTSTP, c,
1357 						    M_SIG, 0);
1358 						continue;
1359 					}
1360 				}
1361 				/*
1362 				 * Throw away CR if IGNCR set, or
1363 				 * turn it into NL if ICRNL set.
1364 				 */
1365 				if (c == '\r') {
1366 					if (tp->t_modes.c_iflag & IGNCR)
1367 						continue;
1368 					if (tp->t_modes.c_iflag & ICRNL)
1369 						c = '\n';
1370 				} else {
1371 					/*
1372 					 * Turn NL into CR if INLCR
1373 					 * set.
1374 					 */
1375 					if (c == '\n' &&
1376 					    tp->t_modes.c_iflag & INLCR)
1377 						c = '\r';
1378 				}
1379 
1380 				/*
1381 				 * Map upper case input to lower case
1382 				 * if IUCLC flag set.
1383 				 */
1384 				if (tp->t_modes.c_iflag & IUCLC &&
1385 				    c >= 'A' && c <= 'Z')
1386 					c += 'a' - 'A';
1387 
1388 				/*
1389 				 * Put the possibly-transformed
1390 				 * character back in the message.
1391 				 */
1392 				*writep++ = c;
1393 			}
1394 
1395 			/*
1396 			 * If we didn't copy some characters because
1397 			 * we were ignoring them, fix the size of the
1398 			 * data block by adjusting the write pointer.
1399 			 * XXX This may result in a zero-length
1400 			 * block; will this cause anybody gastric
1401 			 * distress?
1402 			 */
1403 			bp->b_wptr -= (readp - writep);
1404 		} else {
1405 			/*
1406 			 * We won't be doing anything other than
1407 			 * possibly stripping the input.
1408 			 */
1409 			if (tp->t_modes.c_iflag & ISTRIP) {
1410 				while (readp < bp->b_wptr)
1411 					*writep++ = *readp++ & 0177;
1412 			}
1413 			tp->t_modes.c_lflag &= ~FLUSHO;
1414 		}
1415 
1416 	} while ((bp = bp->b_cont) != NULL);	/* next block, if any */
1417 
1418 	/*
1419 	 * Queue the message for service procedure if the
1420 	 * queue is not empty or canputnext() fails or
1421 	 * tp->t_state & TS_RESCAN is true.
1422 	 */
1423 
1424 	if (q->q_first != NULL || !bcanputnext(q, mp->b_band) ||
1425 	    (tp->t_state & TS_RESCAN))
1426 		(void) putq(q, mp);
1427 	else
1428 		(void) ldtermrmsg(q, mp);
1429 
1430 	/*
1431 	 * Flow control: send "stop input" message if our queue is
1432 	 * approaching its high-water mark. The message will be
1433 	 * dropped on the floor in the service procedure, if we
1434 	 * cannot ship it up and we have had it upto our neck!
1435 	 *
1436 	 * Set QWANTW to ensure that the read queue service procedure
1437 	 * gets run when nextq empties up again, so that it can
1438 	 * unstop the input.
1439 	 */
1440 	if ((tp->t_modes.c_iflag & IXOFF) && !(tp->t_state & TS_TBLOCK) &&
1441 	    q->q_count >= TTXOHI) {
1442 		mutex_enter(QLOCK(nextq));
1443 		nextq->q_flag |= QWANTW;
1444 		mutex_exit(QLOCK(nextq));
1445 		tp->t_state |= TS_TBLOCK;
1446 		(void) putnextctl(wrq, M_STOPI);
1447 		DEBUG1(("M_STOPI down\n"));
1448 	}
1449 }
1450 
1451 
1452 /*
1453  * Line discipline input server processing.  Erase/kill and escape
1454  * ('\') processing, gathering into messages, upper/lower case input
1455  * mapping.
1456  */
1457 static void
1458 ldtermrsrv(queue_t *q)
1459 {
1460 	ldtermstd_state_t *tp;
1461 	mblk_t *mp;
1462 
1463 	tp = (ldtermstd_state_t *)q->q_ptr;
1464 
1465 	if (tp->t_state & TS_RESCAN) {
1466 		/*
1467 		 * Canonicalization was turned on or off. Put the
1468 		 * message being assembled back in the input queue,
1469 		 * so that we rescan it.
1470 		 */
1471 		if (tp->t_message != NULL) {
1472 			DEBUG5(("RESCAN WAS SET; put back in q\n"));
1473 			if (tp->t_msglen != 0)
1474 				(void) putbq(q, tp->t_message);
1475 			else
1476 				freemsg(tp->t_message);
1477 			tp->t_message = NULL;
1478 			tp->t_endmsg = NULL;
1479 			tp->t_msglen = 0;
1480 		}
1481 		if (tp->t_state & TS_MEUC) {
1482 			ASSERT(tp->t_eucp_mp);
1483 			tp->t_eucp = tp->t_eucp_mp->b_rptr;
1484 			tp->t_codeset = 0;
1485 			tp->t_eucleft = 0;
1486 		}
1487 		tp->t_state &= ~TS_RESCAN;
1488 	}
1489 
1490 	while ((mp = getq(q)) != NULL) {
1491 		if (!ldtermrmsg(q, mp))
1492 			break;
1493 	}
1494 
1495 	/*
1496 	 * Flow control: send start message if blocked and our queue
1497 	 * is below its low water mark.
1498 	 */
1499 	if ((tp->t_modes.c_iflag & IXOFF) && (tp->t_state & TS_TBLOCK) &&
1500 	    !(tp->t_state & TS_IFBLOCK) && q->q_count <= TTXOLO) {
1501 		tp->t_state &= ~TS_TBLOCK;
1502 		(void) putctl(WR(q), M_STARTI);
1503 	}
1504 }
1505 
1506 /*
1507  * This routine is called from both ldtermrput and ldtermrsrv to
1508  * do the actual work of dealing with mp. Return 1 on sucesss and
1509  * 0 on failure.
1510  */
1511 static int
1512 ldtermrmsg(queue_t *q, mblk_t *mp)
1513 {
1514 	unsigned char c;
1515 	int dofree;
1516 	int status = 1;
1517 	size_t   ebsize;
1518 	mblk_t *bp;
1519 	mblk_t *bpt;
1520 	ldtermstd_state_t *tp;
1521 
1522 	bpt = NULL;
1523 
1524 	tp = (ldtermstd_state_t *)q->q_ptr;
1525 
1526 	if (mp->b_datap->db_type <= QPCTL && !bcanputnext(q, mp->b_band)) {
1527 		/*
1528 		 * Stream head is flow controlled. If echo is
1529 		 * turned on, flush the read side or send a
1530 		 * bell down the line to stop input and
1531 		 * process the current message.
1532 		 * Otherwise(putbq) the user will not see any
1533 		 * response to to the typed input. Typically
1534 		 * happens if there is no reader process.
1535 		 * Note that you will loose the data in this
1536 		 * case if the data is coming too fast. There
1537 		 * is an assumption here that if ECHO is
1538 		 * turned on its some user typing the data on
1539 		 * a terminal and its not network.
1540 		 */
1541 		if (tp->t_modes.c_lflag & ECHO) {
1542 			if ((tp->t_modes.c_iflag & IMAXBEL) &&
1543 			    (tp->t_modes.c_lflag & ICANON)) {
1544 				freemsg(mp);
1545 				if (canputnext(WR(q)))
1546 					ldterm_outchar(CTRL('g'), WR(q), 4, tp);
1547 				status = 0;
1548 				goto echo;
1549 			} else {
1550 				(void) putctl1(q, M_FLUSH, FLUSHR);
1551 			}
1552 		} else {
1553 			(void) putbq(q, mp);
1554 			status = 0;
1555 			goto out;	/* read side is blocked */
1556 		}
1557 	}
1558 	switch (mp->b_datap->db_type) {
1559 
1560 	default:
1561 		putnext(q, mp);	/* pass it on */
1562 		goto out;
1563 
1564 	case M_HANGUP:
1565 		/*
1566 		 * Flush everything we haven't looked at yet.
1567 		 */
1568 		flushq(q, FLUSHDATA);
1569 
1570 		/*
1571 		 * Flush everything we have looked at.
1572 		 */
1573 		freemsg(tp->t_message);
1574 		tp->t_message = NULL;
1575 		tp->t_endmsg = NULL;
1576 		tp->t_msglen = 0;
1577 		/*
1578 		 * XXX  should we set read request
1579 		 * tp->t_rd_request to NULL?
1580 		 */
1581 		tp->t_rocount = 0;	/* if it hasn't been typed */
1582 		tp->t_rocol = 0;	/* it hasn't been echoed :-) */
1583 		if (tp->t_state & TS_MEUC) {
1584 			ASSERT(tp->t_eucp_mp);
1585 			tp->t_eucp = tp->t_eucp_mp->b_rptr;
1586 		}
1587 		/*
1588 		 * Restart output, since it's probably got
1589 		 * nowhere to go anyway, and we're probably
1590 		 * not going to see another ^Q for a while.
1591 		 */
1592 		if (tp->t_state & TS_TTSTOP) {
1593 			tp->t_state &= ~(TS_TTSTOP|TS_OFBLOCK);
1594 			(void) putnextctl(WR(q), M_START);
1595 		}
1596 		/*
1597 		 * This message will travel up the read
1598 		 * queue, flushing as it goes, get turned
1599 		 * around at the stream head, and travel back
1600 		 * down the write queue, flushing as it goes.
1601 		 */
1602 		(void) putnextctl1(q, M_FLUSH, FLUSHW);
1603 
1604 		/*
1605 		 * This message will travel down the write
1606 		 * queue, flushing as it goes, get turned
1607 		 * around at the driver, and travel back up
1608 		 * the read queue, flushing as it goes.
1609 		 */
1610 		(void) putctl1(WR(q), M_FLUSH, FLUSHR);
1611 
1612 		/*
1613 		 * Now that that's done, we send a SIGCONT
1614 		 * upstream, followed by the M_HANGUP.
1615 		 */
1616 		/* (void) putnextctl1(q, M_PCSIG, SIGCONT); */
1617 		putnext(q, mp);
1618 		goto out;
1619 
1620 	case M_IOCACK:
1621 
1622 		/*
1623 		 * Augment whatever information the driver is
1624 		 * returning  with the information we supply.
1625 		 */
1626 		ldterm_ioctl_reply(q, mp);
1627 		goto out;
1628 
1629 	case M_DATA:
1630 		break;
1631 	}
1632 
1633 	/*
1634 	 * This is an M_DATA message.
1635 	 */
1636 
1637 	/*
1638 	 * If somebody below us ("intelligent" communications
1639 	 * board, pseudo-tty controlled by an editor) is
1640 	 * doing canonicalization, don't scan it for special
1641 	 * characters.
1642 	 */
1643 	if (tp->t_state & TS_NOCANON) {
1644 		putnext(q, mp);
1645 		goto out;
1646 	}
1647 	bp = mp;
1648 
1649 	if ((bpt = newmsg(tp)) != NULL) {
1650 		mblk_t *bcont;
1651 
1652 		do {
1653 			ASSERT(bp->b_wptr >= bp->b_rptr);
1654 			ebsize = bp->b_wptr - bp->b_rptr;
1655 			if (ebsize > EBSIZE)
1656 				ebsize = EBSIZE;
1657 			bcont = bp->b_cont;
1658 			if (CANON_MODE) {
1659 				/*
1660 				 * By default, free the message once processed
1661 				 */
1662 				dofree = 1;
1663 
1664 				/*
1665 				 * update sysinfo canch
1666 				 * character. The value of
1667 				 * canch may vary as compared
1668 				 * to character tty
1669 				 * implementation.
1670 				 */
1671 				while (bp->b_rptr < bp->b_wptr) {
1672 					c = *bp->b_rptr++;
1673 					if ((bpt = ldterm_docanon(c,
1674 					    bpt, ebsize, q, tp, &dofree)) ==
1675 					    NULL)
1676 						break;
1677 				}
1678 				/*
1679 				 * Release this block or put back on queue.
1680 				 */
1681 				if (dofree)
1682 					freeb(bp);
1683 				else {
1684 					(void) putbq(q, bp);
1685 					break;
1686 				}
1687 			} else
1688 				bpt = ldterm_dononcanon(bp, bpt, ebsize, q, tp);
1689 			if (bpt == NULL) {
1690 				cmn_err(CE_WARN,
1691 				    "ldtermrsrv: out of blocks");
1692 				freemsg(bcont);
1693 				break;
1694 			}
1695 		} while ((bp = bcont) != NULL);
1696 	}
1697 echo:
1698 	/*
1699 	 * Send whatever we echoed downstream.
1700 	 */
1701 	if (tp->t_echomp != NULL) {
1702 		if (canputnext(WR(q)))
1703 			putnext(WR(q), tp->t_echomp);
1704 		else
1705 			freemsg(tp->t_echomp);
1706 		tp->t_echomp = NULL;
1707 	}
1708 
1709 out:
1710 	return (status);
1711 }
1712 
1713 
1714 /*
1715  * Do canonical mode input; check whether this character is to be
1716  * treated as a special character - if so, check whether it's equal
1717  * to any of the special characters and handle it accordingly.
1718  * Otherwise, just add it to the current line.
1719  */
1720 static mblk_t *
1721 ldterm_docanon(uchar_t c, mblk_t *bpt, size_t ebsize, queue_t *q,
1722     ldtermstd_state_t *tp, int *dofreep)
1723 {
1724 	queue_t *wrq = WR(q);
1725 	int i;
1726 
1727 	/*
1728 	 * If the previous character was the "literal next"
1729 	 * character, treat this character as regular input.
1730 	 */
1731 	if (tp->t_state & TS_SLNCH)
1732 		goto escaped;
1733 
1734 	/*
1735 	 * Setting a special character to NUL disables it, so if this
1736 	 * character is NUL, it should not be compared with any of
1737 	 * the special characters.
1738 	 */
1739 	if (c == _POSIX_VDISABLE) {
1740 		tp->t_state &= ~TS_QUOT;
1741 		goto escaped;
1742 	}
1743 	/*
1744 	 * If this character is the literal next character, echo it
1745 	 * as '^', backspace over it, and record that fact.
1746 	 */
1747 	if ((tp->t_modes.c_lflag & IEXTEN) && c == tp->t_modes.c_cc[VLNEXT]) {
1748 		if (tp->t_modes.c_lflag & ECHO)
1749 			ldterm_outstring((unsigned char *)"^\b", 2, wrq,
1750 			    ebsize, tp);
1751 		tp->t_state |= TS_SLNCH;
1752 		goto out;
1753 	}
1754 	/*
1755 	 * Check for the editing character. If the display width of
1756 	 * the last byte at the canonical buffer is not one and also
1757 	 * smaller than or equal to UNKNOWN_WIDTH, the character at
1758 	 * the end of the buffer is a multi-byte and/or multi-column
1759 	 * character.
1760 	 */
1761 	if (c == tp->t_modes.c_cc[VERASE]) {
1762 		if (tp->t_state & TS_QUOT) {
1763 			/*
1764 			 * Get rid of the backslash, and put the
1765 			 * erase character in its place.
1766 			 */
1767 			ldterm_erase(wrq, ebsize, tp);
1768 			bpt = tp->t_endmsg;
1769 			goto escaped;
1770 		} else {
1771 			if ((tp->t_state & TS_MEUC) && tp->t_msglen &&
1772 			    (*(tp->t_eucp - 1) != 1 &&
1773 			    *(tp->t_eucp - 1) <= UNKNOWN_WIDTH))
1774 				ldterm_csi_erase(wrq, ebsize, tp);
1775 			else
1776 				ldterm_erase(wrq, ebsize, tp);
1777 			bpt = tp->t_endmsg;
1778 			goto out;
1779 		}
1780 	}
1781 	if ((tp->t_modes.c_lflag & IEXTEN) && c == tp->t_modes.c_cc[VWERASE]) {
1782 		/*
1783 		 * Do "ASCII word" or "multibyte character token/chunk" erase.
1784 		 */
1785 		if (tp->t_state & TS_MEUC)
1786 			ldterm_csi_werase(wrq, ebsize, tp);
1787 		else
1788 			ldterm_werase(wrq, ebsize, tp);
1789 		bpt = tp->t_endmsg;
1790 		goto out;
1791 	}
1792 	if (c == tp->t_modes.c_cc[VKILL]) {
1793 		if (tp->t_state & TS_QUOT) {
1794 			/*
1795 			 * Get rid of the backslash, and put the kill
1796 			 * character in its place.
1797 			 */
1798 			ldterm_erase(wrq, ebsize, tp);
1799 			bpt = tp->t_endmsg;
1800 			goto escaped;
1801 		} else {
1802 			ldterm_kill(wrq, ebsize, tp);
1803 			bpt = tp->t_endmsg;
1804 			goto out;
1805 		}
1806 	}
1807 	if ((tp->t_modes.c_lflag & IEXTEN) && c == tp->t_modes.c_cc[VREPRINT]) {
1808 		ldterm_reprint(wrq, ebsize, tp);
1809 		goto out;
1810 	}
1811 	/*
1812 	 * If the preceding character was a backslash: if the current
1813 	 * character is an EOF, get rid of the backslash and treat
1814 	 * the EOF as data; if we're in XCASE mode and the current
1815 	 * character is part of a backslash-X escape sequence,
1816 	 * process it; otherwise, just treat the current character
1817 	 * normally.
1818 	 */
1819 	if (tp->t_state & TS_QUOT) {
1820 		tp->t_state &= ~TS_QUOT;
1821 		if (c == tp->t_modes.c_cc[VEOF]) {
1822 			/*
1823 			 * EOF character. Since it's escaped, get rid
1824 			 * of the backslash and put the EOF character
1825 			 * in its place.
1826 			 */
1827 			ldterm_erase(wrq, ebsize, tp);
1828 			bpt = tp->t_endmsg;
1829 		} else {
1830 			/*
1831 			 * If we're in XCASE mode, and the current
1832 			 * character is part of a backslash-X
1833 			 * sequence, get rid of the backslash and
1834 			 * replace the current character with what
1835 			 * that sequence maps to.
1836 			 */
1837 			if ((tp->t_modes.c_lflag & XCASE) &&
1838 			    imaptab[c] != '\0') {
1839 				ldterm_erase(wrq, ebsize, tp);
1840 				bpt = tp->t_endmsg;
1841 				c = imaptab[c];
1842 			}
1843 		}
1844 	} else {
1845 		/*
1846 		 * Previous character wasn't backslash; check whether
1847 		 * this was the EOF character.
1848 		 */
1849 		if (c == tp->t_modes.c_cc[VEOF]) {
1850 			/*
1851 			 * EOF character. Don't echo it unless
1852 			 * ECHOCTL is set, don't stuff it in the
1853 			 * current line, but send the line up the
1854 			 * stream.
1855 			 */
1856 			if ((tp->t_modes.c_lflag & ECHOCTL) &&
1857 			    (tp->t_modes.c_lflag & IEXTEN) &&
1858 			    (tp->t_modes.c_lflag & ECHO)) {
1859 				i = ldterm_echo(c, wrq, ebsize, tp);
1860 				while (i > 0) {
1861 					ldterm_outchar('\b', wrq, ebsize, tp);
1862 					i--;
1863 				}
1864 			}
1865 			bpt->b_datap->db_type = M_DATA;
1866 			ldterm_msg_upstream(q, tp);
1867 			if (!canputnext(q)) {
1868 				bpt = NULL;
1869 				*dofreep = 0;
1870 			} else {
1871 				bpt = newmsg(tp);
1872 				*dofreep = 1;
1873 			}
1874 			goto out;
1875 		}
1876 	}
1877 
1878 escaped:
1879 	/*
1880 	 * First, make sure we can fit one WHOLE multi-byte char in the
1881 	 * buffer.  This is one place where we have overhead even if
1882 	 * not in multi-byte mode; the overhead is subtracting
1883 	 * tp->t_maxeuc from MAX_CANON before checking.
1884 	 *
1885 	 * Allows MAX_CANON bytes in the buffer before throwing awaying
1886 	 * the the overflow of characters.
1887 	 */
1888 	if ((tp->t_msglen > ((MAX_CANON + 1) - (int)tp->t_maxeuc)) &&
1889 	    !((tp->t_state & TS_MEUC) && tp->t_eucleft)) {
1890 
1891 		/*
1892 		 * Byte will cause line to overflow, or the next EUC
1893 		 * won't fit: Ring the bell or discard all input, and
1894 		 * don't save the byte away.
1895 		 */
1896 		if (tp->t_modes.c_iflag & IMAXBEL) {
1897 			if (canputnext(wrq))
1898 				ldterm_outchar(CTRL('g'), wrq, ebsize, tp);
1899 			goto out;
1900 		} else {
1901 			/*
1902 			 * MAX_CANON processing. free everything in
1903 			 * the current line and start with the
1904 			 * current character as the first character.
1905 			 */
1906 			DEBUG7(("ldterm_docanon: MAX_CANON processing\n"));
1907 			freemsg(tp->t_message);
1908 			tp->t_message = NULL;
1909 			tp->t_endmsg = NULL;
1910 			tp->t_msglen = 0;
1911 			tp->t_rocount = 0;	/* if it hasn't been type */
1912 			tp->t_rocol = 0;	/* it hasn't been echoed :-) */
1913 			if (tp->t_state & TS_MEUC) {
1914 				ASSERT(tp->t_eucp_mp);
1915 				tp->t_eucp = tp->t_eucp_mp->b_rptr;
1916 			}
1917 			tp->t_state &= ~TS_SLNCH;
1918 			bpt = newmsg(tp);
1919 		}
1920 	}
1921 	/*
1922 	 * Add the character to the current line.
1923 	 */
1924 	if (bpt->b_wptr >= bpt->b_datap->db_lim) {
1925 		/*
1926 		 * No more room in this mblk; save this one away, and
1927 		 * allocate a new one.
1928 		 */
1929 		bpt->b_datap->db_type = M_DATA;
1930 		if ((bpt = allocb(IBSIZE, BPRI_MED)) == NULL)
1931 			goto out;
1932 
1933 		/*
1934 		 * Chain the new one to the end of the old one, and
1935 		 * mark it as the last block in the current line.
1936 		 */
1937 		tp->t_endmsg->b_cont = bpt;
1938 		tp->t_endmsg = bpt;
1939 	}
1940 	*bpt->b_wptr++ = c;
1941 	tp->t_msglen++;		/* message length in BYTES */
1942 
1943 	/*
1944 	 * In multi-byte mode, we have to keep track of where we are.
1945 	 * The first bytes of multi-byte chars get the full count for the
1946 	 * whole character.  We don't do any column calculations
1947 	 * here, but we need the information for when we do. We could
1948 	 * come across cases where we are getting garbage on the
1949 	 * line, but we're in multi-byte mode.  In that case, we may
1950 	 * see ASCII controls come in the middle of what should have been a
1951 	 * multi-byte character.  Call ldterm_eucwarn...eventually, a
1952 	 * warning message will be printed about it.
1953 	 */
1954 	if (tp->t_state & TS_MEUC) {
1955 		if (tp->t_eucleft) {	/* if in a multi-byte char already */
1956 			--tp->t_eucleft;
1957 			*tp->t_eucp++ = 0;	/* is a subsequent byte */
1958 			if (c < (uchar_t)0x20)
1959 				ldterm_eucwarn(tp);
1960 		} else { /* is the first byte of a multi-byte, or is ASCII */
1961 			if (ISASCII(c)) {
1962 				*tp->t_eucp++ =
1963 				    tp->t_csmethods.ldterm_dispwidth(c,
1964 				    (void *)tp, tp->t_modes.c_lflag & ECHOCTL);
1965 				tp->t_codeset = 0;
1966 			} else {
1967 				*tp->t_eucp++ =
1968 				    tp->t_csmethods.ldterm_dispwidth(c,
1969 				    (void *)tp, tp->t_modes.c_lflag & ECHOCTL);
1970 				tp->t_eucleft =
1971 				    tp->t_csmethods.ldterm_memwidth(c,
1972 				    (void *)tp) - 1;
1973 				tp->t_codeset = ldterm_codeset(
1974 				    tp->t_csdata.codeset_type, c);
1975 			}
1976 		}
1977 	}
1978 	/*
1979 	 * AT&T is concerned about the following but we aren't since
1980 	 * we have already shipped code that works.
1981 	 *
1982 	 * EOL2/XCASE should be conditioned with IEXTEN to be truly
1983 	 * POSIX conformant. This is going to cause problems for
1984 	 * pre-SVR4.0 programs that don't know about IEXTEN. Hence
1985 	 * EOL2/IEXTEN is not conditioned with IEXTEN.
1986 	 */
1987 	if (!(tp->t_state & TS_SLNCH) &&
1988 	    (c == '\n' || (c != '\0' && (c == tp->t_modes.c_cc[VEOL] ||
1989 	    (c == tp->t_modes.c_cc[VEOL2]))))) {
1990 		/*
1991 		 * || ((tp->t_modes.c_lflag & IEXTEN) && c ==
1992 		 * tp->t_modes.c_cc[VEOL2]))))) {
1993 		 */
1994 		/*
1995 		 * It's a line-termination character; send the line
1996 		 * up the stream.
1997 		 */
1998 		bpt->b_datap->db_type = M_DATA;
1999 		ldterm_msg_upstream(q, tp);
2000 		if (tp->t_state & TS_MEUC) {
2001 			ASSERT(tp->t_eucp_mp);
2002 			tp->t_eucp = tp->t_eucp_mp->b_rptr;
2003 		}
2004 		if ((bpt = newmsg(tp)) == NULL)
2005 			goto out;
2006 	} else {
2007 		/*
2008 		 * Character was escaped with LNEXT.
2009 		 */
2010 		if (tp->t_rocount++ == 0)
2011 			tp->t_rocol = tp->t_col;
2012 		tp->t_state &= ~(TS_SLNCH|TS_QUOT);
2013 		/*
2014 		 * If the current character is a single byte and single
2015 		 * column character and it is the backslash character and
2016 		 * IEXTEN, then the state will have TS_QUOT.
2017 		 */
2018 		if ((c == '\\') && (tp->t_modes.c_lflag & IEXTEN) &&
2019 		    (!(tp->t_state & TS_MEUC) ||
2020 		    ((tp->t_state & TS_MEUC) && (!tp->t_eucleft))))
2021 			tp->t_state |= TS_QUOT;
2022 	}
2023 
2024 	/*
2025 	 * Echo it.
2026 	 */
2027 	if (tp->t_state & TS_ERASE) {
2028 		tp->t_state &= ~TS_ERASE;
2029 		if (tp->t_modes.c_lflag & ECHO)
2030 			ldterm_outchar('/', wrq, ebsize, tp);
2031 	}
2032 	if (tp->t_modes.c_lflag & ECHO)
2033 		(void) ldterm_echo(c, wrq, ebsize, tp);
2034 	else {
2035 		/*
2036 		 * Echo NL when ECHO turned off, if ECHONL flag is
2037 		 * set.
2038 		 */
2039 		if (c == '\n' && (tp->t_modes.c_lflag & ECHONL))
2040 			ldterm_outchar(c, wrq, ebsize, tp);
2041 	}
2042 
2043 out:
2044 
2045 	return (bpt);
2046 }
2047 
2048 
2049 static int
2050 ldterm_unget(ldtermstd_state_t *tp)
2051 {
2052 	mblk_t *bpt;
2053 
2054 	if ((bpt = tp->t_endmsg) == NULL)
2055 		return (-1);	/* no buffers */
2056 	if (bpt->b_rptr == bpt->b_wptr)
2057 		return (-1);	/* zero-length record */
2058 	tp->t_msglen--;		/* one fewer character */
2059 	return (*--bpt->b_wptr);
2060 }
2061 
2062 
2063 static void
2064 ldterm_trim(ldtermstd_state_t *tp)
2065 {
2066 	mblk_t *bpt;
2067 	mblk_t *bp;
2068 
2069 	ASSERT(tp->t_endmsg);
2070 	bpt = tp->t_endmsg;
2071 
2072 	if (bpt->b_rptr == bpt->b_wptr) {
2073 		/*
2074 		 * This mblk is now empty. Find the previous mblk;
2075 		 * throw this one away, unless it's the first one.
2076 		 */
2077 		bp = tp->t_message;
2078 		if (bp != bpt) {
2079 			while (bp->b_cont != bpt) {
2080 				ASSERT(bp->b_cont);
2081 				bp = bp->b_cont;
2082 			}
2083 			bp->b_cont = NULL;
2084 			freeb(bpt);
2085 			tp->t_endmsg = bp;	/* point to that mblk */
2086 		}
2087 	}
2088 }
2089 
2090 
2091 /*
2092  * Rubout one character from the current line being built for tp as
2093  * cleanly as possible.  q is the write queue for tp. Most of this
2094  * can't be applied to multi-byte processing.  We do our own thing
2095  * for that... See the "ldterm_eucerase" routine.  We never call
2096  * ldterm_rubout on a multi-byte or multi-column character.
2097  */
2098 static void
2099 ldterm_rubout(uchar_t c, queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2100 {
2101 	int tabcols;
2102 	static unsigned char crtrubout[] = "\b \b\b \b";
2103 #define	RUBOUT1	&crtrubout[3]	/* rub out one position */
2104 #define	RUBOUT2	&crtrubout[0]	/* rub out two positions */
2105 
2106 	if (!(tp->t_modes.c_lflag & ECHO))
2107 		return;
2108 	if (tp->t_modes.c_lflag & ECHOE) {
2109 		/*
2110 		 * "CRT rubout"; try erasing it from the screen.
2111 		 */
2112 		if (tp->t_rocount == 0) {
2113 			/*
2114 			 * After the character being erased was
2115 			 * echoed, some data was written to the
2116 			 * terminal; we can't erase it cleanly, so we
2117 			 * just reprint the whole line as if the user
2118 			 * had typed the reprint character.
2119 			 */
2120 			ldterm_reprint(q, ebsize, tp);
2121 			return;
2122 		} else {
2123 			/*
2124 			 * XXX what about escaped characters?
2125 			 */
2126 			switch (typetab[c]) {
2127 
2128 			case ORDINARY:
2129 				if ((tp->t_modes.c_lflag & XCASE) &&
2130 				    omaptab[c])
2131 					ldterm_outstring(RUBOUT1, 3, q, ebsize,
2132 					    tp);
2133 				ldterm_outstring(RUBOUT1, 3, q, ebsize, tp);
2134 				break;
2135 
2136 			case VTAB:
2137 			case BACKSPACE:
2138 			case CONTROL:
2139 			case RETURN:
2140 			case NEWLINE:
2141 				if ((tp->t_modes.c_lflag & ECHOCTL) &&
2142 				    (tp->t_modes.c_lflag & IEXTEN))
2143 					ldterm_outstring(RUBOUT2, 6, q, ebsize,
2144 					    tp);
2145 				break;
2146 
2147 			case TAB:
2148 				if (tp->t_rocount < tp->t_msglen) {
2149 					/*
2150 					 * While the tab being erased was
2151 					 * expanded, some data was written
2152 					 * to the terminal; we can't erase
2153 					 * it cleanly, so we just reprint
2154 					 * the whole line as if the user
2155 					 * had typed the reprint character.
2156 					 */
2157 					ldterm_reprint(q, ebsize, tp);
2158 					return;
2159 				}
2160 				tabcols = ldterm_tabcols(tp);
2161 				while (--tabcols >= 0)
2162 					ldterm_outchar('\b', q, ebsize, tp);
2163 				break;
2164 			}
2165 		}
2166 	} else if ((tp->t_modes.c_lflag & ECHOPRT) &&
2167 	    (tp->t_modes.c_lflag & IEXTEN)) {
2168 		/*
2169 		 * "Printing rubout"; echo it between \ and /.
2170 		 */
2171 		if (!(tp->t_state & TS_ERASE)) {
2172 			ldterm_outchar('\\', q, ebsize, tp);
2173 			tp->t_state |= TS_ERASE;
2174 		}
2175 		(void) ldterm_echo(c, q, ebsize, tp);
2176 	} else
2177 		(void) ldterm_echo(tp->t_modes.c_cc[VERASE], q, ebsize, tp);
2178 	tp->t_rocount--;	/* we "unechoed" this character */
2179 }
2180 
2181 
2182 /*
2183  * Find the number of characters the tab we just deleted took up by
2184  * zipping through the current line and recomputing the column
2185  * number.
2186  */
2187 static int
2188 ldterm_tabcols(ldtermstd_state_t *tp)
2189 {
2190 	int col;
2191 	int i;
2192 	mblk_t *bp;
2193 	unsigned char *readp, *endp;
2194 	unsigned char c;
2195 	uchar_t *startp;
2196 	char errflg;
2197 	uchar_t u8[LDTERM_CS_MAX_BYTE_LENGTH];
2198 
2199 	col = tp->t_rocol;
2200 	/*
2201 	 * If we're doing multi-byte stuff, zip through the list of
2202 	 * widths to figure out where we are (we've kept track in most
2203 	 * cases).
2204 	 */
2205 	if (tp->t_state & TS_MEUC) {
2206 		ASSERT(tp->t_eucp_mp);
2207 		bp = tp->t_message;
2208 		startp = bp->b_datap->db_base;
2209 		readp = tp->t_eucp_mp->b_rptr;
2210 		endp = tp->t_eucp;
2211 		errflg = (char)0;
2212 		while (readp < endp) {
2213 			switch (*readp) {
2214 			case EUC_TWIDTH:	/* it's a tab */
2215 				col |= 07;	/* bump up */
2216 				col++;
2217 				break;
2218 			case EUC_BSWIDTH:	/* backspace */
2219 				if (col)
2220 					col--;
2221 				break;
2222 			case EUC_NLWIDTH:	/* newline */
2223 				if (tp->t_modes.c_oflag & ONLRET)
2224 					col = 0;
2225 				break;
2226 			case EUC_CRWIDTH:	/* return */
2227 				col = 0;
2228 				break;
2229 			case UNKNOWN_WIDTH:	/* UTF-8 unknown width */
2230 				if (tp->t_csdata.codeset_type !=
2231 				    LDTERM_CS_TYPE_UTF8 || errflg) {
2232 					*readp = 1;
2233 					col++;
2234 					break;
2235 				}
2236 				/*
2237 				 * Collect the current UTF-8 character bytes
2238 				 * from (possibly multiple) data buffers so
2239 				 * that we can figure out the display width.
2240 				 */
2241 				u8[0] = *startp;
2242 				for (i = 1; (i < LDTERM_CS_MAX_BYTE_LENGTH) &&
2243 				    (*(readp + i) == 0); i++) {
2244 					startp++;
2245 					if (startp >= bp->b_datap->db_lim) {
2246 						if (bp->b_cont) {
2247 							bp = bp->b_cont;
2248 							startp =
2249 							    bp->b_datap->
2250 							    db_base;
2251 						} else {
2252 							*readp = 1;
2253 							col++;
2254 							break;
2255 						}
2256 					}
2257 					u8[i] = *startp;
2258 				}
2259 
2260 				/* tp->t_eucp_mp contains wrong info?? */
2261 				if (*readp == 1)
2262 					break;
2263 
2264 				*readp = ldterm_utf8_width(u8, i);
2265 
2266 				col += *readp;
2267 				readp += (i - 1);
2268 				break;
2269 			default:
2270 				col += *readp;
2271 				break;
2272 			}
2273 			++readp;
2274 			++startp;
2275 			if (startp >= bp->b_datap->db_lim) {
2276 				if (bp->b_cont) {
2277 					bp = bp->b_cont;
2278 					startp = bp->b_datap->db_base;
2279 				} else {
2280 					/*
2281 					 * This will happen only if
2282 					 * tp->t_eucp_mp contains wrong
2283 					 * display width info.
2284 					 */
2285 					errflg = (char)1;
2286 					startp--;
2287 				}
2288 			}
2289 		}
2290 		goto eucout;	/* finished! */
2291 	}
2292 	bp = tp->t_message;
2293 	do {
2294 		readp = bp->b_rptr;
2295 		while (readp < bp->b_wptr) {
2296 			c = *readp++;
2297 			if ((tp->t_modes.c_lflag & ECHOCTL) &&
2298 			    (tp->t_modes.c_lflag & IEXTEN)) {
2299 				if (c <= 037 && c != '\t' && c != '\n' ||
2300 				    c == 0177) {
2301 					col += 2;
2302 					continue;
2303 				}
2304 			}
2305 			/*
2306 			 * Column position calculated here.
2307 			 */
2308 			switch (typetab[c]) {
2309 
2310 				/*
2311 				 * Ordinary characters; advance by
2312 				 * one.
2313 				 */
2314 			case ORDINARY:
2315 				col++;
2316 				break;
2317 
2318 				/*
2319 				 * Non-printing characters; nothing
2320 				 * happens.
2321 				 */
2322 			case CONTROL:
2323 				break;
2324 
2325 				/* Backspace */
2326 			case BACKSPACE:
2327 				if (col != 0)
2328 					col--;
2329 				break;
2330 
2331 				/* Newline; column depends on flags. */
2332 			case NEWLINE:
2333 				if (tp->t_modes.c_oflag & ONLRET)
2334 					col = 0;
2335 				break;
2336 
2337 				/* tab */
2338 			case TAB:
2339 				col |= 07;
2340 				col++;
2341 				break;
2342 
2343 				/* vertical motion */
2344 			case VTAB:
2345 				break;
2346 
2347 				/* carriage return */
2348 			case RETURN:
2349 				col = 0;
2350 				break;
2351 			}
2352 		}
2353 	} while ((bp = bp->b_cont) != NULL);	/* next block, if any */
2354 
2355 	/*
2356 	 * "col" is now the column number before the tab. "tp->t_col"
2357 	 * is still the column number after the tab, since we haven't
2358 	 * erased the tab yet. Thus "tp->t_col - col" is the number
2359 	 * of positions the tab moved.
2360 	 */
2361 eucout:
2362 	col = tp->t_col - col;
2363 	if (col > 8)
2364 		col = 8;	/* overflow screw */
2365 	return (col);
2366 }
2367 
2368 
2369 /*
2370  * Erase a single character; We ONLY ONLY deal with ASCII or
2371  * single-column single-byte codeset character.  For multi-byte characters,
2372  * see "ldterm_csi_erase".
2373  */
2374 static void
2375 ldterm_erase(queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2376 {
2377 	int c;
2378 
2379 	if ((c = ldterm_unget(tp)) != -1) {
2380 		ldterm_rubout((unsigned char) c, q, ebsize, tp);
2381 		ldterm_trim(tp);
2382 		if (tp->t_state & TS_MEUC)
2383 			--tp->t_eucp;
2384 	}
2385 }
2386 
2387 
2388 /*
2389  * Erase an entire word, single-byte EUC only please.
2390  */
2391 static void
2392 ldterm_werase(queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2393 {
2394 	int c;
2395 
2396 	/*
2397 	 * Erase trailing white space, if any.
2398 	 */
2399 	while ((c = ldterm_unget(tp)) == ' ' || c == '\t') {
2400 		ldterm_rubout((unsigned char) c, q, ebsize, tp);
2401 		ldterm_trim(tp);
2402 	}
2403 
2404 	/*
2405 	 * Erase non-white-space characters, if any.
2406 	 */
2407 	while (c != -1 && c != ' ' && c != '\t') {
2408 		ldterm_rubout((unsigned char) c, q, ebsize, tp);
2409 		ldterm_trim(tp);
2410 		c = ldterm_unget(tp);
2411 	}
2412 	if (c != -1) {
2413 		/*
2414 		 * We removed one too many characters; put the last
2415 		 * one back.
2416 		 */
2417 		tp->t_endmsg->b_wptr++;	/* put 'c' back */
2418 		tp->t_msglen++;
2419 	}
2420 }
2421 
2422 
2423 /*
2424  * ldterm_csi_werase - This is multi-byte equivalent of "word erase".
2425  * "Word erase" only makes sense in languages which space between words,
2426  * and it's presumptuous for us to attempt "word erase" when we don't
2427  * know anything about what's really going on.  It makes no sense for
2428  * many languages, as the criteria for defining words and tokens may
2429  * be completely different.
2430  *
2431  * In the TS_MEUC case (which is how we got here), we define a token to
2432  * be space- or tab-delimited, and erase one of them.  It helps to
2433  * have this for command lines, but it's otherwise useless for text
2434  * editing applications; you need more sophistication than we can
2435  * provide here.
2436  */
2437 static void
2438 ldterm_csi_werase(queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2439 {
2440 	int c, i;
2441 	int len;
2442 	uchar_t *ip;
2443 	uchar_t	u8[LDTERM_CS_MAX_BYTE_LENGTH];
2444 	uchar_t	u8_2[LDTERM_CS_MAX_BYTE_LENGTH];
2445 
2446 	/*
2447 	 * ip points to the width of the actual bytes.  t_eucp points
2448 	 * one byte beyond, where the next thing will be inserted.
2449 	 */
2450 	ip = tp->t_eucp - 1;
2451 	/*
2452 	 * Erase trailing white space, if any.
2453 	 */
2454 	while ((c = ldterm_unget(tp)) == ' ' || c == '\t') {
2455 		tp->t_eucp--;
2456 		ldterm_rubout((unsigned char) c, q, ebsize, tp);
2457 		ldterm_trim(tp);
2458 		--ip;
2459 	}
2460 
2461 	/*
2462 	 * Erase non-white-space characters, if any.  The outer loop
2463 	 * bops through each byte in the buffer. Multi-byte is removed, as
2464 	 * is ASCII, one byte at a time. The inner loop (for) is only
2465 	 * executed for first bytes of multi-byte.  The inner loop erases
2466 	 * the number of columns required for the multi-byte char.  We check
2467 	 * for ASCII first, and ldterm_rubout knows about ASCII.
2468 	 */
2469 	len = 0;
2470 	while (c != -1 && c != ' ' && c != '\t') {
2471 		tp->t_eucp--;
2472 		if (len < LDTERM_CS_MAX_BYTE_LENGTH) {
2473 			u8[len++] = (uchar_t)c;
2474 		}
2475 		/*
2476 		 * Unlike EUC, except the leading byte, some bytes of
2477 		 * a non-EUC multi-byte characters are in the ASCII code
2478 		 * range, esp., 0x41 ~ 0x7a. Thus, we cannot simply check
2479 		 * ISASCII().
2480 		 * Checking the (*ip == 1 || *ip == 2 || *ip > UNKNOWN_WIDTH)
2481 		 * will ensure that it is a single byte character (even though
2482 		 * it is on display width not byte length) and can be further
2483 		 * checked whether it is an ASCII character or not.
2484 		 *
2485 		 * When ECHOCTL is on and 'c' is an ASCII control character,
2486 		 * *ip == 2 happens.
2487 		 */
2488 		if ((*ip == 1 || *ip == 2 || *ip > UNKNOWN_WIDTH) &&
2489 		    ISASCII(c)) {
2490 			ldterm_rubout((unsigned char) c, q, ebsize, tp);
2491 			len = 0;
2492 		} else if (*ip) {
2493 			if (*ip == UNKNOWN_WIDTH) {
2494 				if (tp->t_csdata.codeset_type ==
2495 				    LDTERM_CS_TYPE_UTF8) {
2496 					for (i = 0; i < len; i++)
2497 						u8_2[i] = u8[len - i - 1];
2498 					*ip = ldterm_utf8_width(u8_2, len);
2499 				} else {
2500 					*ip = 1;
2501 				}
2502 			}
2503 			/*
2504 			 * erase for number of columns required for
2505 			 * this multi-byte character. Hopefully, matches
2506 			 * ldterm_dispwidth!
2507 			 */
2508 			for (i = 0; i < (int)*ip; i++)
2509 				ldterm_rubout(' ', q, ebsize, tp);
2510 			len = 0;
2511 		}
2512 		ldterm_trim(tp);
2513 		--ip;
2514 		c = ldterm_unget(tp);
2515 	}
2516 	if (c != -1) {
2517 		/*
2518 		 * We removed one too many characters; put the last
2519 		 * one back.
2520 		 */
2521 		tp->t_endmsg->b_wptr++;	/* put 'c' back */
2522 		tp->t_msglen++;
2523 	}
2524 }
2525 
2526 
2527 /*
2528  * Kill an entire line, erasing each character one-by-one (if ECHOKE
2529  * is set) or just echoing the kill character, followed by a newline
2530  * (if ECHOK is set).  Multi-byte processing is included here.
2531  */
2532 
2533 static void
2534 ldterm_kill(queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2535 {
2536 	int c, i;
2537 	int len;
2538 	uchar_t *ip;
2539 	uchar_t u8[LDTERM_CS_MAX_BYTE_LENGTH];
2540 	uchar_t u8_2[LDTERM_CS_MAX_BYTE_LENGTH];
2541 
2542 	if ((tp->t_modes.c_lflag & ECHOKE) &&
2543 	    (tp->t_modes.c_lflag & IEXTEN) &&
2544 	    (tp->t_msglen == tp->t_rocount)) {
2545 		if (tp->t_state & TS_MEUC) {
2546 			ip = tp->t_eucp - 1;
2547 			/*
2548 			 * This loop similar to "ldterm_csi_werase" above.
2549 			 */
2550 			len = 0;
2551 			while ((c = ldterm_unget(tp)) != (-1)) {
2552 				tp->t_eucp--;
2553 				if (len < LDTERM_CS_MAX_BYTE_LENGTH) {
2554 					u8[len++] = (uchar_t)c;
2555 				}
2556 				if ((*ip == 1 || *ip == 2 ||
2557 				    *ip > UNKNOWN_WIDTH) && ISASCII(c)) {
2558 					ldterm_rubout((unsigned char) c, q,
2559 					    ebsize, tp);
2560 					len = 0;
2561 				} else if (*ip) {
2562 					if (*ip == UNKNOWN_WIDTH) {
2563 						if (tp->t_csdata.codeset_type
2564 						    == LDTERM_CS_TYPE_UTF8) {
2565 							for (i = 0; i < len;
2566 							    i++)
2567 								u8_2[i] =
2568 								    u8[len-i-1];
2569 							*ip = ldterm_utf8_width(
2570 							    u8_2, len);
2571 						} else {
2572 							*ip = 1;
2573 						}
2574 					}
2575 					for (i = 0; i < (int)*ip; i++)
2576 						ldterm_rubout(' ', q, ebsize,
2577 						    tp);
2578 					len = 0;
2579 				}
2580 				ldterm_trim(tp);
2581 				--ip;
2582 			}
2583 		} else {
2584 			while ((c = ldterm_unget(tp)) != -1) {
2585 				ldterm_rubout((unsigned char) c, q, ebsize, tp);
2586 				ldterm_trim(tp);
2587 			}
2588 		}
2589 	} else {
2590 		(void) ldterm_echo(tp->t_modes.c_cc[VKILL], q, ebsize, tp);
2591 		if (tp->t_modes.c_lflag & ECHOK)
2592 			(void) ldterm_echo('\n', q, ebsize, tp);
2593 		while (ldterm_unget(tp) != -1) {
2594 			if (tp->t_state & TS_MEUC)
2595 				--tp->t_eucp;
2596 			ldterm_trim(tp);
2597 		}
2598 		tp->t_rocount = 0;
2599 		if (tp->t_state & TS_MEUC)
2600 			tp->t_eucp = tp->t_eucp_mp->b_rptr;
2601 	}
2602 	tp->t_state &= ~(TS_QUOT|TS_ERASE|TS_SLNCH);
2603 }
2604 
2605 
2606 /*
2607  * Reprint the current input line. We assume c_cc has already been
2608  * checked. XXX just the current line, not the whole queue? What
2609  * about DEFECHO mode?
2610  */
2611 static void
2612 ldterm_reprint(queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2613 {
2614 	mblk_t *bp;
2615 	unsigned char *readp;
2616 
2617 	if (tp->t_modes.c_cc[VREPRINT] != (unsigned char) 0)
2618 		(void) ldterm_echo(tp->t_modes.c_cc[VREPRINT], q, ebsize, tp);
2619 	ldterm_outchar('\n', q, ebsize, tp);
2620 
2621 	bp = tp->t_message;
2622 	do {
2623 		readp = bp->b_rptr;
2624 		while (readp < bp->b_wptr)
2625 			(void) ldterm_echo(*readp++, q, ebsize, tp);
2626 	} while ((bp = bp->b_cont) != NULL);	/* next block, if any */
2627 
2628 	tp->t_state &= ~TS_ERASE;
2629 	tp->t_rocount = tp->t_msglen;	/* we reechoed the entire line */
2630 	tp->t_rocol = 0;
2631 }
2632 
2633 
2634 /*
2635  * Non canonical processing. Called with q locked from  ldtermrsrv.
2636  *
2637  */
2638 static mblk_t *
2639 ldterm_dononcanon(mblk_t *bp, mblk_t *bpt, size_t ebsize, queue_t *q,
2640     ldtermstd_state_t *tp)
2641 {
2642 	queue_t *wrq = WR(q);
2643 	unsigned char *rptr;
2644 	size_t bytes_in_bp;
2645 	size_t roomleft;
2646 	size_t bytes_to_move;
2647 	int free_flag = 0;
2648 
2649 	if (tp->t_modes.c_lflag & (ECHO|ECHONL|IEXTEN)) {
2650 		unsigned char *wptr;
2651 		unsigned char c;
2652 
2653 		/*
2654 		 * Either we must echo the characters, or we must
2655 		 * echo NL, or we must check for VLNEXT. Process
2656 		 * characters one at a time.
2657 		 */
2658 		rptr = bp->b_rptr;
2659 		wptr = bp->b_rptr;
2660 		while (rptr < bp->b_wptr) {
2661 			c = *rptr++;
2662 			/*
2663 			 * If this character is the literal next
2664 			 * character, echo it as '^' and backspace
2665 			 * over it if echoing is enabled, indicate
2666 			 * that the next character is to be treated
2667 			 * literally, and remove the LNEXT from the
2668 			 * input stream.
2669 			 *
2670 			 * If the *previous* character was the literal
2671 			 * next character, don't check whether this
2672 			 * is a literal next or not.
2673 			 */
2674 			if ((tp->t_modes.c_lflag & IEXTEN) &&
2675 			    !(tp->t_state & TS_SLNCH) &&
2676 			    c != _POSIX_VDISABLE &&
2677 			    c == tp->t_modes.c_cc[VLNEXT]) {
2678 				if (tp->t_modes.c_lflag & ECHO)
2679 					ldterm_outstring(
2680 					    (unsigned char *)"^\b",
2681 					    2, wrq, ebsize, tp);
2682 				tp->t_state |= TS_SLNCH;
2683 				continue;	/* and ignore it */
2684 			}
2685 			/*
2686 			 * Not a "literal next" character, so it
2687 			 * should show up as input. If it was
2688 			 * literal-nexted, turn off the literal-next
2689 			 * flag.
2690 			 */
2691 			tp->t_state &= ~TS_SLNCH;
2692 			*wptr++ = c;
2693 			if (tp->t_modes.c_lflag & ECHO) {
2694 				/*
2695 				 * Echo the character.
2696 				 */
2697 				(void) ldterm_echo(c, wrq, ebsize, tp);
2698 			} else if (tp->t_modes.c_lflag & ECHONL) {
2699 				/*
2700 				 * Echo NL, even though ECHO is not
2701 				 * set.
2702 				 */
2703 				if (c == '\n')
2704 					ldterm_outchar('\n', wrq, 1, tp);
2705 			}
2706 		}
2707 		bp->b_wptr = wptr;
2708 	} else {
2709 		/*
2710 		 * If there are any characters in this buffer, and
2711 		 * the first of them was literal-nexted, turn off the
2712 		 * literal-next flag.
2713 		 */
2714 		if (bp->b_rptr != bp->b_wptr)
2715 			tp->t_state &= ~TS_SLNCH;
2716 	}
2717 
2718 	ASSERT(bp->b_wptr >= bp->b_rptr);
2719 	bytes_in_bp = bp->b_wptr - bp->b_rptr;
2720 	rptr = bp->b_rptr;
2721 	while (bytes_in_bp != 0) {
2722 		roomleft = bpt->b_datap->db_lim - bpt->b_wptr;
2723 		if (roomleft == 0) {
2724 			/*
2725 			 * No more room in this mblk; save this one
2726 			 * away, and allocate a new one.
2727 			 */
2728 			if ((bpt = allocb(IBSIZE, BPRI_MED)) == NULL) {
2729 				freeb(bp);
2730 				DEBUG4(("ldterm_do_noncanon: allcob failed\n"));
2731 				return (bpt);
2732 			}
2733 			/*
2734 			 * Chain the new one to the end of the old
2735 			 * one, and mark it as the last block in the
2736 			 * current lump.
2737 			 */
2738 			tp->t_endmsg->b_cont = bpt;
2739 			tp->t_endmsg = bpt;
2740 			roomleft = IBSIZE;
2741 		}
2742 		DEBUG5(("roomleft=%d, bytes_in_bp=%d, tp->t_rd_request=%d\n",
2743 		    roomleft, bytes_in_bp, tp->t_rd_request));
2744 		/*
2745 		 * if there is a read pending before this data got
2746 		 * here move bytes according to the minimum of room
2747 		 * left in this buffer, bytes in the message and byte
2748 		 * count requested in the read. If there is no read
2749 		 * pending, move the minimum of the first two
2750 		 */
2751 		if (tp->t_rd_request == 0)
2752 			bytes_to_move = MIN(roomleft, bytes_in_bp);
2753 		else
2754 			bytes_to_move =
2755 			    MIN(MIN(roomleft, bytes_in_bp), tp->t_rd_request);
2756 		DEBUG5(("Bytes to move = %lu\n", bytes_to_move));
2757 		if (bytes_to_move == 0)
2758 			break;
2759 		bcopy(rptr, bpt->b_wptr, bytes_to_move);
2760 		bpt->b_wptr += bytes_to_move;
2761 		rptr += bytes_to_move;
2762 		tp->t_msglen += bytes_to_move;
2763 		bytes_in_bp -= bytes_to_move;
2764 	}
2765 	if (bytes_in_bp == 0) {
2766 		DEBUG4(("bytes_in_bp is zero\n"));
2767 		freeb(bp);
2768 	} else
2769 		free_flag = 1;	/* for debugging olny */
2770 
2771 	DEBUG4(("ldterm_do_noncanon: VMIN = %d, VTIME = %d, msglen = %d, \
2772 		tid = %d\n", V_MIN, V_TIME, tp->t_msglen, tp->t_vtid));
2773 	/*
2774 	 * If there is a pending read request at the stream head we
2775 	 * need to do VMIN/VTIME processing. The four possible cases
2776 	 * are:
2777 	 *	MIN = 0, TIME > 0
2778 	 *	MIN = >, TIME = 0
2779 	 *	MIN > 0, TIME > 0
2780 	 *	MIN = 0, TIME = 0
2781 	 * If we can satisfy VMIN, send it up, and start a new
2782 	 * timer if necessary.  These four cases of VMIN/VTIME
2783 	 * are also dealt with in the write side put routine
2784 	 * when the M_READ is first seen.
2785 	 */
2786 
2787 	DEBUG4(("Incoming data while M_READ'ing\n"));
2788 	/*
2789 	 * Case 1:  Any data will satisfy the read, so send
2790 	 * it upstream.
2791 	 */
2792 	if (V_MIN == 0 && V_TIME > 0) {
2793 		if (tp->t_msglen)
2794 			vmin_satisfied(q, tp, 1);
2795 		else {
2796 			/* EMPTY */
2797 			DEBUG4(("ldterm_do_noncanon called, but no data!\n"));
2798 		}
2799 		/*
2800 		 * Case 2:  This should never time out, so
2801 		 * until there's enough data, do nothing.
2802 		 */
2803 	} else if (V_MIN > 0 && V_TIME == 0) {
2804 		if (tp->t_msglen >= (int)V_MIN)
2805 			vmin_satisfied(q, tp, 1);
2806 
2807 		/*
2808 		 * Case 3:  If MIN is satisfied, send it up.
2809 		 * Also, remember to start a new timer *every*
2810 		 * time we see something if MIN isn't
2811 		 * safisfied
2812 		 */
2813 	} else if (V_MIN > 0 && V_TIME > 0) {
2814 		if (tp->t_msglen >= (int)V_MIN)
2815 			vmin_satisfied(q, tp, 1);
2816 		else
2817 			vmin_settimer(q);
2818 		/*
2819 		 * Case 4:  Not possible.  This request
2820 		 * should always be satisfied from the write
2821 		 * side, left here for debugging.
2822 		 */
2823 	} else {	/* V_MIN == 0 && V_TIME == 0 */
2824 			vmin_satisfied(q, tp, 1);
2825 	}
2826 
2827 	if (free_flag) {
2828 		/* EMPTY */
2829 		DEBUG4(("CAUTION message block not freed\n"));
2830 	}
2831 	return (newmsg(tp));
2832 }
2833 
2834 
2835 /*
2836  * Echo a typed byte to the terminal.  Returns the number of bytes
2837  * printed. Bytes of EUC characters drop through the ECHOCTL stuff
2838  * and are just output as themselves.
2839  */
2840 static int
2841 ldterm_echo(uchar_t c, queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
2842 {
2843 	int i;
2844 
2845 	if (!(tp->t_modes.c_lflag & ECHO))
2846 		return (0);
2847 	i = 0;
2848 
2849 	/*
2850 	 * Echo control characters (c <= 37) only if the ECHOCTRL
2851 	 * flag is set as ^X.
2852 	 */
2853 
2854 	if ((tp->t_modes.c_lflag & ECHOCTL) &&
2855 	    (tp->t_modes.c_lflag & IEXTEN)) {
2856 		if (c <= 037 && c != '\t' && c != '\n') {
2857 			ldterm_outchar('^', q, ebsize, tp);
2858 			i++;
2859 			if (tp->t_modes.c_oflag & OLCUC)
2860 				c += 'a' - 1;
2861 			else
2862 				c += 'A' - 1;
2863 		} else if (c == 0177) {
2864 			ldterm_outchar('^', q, ebsize, tp);
2865 			i++;
2866 			c = '?';
2867 		}
2868 		ldterm_outchar(c, q, ebsize, tp);
2869 		return (i + 1);
2870 		/* echo only special control character and the Bell */
2871 	} else if ((c > 037 && c != 0177) || c == '\t' || c == '\n' ||
2872 	    c == '\r' || c == '\b' || c == 007 ||
2873 	    c == tp->t_modes.c_cc[VKILL]) {
2874 		ldterm_outchar(c, q, ebsize, tp);
2875 		return (i + 1);
2876 	}
2877 	return (i);
2878 }
2879 
2880 
2881 /*
2882  * Put a character on the output queue.
2883  */
2884 static void
2885 ldterm_outchar(uchar_t c, queue_t *q, size_t bsize, ldtermstd_state_t *tp)
2886 {
2887 	mblk_t *curbp;
2888 
2889 	/*
2890 	 * Don't even look at the characters unless we have something
2891 	 * useful to do with them.
2892 	 */
2893 	if ((tp->t_modes.c_oflag & OPOST) ||
2894 	    ((tp->t_modes.c_lflag & XCASE) &&
2895 	    (tp->t_modes.c_lflag & ICANON))) {
2896 		mblk_t *mp;
2897 
2898 		if ((mp = allocb(4, BPRI_HI)) == NULL) {
2899 			cmn_err(CE_WARN,
2900 			    "ldterm: (ldterm_outchar) out of blocks");
2901 			return;
2902 		}
2903 		*mp->b_wptr++ = c;
2904 		mp = ldterm_output_msg(q, mp, &tp->t_echomp, tp, bsize, 1);
2905 		if (mp != NULL)
2906 			freemsg(mp);
2907 
2908 	} else {
2909 		if ((curbp = tp->t_echomp) != NULL) {
2910 			while (curbp->b_cont != NULL)
2911 				curbp = curbp->b_cont;
2912 			if (curbp->b_datap->db_lim == curbp->b_wptr) {
2913 				mblk_t *newbp;
2914 
2915 				if ((newbp = allocb(bsize, BPRI_HI)) == NULL) {
2916 					cmn_err(CE_WARN,
2917 					    "ldterm_outchar: out of blocks");
2918 					return;
2919 				}
2920 				curbp->b_cont = newbp;
2921 				curbp = newbp;
2922 			}
2923 		} else {
2924 			if ((curbp = allocb(bsize, BPRI_HI)) == NULL) {
2925 				cmn_err(CE_WARN,
2926 				    "ldterm_outchar: out of blocks");
2927 				return;
2928 			}
2929 			tp->t_echomp = curbp;
2930 		}
2931 		*curbp->b_wptr++ = c;
2932 	}
2933 }
2934 
2935 
2936 /*
2937  * Copy a string, of length len, to the output queue.
2938  */
2939 static void
2940 ldterm_outstring(uchar_t *cp, int len, queue_t *q, size_t bsize,
2941     ldtermstd_state_t *tp)
2942 {
2943 	while (len > 0) {
2944 		ldterm_outchar(*cp++, q, bsize, tp);
2945 		len--;
2946 	}
2947 }
2948 
2949 
2950 static mblk_t *
2951 newmsg(ldtermstd_state_t *tp)
2952 {
2953 	mblk_t *bp;
2954 
2955 	/*
2956 	 * If no current message, allocate a block for it.
2957 	 */
2958 	if ((bp = tp->t_endmsg) == NULL) {
2959 		if ((bp = allocb(IBSIZE, BPRI_MED)) == NULL) {
2960 			cmn_err(CE_WARN,
2961 			    "ldterm: (ldtermrsrv/newmsg) out of blocks");
2962 			return (bp);
2963 		}
2964 		tp->t_message = bp;
2965 		tp->t_endmsg = bp;
2966 	}
2967 	return (bp);
2968 }
2969 
2970 
2971 static void
2972 ldterm_msg_upstream(queue_t *q, ldtermstd_state_t *tp)
2973 {
2974 	ssize_t s;
2975 	mblk_t *bp;
2976 
2977 	bp = tp->t_message;
2978 	s = msgdsize(bp);
2979 	if (bp)
2980 		putnext(q, tp->t_message);
2981 
2982 	/*
2983 	 * update sysinfo canch character.
2984 	 */
2985 	if (CANON_MODE)
2986 		(void) drv_setparm(SYSCANC, s);
2987 	tp->t_message = NULL;
2988 	tp->t_endmsg = NULL;
2989 	tp->t_msglen = 0;
2990 	tp->t_rocount = 0;
2991 	tp->t_rd_request = 0;
2992 	if (tp->t_state & TS_MEUC) {
2993 		ASSERT(tp->t_eucp_mp);
2994 		tp->t_eucp = tp->t_eucp_mp->b_rptr;
2995 		/* can't reset everything, as we may have other input */
2996 	}
2997 }
2998 
2999 
3000 /*
3001  * Re-enable the write-side service procedure.  When an allocation
3002  * failure causes write-side processing to stall, we disable the
3003  * write side and arrange to call this function when allocation once
3004  * again becomes possible.
3005  */
3006 static void
3007 ldterm_wenable(void *addr)
3008 {
3009 	queue_t *q = addr;
3010 	ldtermstd_state_t *tp;
3011 
3012 	tp = (ldtermstd_state_t *)q->q_ptr;
3013 	/*
3014 	 * The bufcall is no longer pending.
3015 	 */
3016 	tp->t_wbufcid = 0;
3017 	enableok(q);
3018 	qenable(q);
3019 }
3020 
3021 
3022 /*
3023  * Line discipline output queue put procedure.  Attempts to process
3024  * the message directly and send it on downstream, queueing it only
3025  * if there's already something pending or if its downstream neighbor
3026  * is clogged.
3027  */
3028 static void
3029 ldtermwput(queue_t *q, mblk_t *mp)
3030 {
3031 	ldtermstd_state_t *tp;
3032 	unsigned char type = mp->b_datap->db_type;
3033 
3034 	tp = (ldtermstd_state_t *)q->q_ptr;
3035 
3036 	/*
3037 	 * Always process priority messages, regardless of whether or
3038 	 * not our queue is nonempty.
3039 	 */
3040 	if (type >= QPCTL) {
3041 		switch (type) {
3042 
3043 		case M_FLUSH:
3044 			/*
3045 			 * Get rid of it, see comment in
3046 			 * ldterm_dosig().
3047 			 */
3048 			if ((tp->t_state & TS_FLUSHWAIT) &&
3049 			    (*mp->b_rptr == FLUSHW)) {
3050 				tp->t_state &= ~TS_FLUSHWAIT;
3051 				freemsg(mp);
3052 				return;
3053 			}
3054 			/*
3055 			 * This is coming from above, so we only
3056 			 * handle the write queue here.  If FLUSHR is
3057 			 * set, it will get turned around at the
3058 			 * driver, and the read procedure will see it
3059 			 * eventually.
3060 			 */
3061 			if (*mp->b_rptr & FLUSHW) {
3062 				if ((tp->t_state & TS_ISPTSTTY) &&
3063 				    (*mp->b_rptr & FLUSHBAND))
3064 					flushband(q, *(mp->b_rptr + 1),
3065 					    FLUSHDATA);
3066 				else
3067 					flushq(q, FLUSHDATA);
3068 			}
3069 
3070 			putnext(q, mp);
3071 			/*
3072 			 * If a timed read is interrupted, there is
3073 			 * no way to cancel an existing M_READ
3074 			 * request.  We kludge by allowing a flush to
3075 			 * do so.
3076 			 */
3077 			if (tp->t_state & TS_MREAD)
3078 				vmin_satisfied(RD(q), tp, 0);
3079 			break;
3080 
3081 		case M_READ:
3082 			DEBUG1(("ldtermwmsg:M_READ RECEIVED\n"));
3083 			/*
3084 			 * Stream head needs data to satisfy timed
3085 			 * read. Has meaning only if ICANON flag is
3086 			 * off indicating raw mode
3087 			 */
3088 
3089 			DEBUG4((
3090 			    "M_READ: RAW_MODE=%d, CNT=%d, VMIN=%d, VTIME=%d\n",
3091 			    RAW_MODE, *(unsigned int *)mp->b_rptr, V_MIN,
3092 			    V_TIME));
3093 
3094 			tp->t_rd_request = *(unsigned int *)mp->b_rptr;
3095 
3096 			if (RAW_MODE) {
3097 				if (newmsg(tp) != NULL) {
3098 					/*
3099 					 * VMIN/VTIME processing...
3100 					 * The four possible cases are:
3101 					 *	MIN = 0, TIME > 0
3102 					 *	MIN = >, TIME = 0
3103 					 *	MIN > 0, TIME > 0
3104 					 *	MIN = 0, TIME = 0
3105 					 * These four conditions must be dealt
3106 					 * with on the read side as well in
3107 					 * ldterm_do_noncanon(). Set TS_MREAD
3108 					 * so that the read side will know
3109 					 * there is a pending read request
3110 					 * waiting at the stream head.  If we
3111 					 * can satisfy MIN do it here, rather
3112 					 * than on the read side.  If we can't,
3113 					 * start timers if necessary and let
3114 					 * the other side deal with it.
3115 					 *
3116 					 * We got another M_READ before the
3117 					 * pending one completed, cancel any
3118 					 * existing timeout.
3119 					 */
3120 					if (tp->t_state & TS_MREAD) {
3121 						vmin_satisfied(RD(q),
3122 						    tp, 0);
3123 					}
3124 					tp->t_state |= TS_MREAD;
3125 					/*
3126 					 * Case 1:  Any data will
3127 					 * satisfy read, otherwise
3128 					 * start timer
3129 					 */
3130 					if (V_MIN == 0 && V_TIME > 0) {
3131 						if (tp->t_msglen)
3132 							vmin_satisfied(RD(q),
3133 							    tp, 1);
3134 						else
3135 							vmin_settimer(RD(q));
3136 
3137 						/*
3138 						 * Case 2:  If we have enough
3139 						 * data, send up now.
3140 						 * Otherwise, the read side
3141 						 * should wait forever until MIN
3142 						 * is satisified.
3143 						 */
3144 					} else if (V_MIN > 0 && V_TIME == 0) {
3145 						if (tp->t_msglen >= (int)V_MIN)
3146 							vmin_satisfied(RD(q),
3147 							    tp, 1);
3148 
3149 						/*
3150 						 * Case 3:  If we can satisfy
3151 						 * the read, send it up. If we
3152 						 * don't have enough data, but
3153 						 * there is at least one char,
3154 						 * start a timer.  Otherwise,
3155 						 * let the read side start
3156 						 * the timer.
3157 						 */
3158 					} else if (V_MIN > 0 && V_TIME > 0) {
3159 						if (tp->t_msglen >= (int)V_MIN)
3160 							vmin_satisfied(RD(q),
3161 							    tp, 1);
3162 						else if (tp->t_msglen)
3163 							vmin_settimer(RD(q));
3164 						/*
3165 						 * Case 4:  Read returns
3166 						 * whatever data is available
3167 						 * or zero if none.
3168 						 */
3169 					} else { /* V_MIN == 0 && V_TIME == 0 */
3170 						vmin_satisfied(RD(q), tp, 1);
3171 					}
3172 
3173 				} else	/* should do bufcall, really! */
3174 					cmn_err(CE_WARN,
3175 					    "ldtermwmsg: out of blocks");
3176 			}
3177 			/*
3178 			 * pass M_READ down
3179 			 */
3180 			putnext(q, mp);
3181 			break;
3182 
3183 		default:
3184 			/* Pass it through unmolested. */
3185 			putnext(q, mp);
3186 			break;
3187 		}
3188 		return;
3189 	}
3190 	/*
3191 	 * If our queue is nonempty or there's a traffic jam
3192 	 * downstream, this message must get in line.
3193 	 */
3194 	if (q->q_first != NULL || !bcanputnext(q, mp->b_band)) {
3195 		/*
3196 		 * Exception: ioctls, except for those defined to
3197 		 * take effect after output has drained, should be
3198 		 * processed immediately.
3199 		 */
3200 		if (type == M_IOCTL) {
3201 			struct iocblk *iocp;
3202 
3203 			iocp = (struct iocblk *)mp->b_rptr;
3204 			switch (iocp->ioc_cmd) {
3205 
3206 				/*
3207 				 * Queue these.
3208 				 */
3209 			case TCSETSW:
3210 			case TCSETSF:
3211 			case TCSETAW:
3212 			case TCSETAF:
3213 			case TCSBRK:
3214 				break;
3215 
3216 				/*
3217 				 * Handle all others immediately.
3218 				 */
3219 			default:
3220 				(void) ldtermwmsg(q, mp);
3221 				return;
3222 			}
3223 		}
3224 		(void) putq(q, mp);
3225 		return;
3226 	}
3227 	/*
3228 	 * We can take the fast path through, by simply calling
3229 	 * ldtermwmsg to dispose of mp.
3230 	 */
3231 	(void) ldtermwmsg(q, mp);
3232 }
3233 
3234 
3235 /*
3236  * Line discipline output queue service procedure.
3237  */
3238 static void
3239 ldtermwsrv(queue_t *q)
3240 {
3241 	mblk_t *mp;
3242 
3243 	/*
3244 	 * We expect this loop to iterate at most once, but must be
3245 	 * prepared for more in case our upstream neighbor isn't
3246 	 * paying strict attention to what canput tells it.
3247 	 */
3248 	while ((mp = getq(q)) != NULL) {
3249 		/*
3250 		 * N.B.: ldtermwput has already handled high-priority
3251 		 * messages, so we don't have to worry about them
3252 		 * here. Hence, the putbq call is safe.
3253 		 */
3254 		if (!bcanputnext(q, mp->b_band)) {
3255 			(void) putbq(q, mp);
3256 			break;
3257 		}
3258 		if (!ldtermwmsg(q, mp)) {
3259 			/*
3260 			 * Couldn't handle the whole thing; give up
3261 			 * for now and wait to be rescheduled.
3262 			 */
3263 			break;
3264 		}
3265 	}
3266 }
3267 
3268 
3269 /*
3270  * Process the write-side message denoted by mp.  If mp can't be
3271  * processed completely (due to allocation failures), put the
3272  * residual unprocessed part on the front of the write queue, disable
3273  * the queue, and schedule a qbufcall to arrange to complete its
3274  * processing later.
3275  *
3276  * Return 1 if the message was processed completely and 0 if not.
3277  *
3278  * This routine is called from both ldtermwput and ldtermwsrv to do the
3279  * actual work of dealing with mp.  ldtermwput will have already
3280  * dealt with high priority messages.
3281  */
3282 static int
3283 ldtermwmsg(queue_t *q, mblk_t *mp)
3284 {
3285 	ldtermstd_state_t *tp;
3286 	mblk_t *residmp = NULL;
3287 	size_t size;
3288 
3289 	tp = (ldtermstd_state_t *)q->q_ptr;
3290 
3291 	switch (mp->b_datap->db_type) {
3292 
3293 	case M_IOCTL:
3294 		ldterm_do_ioctl(q, mp);
3295 		break;
3296 
3297 	case M_DATA:
3298 		{
3299 			mblk_t *omp = NULL;
3300 
3301 			if ((tp->t_modes.c_lflag & FLUSHO) &&
3302 			    (tp->t_modes.c_lflag & IEXTEN)) {
3303 				freemsg(mp);	/* drop on floor */
3304 				break;
3305 			}
3306 			tp->t_rocount = 0;
3307 			/*
3308 			 * Don't even look at the characters unless
3309 			 * we have something useful to do with them.
3310 			 */
3311 			if (((tp->t_modes.c_oflag & OPOST) ||
3312 			    ((tp->t_modes.c_lflag & XCASE) &&
3313 			    (tp->t_modes.c_lflag & ICANON))) &&
3314 			    (msgdsize(mp) || !(tp->t_state & TS_ISPTSTTY))) {
3315 				unsigned char band = mp->b_band;
3316 				short flag = mp->b_flag;
3317 
3318 				residmp = ldterm_output_msg(q, mp, &omp,
3319 				    tp, OBSIZE, 0);
3320 				if ((mp = omp) == NULL)
3321 					break;
3322 				mp->b_band |= band;
3323 				mp->b_flag |= flag;
3324 			}
3325 			/* Update sysinfo outch */
3326 			(void) drv_setparm(SYSOUTC, msgdsize(mp));
3327 			putnext(q, mp);
3328 			break;
3329 		}
3330 
3331 	default:
3332 		putnext(q, mp);	/* pass it through unmolested */
3333 		break;
3334 	}
3335 
3336 	if (residmp == NULL)
3337 		return (1);
3338 
3339 	/*
3340 	 * An allocation failure occurred that prevented the message
3341 	 * from being completely processed.  First, disable our
3342 	 * queue, since it's pointless to attempt further processing
3343 	 * until the allocation situation is resolved.  (This must
3344 	 * precede the putbq call below, which would otherwise mark
3345 	 * the queue to be serviced.)
3346 	 */
3347 	noenable(q);
3348 	/*
3349 	 * Stuff the remnant on our write queue so that we can
3350 	 * complete it later when times become less lean.  Note that
3351 	 * this sets QFULL, so that our upstream neighbor will be
3352 	 * blocked by flow control.
3353 	 */
3354 	(void) putbq(q, residmp);
3355 	/*
3356 	 * Schedule a qbufcall to re-enable the queue.  The failure
3357 	 * won't have been for an allocation of more than OBSIZE
3358 	 * bytes, so don't ask for more than that from bufcall.
3359 	 */
3360 	size = msgdsize(residmp);
3361 	if (size > OBSIZE)
3362 		size = OBSIZE;
3363 	if (tp->t_wbufcid)
3364 		qunbufcall(q, tp->t_wbufcid);
3365 	tp->t_wbufcid = qbufcall(q, size, BPRI_MED, ldterm_wenable, q);
3366 
3367 	return (0);
3368 }
3369 
3370 
3371 /*
3372  * Perform output processing on a message, accumulating the output
3373  * characters in a new message.
3374  */
3375 static mblk_t *
3376 ldterm_output_msg(queue_t *q, mblk_t *imp, mblk_t **omp,
3377     ldtermstd_state_t *tp, size_t bsize, int echoing)
3378 {
3379 	mblk_t *ibp;		/* block we're examining from input message */
3380 	mblk_t *obp;		/* block we're filling in output message */
3381 	mblk_t *cbp;		/* continuation block */
3382 	mblk_t *oobp;		/* old value of obp; valid if NEW_BLOCK fails */
3383 	mblk_t **contpp;	/* where to stuff ptr to newly-allocated blk */
3384 	unsigned char c, n;
3385 	int count, ctype;
3386 	ssize_t bytes_left;
3387 
3388 	mblk_t *bp;		/* block to stuff an M_DELAY message in */
3389 
3390 
3391 	/*
3392 	 * Allocate a new block into which to put bytes. If we can't,
3393 	 * we just drop the rest of the message on the floor. If x is
3394 	 * non-zero, just fall thru; failure requires cleanup before
3395 	 * going out
3396 	 */
3397 
3398 #define	NEW_BLOCK(x) \
3399 	{ \
3400 		oobp = obp; \
3401 		if ((obp = allocb(bsize, BPRI_MED)) == NULL) { \
3402 			if (x == 0) \
3403 				goto outofbufs; \
3404 		} else { \
3405 			*contpp = obp; \
3406 			contpp = &obp->b_cont; \
3407 			bytes_left = obp->b_datap->db_lim - obp->b_wptr; \
3408 		} \
3409 	}
3410 
3411 	ibp = imp;
3412 
3413 	/*
3414 	 * When we allocate the first block of a message, we should
3415 	 * stuff the pointer to it in "*omp".  All subsequent blocks
3416 	 * should have the pointer to them stuffed into the "b_cont"
3417 	 * field of the previous block.  "contpp" points to the place
3418 	 * where we should stuff the pointer.
3419 	 *
3420 	 * If we already have a message we're filling in, continue doing
3421 	 * so.
3422 	 */
3423 	if ((obp = *omp) != NULL) {
3424 		while (obp->b_cont != NULL)
3425 			obp = obp->b_cont;
3426 		contpp = &obp->b_cont;
3427 		bytes_left = obp->b_datap->db_lim - obp->b_wptr;
3428 	} else {
3429 		contpp = omp;
3430 		bytes_left = 0;
3431 	}
3432 
3433 	do {
3434 		while (ibp->b_rptr < ibp->b_wptr) {
3435 			/*
3436 			 * Make sure there's room for one more
3437 			 * character.  At most, we'll need "t_maxeuc"
3438 			 * bytes.
3439 			 */
3440 			if ((bytes_left < (int)tp->t_maxeuc)) {
3441 				/* LINTED */
3442 				NEW_BLOCK(0);
3443 			}
3444 			/*
3445 			 * If doing XCASE processing (not very
3446 			 * likely, in this day and age), look at each
3447 			 * character individually.
3448 			 */
3449 			if ((tp->t_modes.c_lflag & XCASE) &&
3450 			    (tp->t_modes.c_lflag & ICANON)) {
3451 				c = *ibp->b_rptr++;
3452 
3453 				/*
3454 				 * We need to make sure that this is not
3455 				 * a following byte of a multibyte character
3456 				 * before applying an XCASE processing.
3457 				 *
3458 				 * tp->t_eucign will be 0 if and only
3459 				 * if the current 'c' is an ASCII character
3460 				 * and also a byte. Otherwise, it will have
3461 				 * the byte length of a multibyte character.
3462 				 */
3463 				if ((tp->t_state & TS_MEUC) &&
3464 				    tp->t_eucign == 0 && NOTASCII(c)) {
3465 					tp->t_eucign =
3466 					    tp->t_csmethods.ldterm_memwidth(
3467 					    c, (void *)tp);
3468 					tp->t_scratch_len = tp->t_eucign;
3469 
3470 					if (tp->t_csdata.codeset_type !=
3471 					    LDTERM_CS_TYPE_UTF8) {
3472 						tp->t_col +=
3473 						    tp->
3474 						    t_csmethods.
3475 						    ldterm_dispwidth(c,
3476 						    (void *)tp,
3477 						    tp->t_modes.c_lflag &
3478 						    ECHOCTL);
3479 					}
3480 				}
3481 
3482 				/*
3483 				 * If character is mapped on output,
3484 				 * put out a backslash followed by
3485 				 * what it is mapped to.
3486 				 */
3487 				if (tp->t_eucign == 0 && omaptab[c] != 0 &&
3488 				    (!echoing || c != '\\')) {
3489 					/* backslash is an ordinary character */
3490 					tp->t_col++;
3491 					*obp->b_wptr++ = '\\';
3492 					bytes_left--;
3493 					if (bytes_left == 0) {
3494 						/* LINTED */
3495 						NEW_BLOCK(1);
3496 					}
3497 					/*
3498 					 * Allocation failed, make
3499 					 * state consistent before
3500 					 * returning
3501 					 */
3502 					if (obp == NULL) {
3503 						ibp->b_rptr--;
3504 						tp->t_col--;
3505 						oobp->b_wptr--;
3506 						goto outofbufs;
3507 					}
3508 					c = omaptab[c];
3509 				}
3510 				/*
3511 				 * If no other output processing is
3512 				 * required, push the character into
3513 				 * the block and get another.
3514 				 */
3515 				if (!(tp->t_modes.c_oflag & OPOST)) {
3516 					if (tp->t_eucign > 0) {
3517 						--tp->t_eucign;
3518 					} else {
3519 						tp->t_col++;
3520 					}
3521 					*obp->b_wptr++ = c;
3522 					bytes_left--;
3523 					continue;
3524 				}
3525 				/*
3526 				 * OPOST output flag is set. Map
3527 				 * lower case to upper case if OLCUC
3528 				 * flag is set and the 'c' is a lowercase
3529 				 * ASCII character.
3530 				 */
3531 				if (tp->t_eucign == 0 &&
3532 				    (tp->t_modes.c_oflag & OLCUC) &&
3533 				    c >= 'a' && c <= 'z')
3534 					c -= 'a' - 'A';
3535 			} else {
3536 				/*
3537 				 * Copy all the ORDINARY characters,
3538 				 * possibly mapping upper case to
3539 				 * lower case.  We use "movtuc",
3540 				 * STOPPING when we can't move some
3541 				 * character. For multi-byte or
3542 				 * multi-column EUC, we can't depend
3543 				 * on the regular tables. Rather than
3544 				 * just drop through to the "big
3545 				 * switch" for all characters, it
3546 				 * _might_ be faster to let "movtuc"
3547 				 * move a bunch of characters.
3548 				 * Chances are, even in multi-byte
3549 				 * mode we'll have lots of ASCII
3550 				 * going through. We check the flag
3551 				 * once, and call movtuc with the
3552 				 * appropriate table as an argument.
3553 				 *
3554 				 * "movtuc will work for all codeset
3555 				 * types since it stops at the beginning
3556 				 * byte of a multibyte character.
3557 				 */
3558 				size_t bytes_to_move;
3559 				size_t bytes_moved;
3560 
3561 				ASSERT(ibp->b_wptr >= ibp->b_rptr);
3562 				bytes_to_move = ibp->b_wptr - ibp->b_rptr;
3563 				if (bytes_to_move > bytes_left)
3564 					bytes_to_move = bytes_left;
3565 				if (tp->t_state & TS_MEUC) {
3566 					bytes_moved = movtuc(bytes_to_move,
3567 					    ibp->b_rptr, obp->b_wptr,
3568 					    (tp->t_modes.c_oflag & OLCUC ?
3569 					    elcuctab : enotrantab));
3570 				} else {
3571 					bytes_moved = movtuc(bytes_to_move,
3572 					    ibp->b_rptr, obp->b_wptr,
3573 					    (tp->t_modes.c_oflag & OLCUC ?
3574 					    lcuctab : notrantab));
3575 				}
3576 				/*
3577 				 * We're save to just do this column
3578 				 * calculation, because if TS_MEUC is
3579 				 * set, we used the proper EUC
3580 				 * tables, and won't have copied any
3581 				 * EUC bytes.
3582 				 */
3583 				tp->t_col += bytes_moved;
3584 				ibp->b_rptr += bytes_moved;
3585 				obp->b_wptr += bytes_moved;
3586 				bytes_left -= bytes_moved;
3587 				if (ibp->b_rptr >= ibp->b_wptr)
3588 					continue;	/* moved all of block */
3589 				if (bytes_left == 0) {
3590 					/* LINTED */
3591 					NEW_BLOCK(0);
3592 				}
3593 				c = *ibp->b_rptr++;	/* stopper */
3594 			}
3595 
3596 			/*
3597 			 * Again, we need to make sure that this is not
3598 			 * a following byte of a multibyte character at
3599 			 * here.
3600 			 *
3601 			 * 'tp->t_eucign' will be 0 iff the current 'c' is
3602 			 * an ASCII character. Otherwise, it will have
3603 			 * the byte length of a multibyte character.
3604 			 * We also add the display width to 'tp->t_col' if
3605 			 * the current codeset is not UTF-8 since this is
3606 			 * a leading byte of a multibyte character.
3607 			 * For UTF-8 codeset type, we add the display width
3608 			 * when we get the last byte of a character.
3609 			 */
3610 			if ((tp->t_state & TS_MEUC) && tp->t_eucign == 0 &&
3611 			    NOTASCII(c)) {
3612 				tp->t_eucign = tp->t_csmethods.ldterm_memwidth(
3613 				    c, (void *)tp);
3614 				tp->t_scratch_len = tp->t_eucign;
3615 
3616 				if (tp->t_csdata.codeset_type !=
3617 				    LDTERM_CS_TYPE_UTF8) {
3618 					tp->t_col +=
3619 					    tp->t_csmethods.ldterm_dispwidth(c,
3620 					    (void *)tp,
3621 					    tp->t_modes.c_lflag & ECHOCTL);
3622 				}
3623 			}
3624 
3625 			/*
3626 			 * If the driver has requested, don't process
3627 			 * output flags.  However, if we're in
3628 			 * multi-byte mode, we HAVE to look at
3629 			 * EVERYTHING going out to maintain column
3630 			 * position properly. Therefore IF the driver
3631 			 * says don't AND we're not doing multi-byte,
3632 			 * then don't do it.  Otherwise, do it.
3633 			 *
3634 			 * NOTE:  Hardware USUALLY doesn't expand tabs
3635 			 * properly for multi-byte situations anyway;
3636 			 * that's a known problem with the 3B2
3637 			 * "PORTS" board firmware, and any other
3638 			 * hardware that doesn't ACTUALLY know about
3639 			 * the current EUC mapping that WE are using
3640 			 * at this very moment.  The problem is that
3641 			 * memory width is INDEPENDENT of screen
3642 			 * width - no relation - so WE know how wide
3643 			 * the characters are, but an off-the-host
3644 			 * board probably doesn't.  So, until we're
3645 			 * SURE that the hardware below us can
3646 			 * correctly expand tabs in a
3647 			 * multi-byte/multi-column EUC situation, we
3648 			 * do it ourselves.
3649 			 */
3650 			/*
3651 			 * Map <CR>to<NL> on output if OCRNL flag
3652 			 * set. ONLCR processing is not done if OCRNL
3653 			 * is set.
3654 			 */
3655 			if (c == '\r' && (tp->t_modes.c_oflag & OCRNL)) {
3656 				c = '\n';
3657 				ctype = typetab[c];
3658 				goto jocrnl;
3659 			}
3660 
3661 			if (tp->t_csdata.codeset_type == LDTERM_CS_TYPE_EUC) {
3662 				ctype = typetab[c];
3663 			} else {
3664 				/*
3665 				 * In other codeset types, we safely assume
3666 				 * any byte of a multibyte character will have
3667 				 * 'ORDINARY' type. For ASCII characters, we
3668 				 * still use the typetab[].
3669 				 */
3670 				if (tp->t_eucign == 0)
3671 					ctype = typetab[c];
3672 				else
3673 					ctype = ORDINARY;
3674 			}
3675 
3676 			/*
3677 			 * Map <NL> to <CR><NL> on output if ONLCR
3678 			 * flag is set.
3679 			 */
3680 			if (c == '\n' && (tp->t_modes.c_oflag & ONLCR)) {
3681 				if (!(tp->t_state & TS_TTCR)) {
3682 					tp->t_state |= TS_TTCR;
3683 					c = '\r';
3684 					ctype = typetab['\r'];
3685 					--ibp->b_rptr;
3686 				} else
3687 					tp->t_state &= ~TS_TTCR;
3688 			}
3689 			/*
3690 			 * Delay values and column position
3691 			 * calculated here.  For EUC chars in
3692 			 * multi-byte mode, we use "t_eucign" to help
3693 			 * calculate columns.  When we see the first
3694 			 * byte of an EUC, we set t_eucign to the
3695 			 * number of bytes that will FOLLOW it, and
3696 			 * we add the screen width of the WHOLE EUC
3697 			 * character to the column position.  In
3698 			 * particular, we can't count SS2 or SS3 as
3699 			 * printing characters.  Remember, folks, the
3700 			 * screen width and memory width are
3701 			 * independent - no relation. We could have
3702 			 * dropped through for ASCII, but we want to
3703 			 * catch any bad characters (i.e., t_eucign
3704 			 * set and an ASCII char received) and
3705 			 * possibly report the garbage situation.
3706 			 */
3707 	jocrnl:
3708 
3709 			count = 0;
3710 			switch (ctype) {
3711 
3712 			case T_SS2:
3713 			case T_SS3:
3714 			case ORDINARY:
3715 				if (tp->t_state & TS_MEUC) {
3716 					if (tp->t_eucign) {
3717 						*obp->b_wptr++ = c;
3718 						bytes_left--;
3719 
3720 						tp->t_scratch[tp->t_scratch_len
3721 						    - tp->t_eucign] = c;
3722 
3723 						--tp->t_eucign;
3724 
3725 						if (tp->t_csdata.codeset_type
3726 						    == LDTERM_CS_TYPE_UTF8 &&
3727 						    tp->t_eucign <= 0) {
3728 							tp->t_col +=
3729 							    ldterm_utf8_width(
3730 							    tp->t_scratch,
3731 							    tp->t_scratch_len);
3732 						}
3733 					} else {
3734 						if (tp->t_modes.c_oflag & OLCUC)
3735 							n = elcuctab[c];
3736 						else
3737 							n = enotrantab[c];
3738 						if (n)
3739 							c = n;
3740 						tp->t_col++;
3741 						*obp->b_wptr++ = c;
3742 						bytes_left--;
3743 					}
3744 				} else {	/* ho hum, ASCII mode... */
3745 					if (tp->t_modes.c_oflag & OLCUC)
3746 						n = lcuctab[c];
3747 					else
3748 						n = notrantab[c];
3749 					if (n)
3750 						c = n;
3751 					tp->t_col++;
3752 					*obp->b_wptr++ = c;
3753 					bytes_left--;
3754 				}
3755 				break;
3756 
3757 				/*
3758 				 * If we're doing ECHOCTL, we've
3759 				 * already mapped the thing during
3760 				 * the process of canonising.  Don't
3761 				 * bother here, as it's not one that
3762 				 * we did.
3763 				 */
3764 			case CONTROL:
3765 				*obp->b_wptr++ = c;
3766 				bytes_left--;
3767 				break;
3768 
3769 				/*
3770 				 * This is probably a backspace
3771 				 * received, not one that we're
3772 				 * echoing.  Let it go as a
3773 				 * single-column backspace.
3774 				 */
3775 			case BACKSPACE:
3776 				if (tp->t_col)
3777 					tp->t_col--;
3778 				if (tp->t_modes.c_oflag & BSDLY) {
3779 					if (tp->t_modes.c_oflag & OFILL)
3780 						count = 1;
3781 				}
3782 				*obp->b_wptr++ = c;
3783 				bytes_left--;
3784 				break;
3785 
3786 			case NEWLINE:
3787 				if (tp->t_modes.c_oflag & ONLRET)
3788 					goto cr;
3789 				if ((tp->t_modes.c_oflag & NLDLY) == NL1)
3790 					count = 2;
3791 				*obp->b_wptr++ = c;
3792 				bytes_left--;
3793 				break;
3794 
3795 			case TAB:
3796 				/*
3797 				 * Map '\t' to spaces if XTABS flag
3798 				 * is set.  The calculation of
3799 				 * "t_eucign" has probably insured
3800 				 * that column will be correct, as we
3801 				 * bumped t_col by the DISP width,
3802 				 * not the memory width.
3803 				 */
3804 				if ((tp->t_modes.c_oflag & TABDLY) == XTABS) {
3805 					for (;;) {
3806 						*obp->b_wptr++ = ' ';
3807 						bytes_left--;
3808 						tp->t_col++;
3809 						if ((tp->t_col & 07) == 0)
3810 							break;	/* every 8th */
3811 						/*
3812 						 * If we don't have
3813 						 * room to fully
3814 						 * expand this tab in
3815 						 * this block, back
3816 						 * up to continue
3817 						 * expanding it into
3818 						 * the next block.
3819 						 */
3820 						if (obp->b_wptr >=
3821 						    obp->b_datap->db_lim) {
3822 							ibp->b_rptr--;
3823 							break;
3824 						}
3825 					}
3826 				} else {
3827 					tp->t_col |= 07;
3828 					tp->t_col++;
3829 					if (tp->t_modes.c_oflag & OFILL) {
3830 						if (tp->t_modes.c_oflag &
3831 						    TABDLY)
3832 							count = 2;
3833 					} else {
3834 						switch (tp->t_modes.c_oflag &
3835 						    TABDLY) {
3836 						case TAB2:
3837 							count = 6;
3838 							break;
3839 
3840 						case TAB1:
3841 							count = 1 + (tp->t_col |
3842 							    ~07);
3843 							if (count < 5)
3844 								count = 0;
3845 							break;
3846 						}
3847 					}
3848 					*obp->b_wptr++ = c;
3849 					bytes_left--;
3850 				}
3851 				break;
3852 
3853 			case VTAB:
3854 				if ((tp->t_modes.c_oflag & VTDLY) &&
3855 				    !(tp->t_modes.c_oflag & OFILL))
3856 					count = 127;
3857 				*obp->b_wptr++ = c;
3858 				bytes_left--;
3859 				break;
3860 
3861 			case RETURN:
3862 				/*
3863 				 * Ignore <CR> in column 0 if ONOCR
3864 				 * flag set.
3865 				 */
3866 				if (tp->t_col == 0 &&
3867 				    (tp->t_modes.c_oflag & ONOCR))
3868 					break;
3869 
3870 		cr:
3871 				switch (tp->t_modes.c_oflag & CRDLY) {
3872 
3873 				case CR1:
3874 					if (tp->t_modes.c_oflag & OFILL)
3875 						count = 2;
3876 					else
3877 						count = tp->t_col % 2;
3878 					break;
3879 
3880 				case CR2:
3881 					if (tp->t_modes.c_oflag & OFILL)
3882 						count = 4;
3883 					else
3884 						count = 6;
3885 					break;
3886 
3887 				case CR3:
3888 					if (tp->t_modes.c_oflag & OFILL)
3889 						count = 0;
3890 					else
3891 						count = 9;
3892 					break;
3893 				}
3894 				tp->t_col = 0;
3895 				*obp->b_wptr++ = c;
3896 				bytes_left--;
3897 				break;
3898 			}
3899 
3900 			if (count != 0) {
3901 				if (tp->t_modes.c_oflag & OFILL) {
3902 					do {
3903 						if (bytes_left == 0) {
3904 							/* LINTED */
3905 							NEW_BLOCK(0);
3906 						}
3907 						if (tp->t_modes.c_oflag & OFDEL)
3908 							*obp->b_wptr++ = CDEL;
3909 						else
3910 							*obp->b_wptr++ = CNUL;
3911 						bytes_left--;
3912 					} while (--count != 0);
3913 				} else {
3914 					if ((tp->t_modes.c_lflag & FLUSHO) &&
3915 					    (tp->t_modes.c_lflag & IEXTEN)) {
3916 						/* drop on floor */
3917 						freemsg(*omp);
3918 					} else {
3919 						/*
3920 						 * Update sysinfo
3921 						 * outch
3922 						 */
3923 						(void) drv_setparm(SYSOUTC,
3924 						    msgdsize(*omp));
3925 						putnext(q, *omp);
3926 						/*
3927 						 * Send M_DELAY
3928 						 * downstream
3929 						 */
3930 						if ((bp =
3931 						    allocb(1, BPRI_MED)) !=
3932 						    NULL) {
3933 							bp->b_datap->db_type =
3934 							    M_DELAY;
3935 							*bp->b_wptr++ =
3936 							    (uchar_t)count;
3937 							putnext(q, bp);
3938 						}
3939 					}
3940 					bytes_left = 0;
3941 					/*
3942 					 * We have to start a new
3943 					 * message; the delay
3944 					 * introduces a break between
3945 					 * messages.
3946 					 */
3947 					*omp = NULL;
3948 					contpp = omp;
3949 				}
3950 			}
3951 		}
3952 		cbp = ibp->b_cont;
3953 		freeb(ibp);
3954 	} while ((ibp = cbp) != NULL);	/* next block, if any */
3955 
3956 outofbufs:
3957 	return (ibp);
3958 #undef NEW_BLOCK
3959 }
3960 
3961 
3962 #if !defined(__sparc)
3963 int
3964 movtuc(size_t size, unsigned char *from, unsigned char *origto,
3965 	unsigned char *table)
3966 {
3967 	unsigned char *to = origto;
3968 	unsigned char c;
3969 
3970 	while (size != 0 && (c = table[*from++]) != 0) {
3971 		*to++ = c;
3972 		size--;
3973 	}
3974 	return (to - origto);
3975 }
3976 #endif
3977 
3978 static void
3979 ldterm_flush_output(uchar_t c, queue_t *q, ldtermstd_state_t *tp)
3980 {
3981 	/* Already conditioned with IEXTEN during VDISCARD processing */
3982 	if (tp->t_modes.c_lflag & FLUSHO)
3983 		tp->t_modes.c_lflag &= ~FLUSHO;
3984 	else {
3985 		flushq(q, FLUSHDATA);	/* flush our write queue */
3986 		/* flush ones below us */
3987 		(void) putnextctl1(q, M_FLUSH, FLUSHW);
3988 		if ((tp->t_echomp = allocb(EBSIZE, BPRI_HI)) != NULL) {
3989 			(void) ldterm_echo(c, q, 1, tp);
3990 			if (tp->t_msglen != 0)
3991 				ldterm_reprint(q, EBSIZE, tp);
3992 			if (tp->t_echomp != NULL) {
3993 				putnext(q, tp->t_echomp);
3994 				tp->t_echomp = NULL;
3995 			}
3996 		}
3997 		tp->t_modes.c_lflag |= FLUSHO;
3998 	}
3999 }
4000 
4001 
4002 /*
4003  * Signal generated by the reader: M_PCSIG and M_FLUSH messages sent.
4004  */
4005 static void
4006 ldterm_dosig(queue_t *q, int sig, uchar_t c, int mtype, int mode)
4007 {
4008 	ldtermstd_state_t *tp = (ldtermstd_state_t *)q->q_ptr;
4009 	int sndsig = 0;
4010 
4011 	/*
4012 	 * c == \0 is brk case; need to flush on BRKINT even if
4013 	 * noflsh is set.
4014 	 */
4015 	if ((!(tp->t_modes.c_lflag & NOFLSH)) || (c == '\0')) {
4016 		if (mode) {
4017 			if (tp->t_state & TS_TTSTOP) {
4018 				sndsig = 1;
4019 				(void) putnextctl1(q, mtype, sig);
4020 			}
4021 			/*
4022 			 * Flush read or write side.
4023 			 * Restart the input or output.
4024 			 */
4025 			if (mode & FLUSHR) {
4026 				flushq(q, FLUSHDATA);
4027 				(void) putnextctl1(WR(q), M_FLUSH, mode);
4028 				if (tp->t_state & (TS_TBLOCK|TS_IFBLOCK)) {
4029 					(void) putnextctl(WR(q), M_STARTI);
4030 					tp->t_state &= ~(TS_TBLOCK|TS_IFBLOCK);
4031 				}
4032 			}
4033 			if (mode & FLUSHW) {
4034 				flushq(WR(q), FLUSHDATA);
4035 				/*
4036 				 * XXX This is extremely gross.
4037 				 * Since we can't be sure our M_FLUSH
4038 				 * will have run its course by the
4039 				 * time we do the echo below, we set
4040 				 * state and toss it in the write put
4041 				 * routine to prevent flushing our
4042 				 * own data.  Note that downstream
4043 				 * modules on the write side will be
4044 				 * flushed by the M_FLUSH sent above.
4045 				 */
4046 				tp->t_state |= TS_FLUSHWAIT;
4047 				(void) putnextctl1(q, M_FLUSH, FLUSHW);
4048 				if (tp->t_state & TS_TTSTOP) {
4049 					(void) putnextctl(WR(q), M_START);
4050 					tp->t_state &= ~(TS_TTSTOP|TS_OFBLOCK);
4051 				}
4052 			}
4053 		}
4054 	}
4055 	tp->t_state &= ~TS_QUOT;
4056 	if (sndsig == 0)
4057 		(void) putnextctl1(q, mtype, sig);
4058 
4059 	if (c != '\0') {
4060 		if ((tp->t_echomp = allocb(4, BPRI_HI)) != NULL) {
4061 			(void) ldterm_echo(c, WR(q), 4, tp);
4062 			putnext(WR(q), tp->t_echomp);
4063 			tp->t_echomp = NULL;
4064 		}
4065 	}
4066 }
4067 
4068 
4069 /*
4070  * Called when an M_IOCTL message is seen on the write queue; does
4071  * whatever we're supposed to do with it, and either replies
4072  * immediately or passes it to the next module down.
4073  */
4074 static void
4075 ldterm_do_ioctl(queue_t *q, mblk_t *mp)
4076 {
4077 	ldtermstd_state_t *tp;
4078 	struct iocblk *iocp;
4079 	struct eucioc *euciocp;	/* needed for EUC ioctls */
4080 	ldterm_cs_data_user_t *csdp;
4081 	int i;
4082 	int locale_name_sz;
4083 	uchar_t maxbytelen;
4084 	uchar_t maxscreenlen;
4085 	int error;
4086 
4087 	iocp = (struct iocblk *)mp->b_rptr;
4088 	tp = (ldtermstd_state_t *)q->q_ptr;
4089 
4090 	switch (iocp->ioc_cmd) {
4091 
4092 	case TCSETS:
4093 	case TCSETSW:
4094 	case TCSETSF:
4095 		{
4096 			/*
4097 			 * Set current parameters and special
4098 			 * characters.
4099 			 */
4100 			struct termios *cb;
4101 			struct termios oldmodes;
4102 
4103 			error = miocpullup(mp, sizeof (struct termios));
4104 			if (error != 0) {
4105 				miocnak(q, mp, 0, error);
4106 				return;
4107 			}
4108 
4109 			cb = (struct termios *)mp->b_cont->b_rptr;
4110 
4111 			oldmodes = tp->t_amodes;
4112 			tp->t_amodes = *cb;
4113 			if ((tp->t_amodes.c_lflag & PENDIN) &&
4114 			    (tp->t_modes.c_lflag & IEXTEN)) {
4115 				/*
4116 				 * Yuk.  The C shell file completion
4117 				 * code actually uses this "feature",
4118 				 * so we have to support it.
4119 				 */
4120 				if (tp->t_message != NULL) {
4121 					tp->t_state |= TS_RESCAN;
4122 					qenable(RD(q));
4123 				}
4124 				tp->t_amodes.c_lflag &= ~PENDIN;
4125 			}
4126 			bcopy(tp->t_amodes.c_cc, tp->t_modes.c_cc, NCCS);
4127 
4128 			/*
4129 			 * ldterm_adjust_modes does not deal with
4130 			 * cflags
4131 			 */
4132 			tp->t_modes.c_cflag = tp->t_amodes.c_cflag;
4133 
4134 			ldterm_adjust_modes(tp);
4135 			if (chgstropts(&oldmodes, tp, RD(q)) == (-1)) {
4136 				miocnak(q, mp, 0, EAGAIN);
4137 				return;
4138 			}
4139 			/*
4140 			 * The driver may want to know about the
4141 			 * following iflags: IGNBRK, BRKINT, IGNPAR,
4142 			 * PARMRK, INPCK, IXON, IXANY.
4143 			 */
4144 			break;
4145 		}
4146 
4147 	case TCSETA:
4148 	case TCSETAW:
4149 	case TCSETAF:
4150 		{
4151 			/*
4152 			 * Old-style "ioctl" to set current
4153 			 * parameters and special characters. Don't
4154 			 * clear out the unset portions, leave them
4155 			 * as they are.
4156 			 */
4157 			struct termio *cb;
4158 			struct termios oldmodes;
4159 
4160 			error = miocpullup(mp, sizeof (struct termio));
4161 			if (error != 0) {
4162 				miocnak(q, mp, 0, error);
4163 				return;
4164 			}
4165 
4166 			cb = (struct termio *)mp->b_cont->b_rptr;
4167 
4168 			oldmodes = tp->t_amodes;
4169 			tp->t_amodes.c_iflag =
4170 			    (tp->t_amodes.c_iflag & 0xffff0000 | cb->c_iflag);
4171 			tp->t_amodes.c_oflag =
4172 			    (tp->t_amodes.c_oflag & 0xffff0000 | cb->c_oflag);
4173 			tp->t_amodes.c_cflag =
4174 			    (tp->t_amodes.c_cflag & 0xffff0000 | cb->c_cflag);
4175 			tp->t_amodes.c_lflag =
4176 			    (tp->t_amodes.c_lflag & 0xffff0000 | cb->c_lflag);
4177 
4178 			bcopy(cb->c_cc, tp->t_modes.c_cc, NCC);
4179 			/* TCGETS returns amodes, so update that too */
4180 			bcopy(cb->c_cc, tp->t_amodes.c_cc, NCC);
4181 
4182 			/* ldterm_adjust_modes does not deal with cflags */
4183 
4184 			tp->t_modes.c_cflag = tp->t_amodes.c_cflag;
4185 
4186 			ldterm_adjust_modes(tp);
4187 			if (chgstropts(&oldmodes, tp, RD(q)) == (-1)) {
4188 				miocnak(q, mp, 0, EAGAIN);
4189 				return;
4190 			}
4191 			/*
4192 			 * The driver may want to know about the
4193 			 * following iflags: IGNBRK, BRKINT, IGNPAR,
4194 			 * PARMRK, INPCK, IXON, IXANY.
4195 			 */
4196 			break;
4197 		}
4198 
4199 	case TCFLSH:
4200 		/*
4201 		 * Do the flush on the write queue immediately, and
4202 		 * queue up any flush on the read queue for the
4203 		 * service procedure to see.  Then turn it into the
4204 		 * appropriate M_FLUSH message, so that the module
4205 		 * below us doesn't have to know about TCFLSH.
4206 		 */
4207 		error = miocpullup(mp, sizeof (int));
4208 		if (error != 0) {
4209 			miocnak(q, mp, 0, error);
4210 			return;
4211 		}
4212 
4213 		ASSERT(mp->b_datap != NULL);
4214 		if (*(int *)mp->b_cont->b_rptr == 0) {
4215 			ASSERT(mp->b_datap != NULL);
4216 			(void) putnextctl1(q, M_FLUSH, FLUSHR);
4217 			(void) putctl1(RD(q), M_FLUSH, FLUSHR);
4218 		} else if (*(int *)mp->b_cont->b_rptr == 1) {
4219 			flushq(q, FLUSHDATA);
4220 			ASSERT(mp->b_datap != NULL);
4221 			tp->t_state |= TS_FLUSHWAIT;
4222 			(void) putnextctl1(RD(q), M_FLUSH, FLUSHW);
4223 			(void) putnextctl1(q, M_FLUSH, FLUSHW);
4224 		} else if (*(int *)mp->b_cont->b_rptr == 2) {
4225 			flushq(q, FLUSHDATA);
4226 			ASSERT(mp->b_datap != NULL);
4227 			(void) putnextctl1(q, M_FLUSH, FLUSHRW);
4228 			tp->t_state |= TS_FLUSHWAIT;
4229 			(void) putnextctl1(RD(q), M_FLUSH, FLUSHRW);
4230 		} else {
4231 			miocnak(q, mp, 0, EINVAL);
4232 			return;
4233 		}
4234 		ASSERT(mp->b_datap != NULL);
4235 		iocp->ioc_rval = 0;
4236 		miocack(q, mp, 0, 0);
4237 		return;
4238 
4239 	case TCXONC:
4240 		error = miocpullup(mp, sizeof (int));
4241 		if (error != 0) {
4242 			miocnak(q, mp, 0, error);
4243 			return;
4244 		}
4245 
4246 		switch (*(int *)mp->b_cont->b_rptr) {
4247 		case 0:
4248 			if (!(tp->t_state & TS_TTSTOP)) {
4249 				(void) putnextctl(q, M_STOP);
4250 				tp->t_state |= (TS_TTSTOP|TS_OFBLOCK);
4251 			}
4252 			break;
4253 
4254 		case 1:
4255 			if (tp->t_state & TS_TTSTOP) {
4256 				(void) putnextctl(q, M_START);
4257 				tp->t_state &= ~(TS_TTSTOP|TS_OFBLOCK);
4258 			}
4259 			break;
4260 
4261 		case 2:
4262 			(void) putnextctl(q, M_STOPI);
4263 			tp->t_state |= (TS_TBLOCK|TS_IFBLOCK);
4264 			break;
4265 
4266 		case 3:
4267 			(void) putnextctl(q, M_STARTI);
4268 			tp->t_state &= ~(TS_TBLOCK|TS_IFBLOCK);
4269 			break;
4270 
4271 		default:
4272 			miocnak(q, mp, 0, EINVAL);
4273 			return;
4274 		}
4275 		ASSERT(mp->b_datap != NULL);
4276 		iocp->ioc_rval = 0;
4277 		miocack(q, mp, 0, 0);
4278 		return;
4279 		/*
4280 		 * TCSBRK is expected to be handled by the driver.
4281 		 * The reason its left for the driver is that when
4282 		 * the argument to TCSBRK is zero driver has to drain
4283 		 * the data and sending a M_IOCACK from LDTERM before
4284 		 * the driver drains the data is going to cause
4285 		 * problems.
4286 		 */
4287 
4288 		/*
4289 		 * The following are EUC related ioctls.  For
4290 		 * EUC_WSET, we have to pass the information on, even
4291 		 * though we ACK the call.  It's vital in the EUC
4292 		 * environment that everybody downstream knows about
4293 		 * the EUC codeset widths currently in use; we
4294 		 * therefore pass down the information in an M_CTL
4295 		 * message.  It will bottom out in the driver.
4296 		 */
4297 	case EUC_WSET:
4298 		{
4299 
4300 			/* only needed for EUC_WSET */
4301 			struct iocblk *riocp;
4302 
4303 			mblk_t *dmp, *dmp_cont;
4304 
4305 			/*
4306 			 * If the user didn't supply any information,
4307 			 * NAK it.
4308 			 */
4309 			error = miocpullup(mp, sizeof (struct eucioc));
4310 			if (error != 0) {
4311 				miocnak(q, mp, 0, error);
4312 				return;
4313 			}
4314 
4315 			euciocp = (struct eucioc *)mp->b_cont->b_rptr;
4316 			/*
4317 			 * Check here for something reasonable.  If
4318 			 * anything will take more than EUC_MAXW
4319 			 * columns or more than EUC_MAXW bytes
4320 			 * following SS2 or SS3, then just reject it
4321 			 * out of hand. It's not impossible for us to
4322 			 * do it, it just isn't reasonable.  So far,
4323 			 * in the world, we've seen the absolute max
4324 			 * columns to be 2 and the max number of
4325 			 * bytes to be 3.  This allows room for some
4326 			 * expansion of that, but it probably won't
4327 			 * even be necessary. At the moment, we
4328 			 * return a "range" error.  If you really
4329 			 * need to, you can push EUC_MAXW up to over
4330 			 * 200; it doesn't make sense, though, with
4331 			 * only a CANBSIZ sized input limit (usually
4332 			 * 256)!
4333 			 */
4334 			for (i = 0; i < 4; i++) {
4335 				if ((euciocp->eucw[i] > EUC_MAXW) ||
4336 				    (euciocp->scrw[i] > EUC_MAXW)) {
4337 					miocnak(q, mp, 0, ERANGE);
4338 					return;
4339 				}
4340 			}
4341 			/*
4342 			 * Otherwise, save the information in tp,
4343 			 * force codeset 0 (ASCII) to be one byte,
4344 			 * one column.
4345 			 */
4346 			cp_eucwioc(euciocp, &tp->eucwioc, EUCIN);
4347 			tp->eucwioc.eucw[0] = tp->eucwioc.scrw[0] = 1;
4348 			/*
4349 			 * Now, check out whether we're doing
4350 			 * multibyte processing. if we are, we need
4351 			 * to allocate a block to hold the parallel
4352 			 * array. By convention, we've been passed
4353 			 * what amounts to a CSWIDTH definition.  We
4354 			 * actually NEED the number of bytes for
4355 			 * Codesets 2 & 3.
4356 			 */
4357 			tp->t_maxeuc = 0;	/* reset to say we're NOT */
4358 
4359 			tp->t_state &= ~TS_MEUC;
4360 			/*
4361 			 * We'll set TS_MEUC if we're doing
4362 			 * multi-column OR multi- byte OR both.  It
4363 			 * makes things easier...  NOTE:  If we fail
4364 			 * to get the buffer we need to hold display
4365 			 * widths, then DON'T let the TS_MEUC bit get
4366 			 * set!
4367 			 */
4368 			for (i = 0; i < 4; i++) {
4369 				if (tp->eucwioc.eucw[i] > tp->t_maxeuc)
4370 					tp->t_maxeuc = tp->eucwioc.eucw[i];
4371 				if (tp->eucwioc.scrw[i] > 1)
4372 					tp->t_state |= TS_MEUC;
4373 			}
4374 			if ((tp->t_maxeuc > 1) || (tp->t_state & TS_MEUC)) {
4375 				if (!tp->t_eucp_mp) {
4376 					if (!(tp->t_eucp_mp = allocb(CANBSIZ,
4377 					    BPRI_HI))) {
4378 						tp->t_maxeuc = 1;
4379 						tp->t_state &= ~TS_MEUC;
4380 						cmn_err(CE_WARN,
4381 						    "Can't allocate eucp_mp");
4382 						miocnak(q, mp, 0, ENOSR);
4383 						return;
4384 					}
4385 					/*
4386 					 * here, if there's junk in
4387 					 * the canonical buffer, then
4388 					 * move the eucp pointer past
4389 					 * it, so we don't run off
4390 					 * the beginning.  This is a
4391 					 * total botch, but will
4392 					 * hopefully keep stuff from
4393 					 * getting too messed up
4394 					 * until the user flushes
4395 					 * this line!
4396 					 */
4397 					if (tp->t_msglen) {
4398 						tp->t_eucp =
4399 						    tp->t_eucp_mp->b_rptr;
4400 						for (i = tp->t_msglen; i; i--)
4401 							*tp->t_eucp++ = 1;
4402 					} else {
4403 						tp->t_eucp =
4404 						    tp->t_eucp_mp->b_rptr;
4405 					}
4406 				}
4407 				/* doing multi-byte handling */
4408 				tp->t_state |= TS_MEUC;
4409 
4410 			} else if (tp->t_eucp_mp) {
4411 				freemsg(tp->t_eucp_mp);
4412 				tp->t_eucp_mp = NULL;
4413 				tp->t_eucp = NULL;
4414 			}
4415 
4416 			/*
4417 			 * Save the EUC width data we have at
4418 			 * the t_csdata, set t_csdata.codeset_type to
4419 			 * EUC one, and, switch the codeset methods at
4420 			 * t_csmethods.
4421 			 */
4422 			bzero(&tp->t_csdata.eucpc_data,
4423 			    (sizeof (ldterm_eucpc_data_t) *
4424 			    LDTERM_CS_MAX_CODESETS));
4425 			tp->t_csdata.eucpc_data[0].byte_length =
4426 			    tp->eucwioc.eucw[1];
4427 			tp->t_csdata.eucpc_data[0].screen_width =
4428 			    tp->eucwioc.scrw[1];
4429 			tp->t_csdata.eucpc_data[1].byte_length =
4430 			    tp->eucwioc.eucw[2];
4431 			tp->t_csdata.eucpc_data[1].screen_width =
4432 			    tp->eucwioc.scrw[2];
4433 			tp->t_csdata.eucpc_data[2].byte_length =
4434 			    tp->eucwioc.eucw[3];
4435 			tp->t_csdata.eucpc_data[2].screen_width =
4436 			    tp->eucwioc.scrw[3];
4437 			tp->t_csdata.version = LDTERM_DATA_VERSION;
4438 			tp->t_csdata.codeset_type = LDTERM_CS_TYPE_EUC;
4439 			/*
4440 			 * We are not using the 'csinfo_num' anyway if the
4441 			 * current codeset type is EUC. So, set it to
4442 			 * the maximum possible.
4443 			 */
4444 			tp->t_csdata.csinfo_num =
4445 			    LDTERM_CS_TYPE_EUC_MAX_SUBCS;
4446 			if (tp->t_csdata.locale_name != (char *)NULL) {
4447 				kmem_free(tp->t_csdata.locale_name,
4448 				    strlen(tp->t_csdata.locale_name) + 1);
4449 				tp->t_csdata.locale_name = (char *)NULL;
4450 			}
4451 			tp->t_csmethods = cs_methods[LDTERM_CS_TYPE_EUC];
4452 
4453 			/*
4454 			 * If we are able to allocate two blocks (the
4455 			 * iocblk and the associated data), then pass
4456 			 * it downstream, otherwise we'll need to NAK
4457 			 * it, and drop whatever we WERE able to
4458 			 * allocate.
4459 			 */
4460 			if ((dmp = mkiocb(EUC_WSET)) == NULL) {
4461 				miocnak(q, mp, 0, ENOSR);
4462 				return;
4463 			}
4464 			if ((dmp_cont = allocb(EUCSIZE, BPRI_HI)) == NULL) {
4465 				freemsg(dmp);
4466 				miocnak(q, mp, 0, ENOSR);
4467 				return;
4468 			}
4469 
4470 			/*
4471 			 * We got both buffers.  Copy out the EUC
4472 			 * information (as we received it, not what
4473 			 * we're using!) & pass it on.
4474 			 */
4475 			bcopy(mp->b_cont->b_rptr, dmp_cont->b_rptr, EUCSIZE);
4476 			dmp_cont->b_wptr += EUCSIZE;
4477 			dmp->b_cont = dmp_cont;
4478 			dmp->b_datap->db_type = M_CTL;
4479 			dmp_cont->b_datap->db_type = M_DATA;
4480 			riocp = (struct iocblk *)dmp->b_rptr;
4481 			riocp->ioc_count = EUCSIZE;
4482 			putnext(q, dmp);
4483 
4484 			/*
4485 			 * Now ACK the ioctl.
4486 			 */
4487 			iocp->ioc_rval = 0;
4488 			miocack(q, mp, 0, 0);
4489 			return;
4490 		}
4491 
4492 	case EUC_WGET:
4493 		error = miocpullup(mp, sizeof (struct eucioc));
4494 		if (error != 0) {
4495 			miocnak(q, mp, 0, error);
4496 			return;
4497 		}
4498 		euciocp = (struct eucioc *)mp->b_cont->b_rptr;
4499 		cp_eucwioc(&tp->eucwioc, euciocp, EUCOUT);
4500 		iocp->ioc_rval = 0;
4501 		miocack(q, mp, EUCSIZE, 0);
4502 		return;
4503 
4504 	case CSDATA_SET:
4505 		error = miocpullup(mp, sizeof (ldterm_cs_data_user_t));
4506 		if (error != 0) {
4507 			miocnak(q, mp, 0, error);
4508 			return;
4509 		}
4510 
4511 		csdp = (ldterm_cs_data_user_t *)mp->b_cont->b_rptr;
4512 
4513 		/* Validate the codeset data provided. */
4514 		if (csdp->version > LDTERM_DATA_VERSION ||
4515 		    csdp->codeset_type < LDTERM_CS_TYPE_MIN ||
4516 		    csdp->codeset_type > LDTERM_CS_TYPE_MAX) {
4517 			miocnak(q, mp, 0, ERANGE);
4518 			return;
4519 		}
4520 
4521 		if ((csdp->codeset_type == LDTERM_CS_TYPE_EUC &&
4522 		    csdp->csinfo_num > LDTERM_CS_TYPE_EUC_MAX_SUBCS) ||
4523 		    (csdp->codeset_type == LDTERM_CS_TYPE_PCCS &&
4524 		    (csdp->csinfo_num < LDTERM_CS_TYPE_PCCS_MIN_SUBCS ||
4525 		    csdp->csinfo_num > LDTERM_CS_TYPE_PCCS_MAX_SUBCS))) {
4526 			miocnak(q, mp, 0, ERANGE);
4527 			return;
4528 		}
4529 
4530 		maxbytelen = maxscreenlen = 0;
4531 		if (csdp->codeset_type == LDTERM_CS_TYPE_EUC) {
4532 			for (i = 0; i < LDTERM_CS_TYPE_EUC_MAX_SUBCS; i++) {
4533 				if (csdp->eucpc_data[i].byte_length >
4534 				    EUC_MAXW ||
4535 				    csdp->eucpc_data[i].screen_width >
4536 				    EUC_MAXW) {
4537 					miocnak(q, mp, 0, ERANGE);
4538 					return;
4539 				}
4540 
4541 				if (csdp->eucpc_data[i].byte_length >
4542 				    maxbytelen)
4543 					maxbytelen =
4544 					    csdp->eucpc_data[i].byte_length;
4545 				if (csdp->eucpc_data[i].screen_width >
4546 				    maxscreenlen)
4547 					maxscreenlen =
4548 					    csdp->eucpc_data[i].screen_width;
4549 			}
4550 			/* POSIX/C locale? */
4551 			if (maxbytelen == 0 && maxscreenlen == 0)
4552 				maxbytelen = maxscreenlen = 1;
4553 		} else if (csdp->codeset_type == LDTERM_CS_TYPE_PCCS) {
4554 			for (i = 0; i < LDTERM_CS_MAX_CODESETS; i++) {
4555 				if (csdp->eucpc_data[i].byte_length >
4556 				    LDTERM_CS_MAX_BYTE_LENGTH) {
4557 					miocnak(q, mp, 0, ERANGE);
4558 					return;
4559 				}
4560 				if (csdp->eucpc_data[i].byte_length >
4561 				    maxbytelen)
4562 					maxbytelen =
4563 					    csdp->eucpc_data[i].byte_length;
4564 				if (csdp->eucpc_data[i].screen_width >
4565 				    maxscreenlen)
4566 					maxscreenlen =
4567 					    csdp->eucpc_data[i].screen_width;
4568 			}
4569 		} else if (csdp->codeset_type == LDTERM_CS_TYPE_UTF8) {
4570 			maxbytelen = 4;
4571 			maxscreenlen = 2;
4572 		}
4573 
4574 		locale_name_sz = 0;
4575 		if (csdp->locale_name) {
4576 			for (i = 0; i < MAXNAMELEN; i++)
4577 				if (csdp->locale_name[i] == '\0')
4578 					break;
4579 			/*
4580 			 * We cannot have any string that is not NULL byte
4581 			 * terminated.
4582 			 */
4583 			if (i >= MAXNAMELEN) {
4584 				miocnak(q, mp, 0, ERANGE);
4585 				return;
4586 			}
4587 
4588 			locale_name_sz = i + 1;
4589 		}
4590 
4591 		/*
4592 		 * As the final check, if there was invalid codeset_type
4593 		 * given, or invalid byte_length was specified, it's an error.
4594 		 */
4595 		if (maxbytelen <= 0 || maxscreenlen <= 0) {
4596 			miocnak(q, mp, 0, ERANGE);
4597 			return;
4598 		}
4599 
4600 		/* Do the switching. */
4601 		tp->t_maxeuc = maxbytelen;
4602 		tp->t_state &= ~TS_MEUC;
4603 		if (maxbytelen > 1 || maxscreenlen > 1) {
4604 			if (!tp->t_eucp_mp) {
4605 				if (!(tp->t_eucp_mp = allocb(CANBSIZ,
4606 				    BPRI_HI))) {
4607 					cmn_err(CE_WARN,
4608 					    "Can't allocate eucp_mp");
4609 					miocnak(q, mp, 0, ENOSR);
4610 					return;
4611 				}
4612 				/*
4613 				 * If there's junk in the canonical buffer,
4614 				 * then move the eucp pointer past it,
4615 				 * so we don't run off the beginning. This is
4616 				 * a total botch, but will hopefully keep
4617 				 * stuff from getting too messed up until
4618 				 * the user flushes this line!
4619 				 */
4620 				if (tp->t_msglen) {
4621 					tp->t_eucp = tp->t_eucp_mp->b_rptr;
4622 					for (i = tp->t_msglen; i; i--)
4623 						*tp->t_eucp++ = 1;
4624 				} else {
4625 					tp->t_eucp = tp->t_eucp_mp->b_rptr;
4626 				}
4627 			}
4628 
4629 			/*
4630 			 * We only set TS_MEUC for a multibyte/multi-column
4631 			 * codeset.
4632 			 */
4633 			tp->t_state |= TS_MEUC;
4634 
4635 			tp->t_csdata.version = csdp->version;
4636 			tp->t_csdata.codeset_type = csdp->codeset_type;
4637 			tp->t_csdata.csinfo_num = csdp->csinfo_num;
4638 			bcopy(csdp->eucpc_data, tp->t_csdata.eucpc_data,
4639 			    sizeof (ldterm_eucpc_data_t) *
4640 			    LDTERM_CS_MAX_CODESETS);
4641 			tp->t_csmethods = cs_methods[csdp->codeset_type];
4642 
4643 			if (csdp->codeset_type == LDTERM_CS_TYPE_EUC) {
4644 				tp->eucwioc.eucw[0] = 1;
4645 				tp->eucwioc.scrw[0] = 1;
4646 
4647 				tp->eucwioc.eucw[1] =
4648 				    csdp->eucpc_data[0].byte_length;
4649 				tp->eucwioc.scrw[1] =
4650 				    csdp->eucpc_data[0].screen_width;
4651 
4652 				tp->eucwioc.eucw[2] =
4653 				    csdp->eucpc_data[1].byte_length + 1;
4654 				tp->eucwioc.scrw[2] =
4655 				    csdp->eucpc_data[1].screen_width;
4656 
4657 				tp->eucwioc.eucw[3] =
4658 				    csdp->eucpc_data[2].byte_length + 1;
4659 				tp->eucwioc.scrw[3] =
4660 				    csdp->eucpc_data[2].screen_width;
4661 			} else {
4662 				/*
4663 				 * We are not going to use this data
4664 				 * structure. So, clear it. Also, stty(1) will
4665 				 * make use of the cleared tp->eucwioc when
4666 				 * it prints out codeset width setting.
4667 				 */
4668 				bzero(&tp->eucwioc, EUCSIZE);
4669 			}
4670 		} else {
4671 			/*
4672 			 * If this codeset is a single byte codeset that
4673 			 * requires only single display column for all
4674 			 * characters, we switch to default EUC codeset
4675 			 * methods and data setting.
4676 			 */
4677 
4678 			if (tp->t_eucp_mp) {
4679 				freemsg(tp->t_eucp_mp);
4680 				tp->t_eucp_mp = NULL;
4681 				tp->t_eucp = NULL;
4682 			}
4683 
4684 			bzero(&tp->eucwioc, EUCSIZE);
4685 			tp->eucwioc.eucw[0] = 1;
4686 			tp->eucwioc.scrw[0] = 1;
4687 			if (tp->t_csdata.locale_name != (char *)NULL) {
4688 				kmem_free(tp->t_csdata.locale_name,
4689 				    strlen(tp->t_csdata.locale_name) + 1);
4690 			}
4691 			tp->t_csdata = default_cs_data;
4692 			tp->t_csmethods = cs_methods[LDTERM_CS_TYPE_EUC];
4693 		}
4694 
4695 		/* Copy over locale_name. */
4696 		if (tp->t_csdata.locale_name != (char *)NULL) {
4697 			kmem_free(tp->t_csdata.locale_name,
4698 			    strlen(tp->t_csdata.locale_name) + 1);
4699 		}
4700 		if (locale_name_sz > 1) {
4701 			tp->t_csdata.locale_name = (char *)kmem_alloc(
4702 			    locale_name_sz, KM_SLEEP);
4703 			(void) strcpy(tp->t_csdata.locale_name,
4704 			    csdp->locale_name);
4705 		} else {
4706 			tp->t_csdata.locale_name = (char *)NULL;
4707 		}
4708 
4709 		/*
4710 		 * Now ACK the ioctl.
4711 		 */
4712 		iocp->ioc_rval = 0;
4713 		miocack(q, mp, 0, 0);
4714 		return;
4715 
4716 	case CSDATA_GET:
4717 		error = miocpullup(mp, sizeof (ldterm_cs_data_user_t));
4718 		if (error != 0) {
4719 			miocnak(q, mp, 0, error);
4720 			return;
4721 		}
4722 
4723 		csdp = (ldterm_cs_data_user_t *)mp->b_cont->b_rptr;
4724 
4725 		csdp->version = tp->t_csdata.version;
4726 		csdp->codeset_type = tp->t_csdata.codeset_type;
4727 		csdp->csinfo_num = tp->t_csdata.csinfo_num;
4728 		csdp->pad = tp->t_csdata.pad;
4729 		if (tp->t_csdata.locale_name) {
4730 			(void) strcpy(csdp->locale_name,
4731 			    tp->t_csdata.locale_name);
4732 		} else {
4733 			csdp->locale_name[0] = '\0';
4734 		}
4735 		bcopy(tp->t_csdata.eucpc_data, csdp->eucpc_data,
4736 		    sizeof (ldterm_eucpc_data_t) * LDTERM_CS_MAX_CODESETS);
4737 		/*
4738 		 * If the codeset is an EUC codeset and if it has 2nd and/or
4739 		 * 3rd supplementary codesets, we subtract one from each
4740 		 * byte length of the supplementary codesets. This is
4741 		 * because single shift characters, SS2 and SS3, are not
4742 		 * included in the byte lengths in the user space.
4743 		 */
4744 		if (csdp->codeset_type == LDTERM_CS_TYPE_EUC) {
4745 			if (csdp->eucpc_data[1].byte_length)
4746 				csdp->eucpc_data[1].byte_length -= 1;
4747 			if (csdp->eucpc_data[2].byte_length)
4748 				csdp->eucpc_data[2].byte_length -= 1;
4749 		}
4750 		iocp->ioc_rval = 0;
4751 		miocack(q, mp, sizeof (ldterm_cs_data_user_t), 0);
4752 		return;
4753 
4754 	case PTSSTTY:
4755 		tp->t_state |= TS_ISPTSTTY;
4756 		break;
4757 
4758 	}
4759 
4760 	putnext(q, mp);
4761 }
4762 
4763 
4764 /*
4765  * Send an M_SETOPTS message upstream if any mode changes are being
4766  * made that affect the stream head options. returns -1 if allocb
4767  * fails, else returns 0.
4768  */
4769 static int
4770 chgstropts(struct termios *oldmodep, ldtermstd_state_t *tp, queue_t *q)
4771 {
4772 	struct stroptions optbuf;
4773 	mblk_t *bp;
4774 
4775 	optbuf.so_flags = 0;
4776 	if ((oldmodep->c_lflag ^ tp->t_modes.c_lflag) & ICANON) {
4777 		/*
4778 		 * Canonical mode is changing state; switch the
4779 		 * stream head to message-nondiscard or byte-stream
4780 		 * mode.  Also, rerun the service procedure so it can
4781 		 * change its mind about whether to send data
4782 		 * upstream or not.
4783 		 */
4784 		if (tp->t_modes.c_lflag & ICANON) {
4785 			DEBUG4(("CHANGING TO CANON MODE\n"));
4786 			optbuf.so_flags = SO_READOPT|SO_MREADOFF;
4787 			optbuf.so_readopt = RMSGN;
4788 
4789 			/*
4790 			 * if there is a pending raw mode timeout,
4791 			 * clear it
4792 			 */
4793 
4794 			/*
4795 			 * Clear VMIN/VTIME state, cancel timers
4796 			 */
4797 			vmin_satisfied(q, tp, 0);
4798 		} else {
4799 			DEBUG4(("CHANGING TO RAW MODE\n"));
4800 			optbuf.so_flags = SO_READOPT|SO_MREADON;
4801 			optbuf.so_readopt = RNORM;
4802 		}
4803 	}
4804 	if ((oldmodep->c_lflag ^ tp->t_modes.c_lflag) & TOSTOP) {
4805 		/*
4806 		 * The "stop on background write" bit is changing.
4807 		 */
4808 		if (tp->t_modes.c_lflag & TOSTOP)
4809 			optbuf.so_flags |= SO_TOSTOP;
4810 		else
4811 			optbuf.so_flags |= SO_TONSTOP;
4812 	}
4813 	if (optbuf.so_flags != 0) {
4814 		if ((bp = allocb(sizeof (struct stroptions), BPRI_HI)) ==
4815 		    NULL) {
4816 			return (-1);
4817 		}
4818 		*(struct stroptions *)bp->b_wptr = optbuf;
4819 		bp->b_wptr += sizeof (struct stroptions);
4820 		bp->b_datap->db_type = M_SETOPTS;
4821 		DEBUG4(("M_SETOPTS to stream head\n"));
4822 		putnext(q, bp);
4823 	}
4824 	return (0);
4825 }
4826 
4827 
4828 /*
4829  * Called when an M_IOCACK message is seen on the read queue;
4830  * modifies the data being returned, if necessary, and passes the
4831  * reply up.
4832  */
4833 static void
4834 ldterm_ioctl_reply(queue_t *q, mblk_t *mp)
4835 {
4836 	ldtermstd_state_t *tp;
4837 	struct iocblk *iocp;
4838 
4839 	iocp = (struct iocblk *)mp->b_rptr;
4840 	tp = (ldtermstd_state_t *)q->q_ptr;
4841 
4842 	switch (iocp->ioc_cmd) {
4843 
4844 	case TCGETS:
4845 		{
4846 			/*
4847 			 * Get current parameters and return them to
4848 			 * stream head eventually.
4849 			 */
4850 			struct termios *cb =
4851 			    (struct termios *)mp->b_cont->b_rptr;
4852 
4853 			/*
4854 			 * cflag has cflags sent upstream by the
4855 			 * driver
4856 			 */
4857 			tcflag_t cflag = cb->c_cflag;
4858 
4859 			*cb = tp->t_amodes;
4860 			if (cflag != 0)
4861 				cb->c_cflag = cflag;	/* set by driver */
4862 			break;
4863 		}
4864 
4865 	case TCGETA:
4866 		{
4867 			/*
4868 			 * Old-style "ioctl" to get current
4869 			 * parameters and return them to stream head
4870 			 * eventually.
4871 			 */
4872 			struct termio *cb =
4873 			    (struct termio *)mp->b_cont->b_rptr;
4874 
4875 			cb->c_iflag = tp->t_amodes.c_iflag; /* all except the */
4876 			cb->c_oflag = tp->t_amodes.c_oflag; /* cb->c_cflag */
4877 			cb->c_lflag = tp->t_amodes.c_lflag;
4878 
4879 			if (cb->c_cflag == 0)	/* not set by driver */
4880 				cb->c_cflag = tp->t_amodes.c_cflag;
4881 
4882 			cb->c_line = 0;
4883 			bcopy(tp->t_amodes.c_cc, cb->c_cc, NCC);
4884 			break;
4885 		}
4886 	}
4887 	putnext(q, mp);
4888 }
4889 
4890 
4891 /*
4892  * A VMIN/VTIME request has been satisfied. Cancel outstanding timers
4893  * if they exist, clear TS_MREAD state, and send upstream. If a NULL
4894  * queue ptr is passed, just reset VMIN/VTIME state.
4895  */
4896 static void
4897 vmin_satisfied(queue_t *q, ldtermstd_state_t *tp, int sendup)
4898 {
4899 	ASSERT(q);
4900 	if (tp->t_vtid != 0)  {
4901 		DEBUG4(("vmin_satisfied: cancelled timer id %d\n", tp->t_vtid));
4902 		(void) quntimeout(q, tp->t_vtid);
4903 		tp->t_vtid = 0;
4904 	}
4905 	if (sendup) {
4906 		if (tp->t_msglen == 0 && V_MIN) {
4907 			/* EMPTY */
4908 			DEBUG4(("vmin_satisfied: data swiped, msglen = 0\n"));
4909 		} else {
4910 			if ((!q->q_first) ||
4911 			    (q->q_first->b_datap->db_type != M_DATA) ||
4912 			    (tp->t_msglen >= LDCHUNK)) {
4913 				ldterm_msg_upstream(q, tp);
4914 				DEBUG4(("vmin_satisfied: delivering data\n"));
4915 			}
4916 		}
4917 	} else {
4918 		/* EMPTY */
4919 		DEBUG4(("vmin_satisfied: VMIN/TIME state reset\n"));
4920 	}
4921 	tp->t_state &= ~TS_MREAD;
4922 }
4923 
4924 static void
4925 vmin_settimer(queue_t *q)
4926 {
4927 	ldtermstd_state_t *tp;
4928 
4929 	tp = (ldtermstd_state_t *)q->q_ptr;
4930 
4931 	/*
4932 	 * Don't start any time bombs.
4933 	 */
4934 	if (tp->t_state & TS_CLOSE)
4935 		return;
4936 
4937 	/*
4938 	 * tp->t_vtid should NOT be set here unless VMIN > 0 and
4939 	 * VTIME > 0.
4940 	 */
4941 	if (tp->t_vtid) {
4942 		if (V_MIN && V_TIME) {
4943 			/* EMPTY */
4944 			DEBUG4(("vmin_settimer: timer restarted, old tid=%d\n",
4945 			    tp->t_vtid));
4946 		} else {
4947 			/* EMPTY */
4948 			DEBUG4(("vmin_settimer: tid = %d was still active!\n",
4949 			    tp->t_vtid));
4950 		}
4951 		(void) quntimeout(q, tp->t_vtid);
4952 		tp->t_vtid = 0;
4953 	}
4954 	tp->t_vtid = qtimeout(q, vmin_timed_out, q,
4955 	    (clock_t)(V_TIME * (hz / 10)));
4956 	DEBUG4(("vmin_settimer: timer started, tid = %d\n", tp->t_vtid));
4957 }
4958 
4959 
4960 /*
4961  * BRRrrringgg!! VTIME was satisfied instead of VMIN
4962  */
4963 static void
4964 vmin_timed_out(void *arg)
4965 {
4966 	queue_t *q = arg;
4967 	ldtermstd_state_t *tp;
4968 
4969 	tp = (ldtermstd_state_t *)q->q_ptr;
4970 
4971 	DEBUG4(("vmin_timed_out: tid = %d\n", tp->t_vtid));
4972 	/* don't call untimeout now that we are in the timeout */
4973 	tp->t_vtid = 0;
4974 	vmin_satisfied(q, tp, 1);
4975 }
4976 
4977 
4978 /*
4979  * Routine to adjust termios flags to be processed by the line
4980  * discipline. Driver below sends a termios structure, with the flags
4981  * the driver intends to process. XOR'ing the driver sent termios
4982  * structure with current termios structure with the default values
4983  * (or set by ioctls from userland), we come up with a new termios
4984  * structrue, the flags of which will be used by the line discipline
4985  * in processing input and output. On return from this routine, we
4986  * will have the following fields set in tp structure -->
4987  * tp->t_modes:	modes the line discipline will process tp->t_amodes:
4988  * modes the user process thinks the line discipline is processing
4989  */
4990 
4991 static void
4992 ldterm_adjust_modes(ldtermstd_state_t *tp)
4993 {
4994 
4995 	DEBUG6(("original iflag = %o\n", tp->t_modes.c_iflag));
4996 	tp->t_modes.c_iflag = tp->t_amodes.c_iflag & ~(tp->t_dmodes.c_iflag);
4997 	tp->t_modes.c_oflag = tp->t_amodes.c_oflag & ~(tp->t_dmodes.c_oflag);
4998 	tp->t_modes.c_lflag = tp->t_amodes.c_lflag & ~(tp->t_dmodes.c_lflag);
4999 	DEBUG6(("driver iflag = %o\n", tp->t_dmodes.c_iflag));
5000 	DEBUG6(("apparent iflag = %o\n", tp->t_amodes.c_iflag));
5001 	DEBUG6(("effective iflag = %o\n", tp->t_modes.c_iflag));
5002 
5003 	/* No negotiation of clfags  c_cc array special characters */
5004 	/*
5005 	 * Copy from amodes to modes already done by TCSETA/TCSETS
5006 	 * code
5007 	 */
5008 }
5009 
5010 
5011 /*
5012  * Erase one multi-byte character.  If TS_MEUC is set AND this
5013  * is a multi-byte character, then this should be called instead of
5014  * ldterm_erase.  "ldterm_erase" will handle ASCII nicely, thank you.
5015  *
5016  * We'd better be pointing to the last byte.  If we aren't, it will get
5017  * screwed up.
5018  */
5019 static void
5020 ldterm_csi_erase(queue_t *q, size_t ebsize, ldtermstd_state_t *tp)
5021 {
5022 	int i, ung;
5023 	uchar_t *p, *bottom;
5024 	uchar_t u8[LDTERM_CS_MAX_BYTE_LENGTH];
5025 	int c;
5026 	int j;
5027 	int len;
5028 
5029 	if (tp->t_eucleft) {
5030 		/* XXX Ick.  We're in the middle of an EUC! */
5031 		/* What to do now? */
5032 		ldterm_eucwarn(tp);
5033 		return;		/* ignore it??? */
5034 	}
5035 	bottom = tp->t_eucp_mp->b_rptr;
5036 	p = tp->t_eucp - 1;	/* previous byte */
5037 	if (p < bottom)
5038 		return;
5039 	ung = 1;		/* number of bytes to un-get from buffer */
5040 	/*
5041 	 * go through the buffer until we find the beginning of the
5042 	 * multi-byte char.
5043 	 */
5044 	while ((*p == 0) && (p > bottom)) {
5045 		p--;
5046 		++ung;
5047 	}
5048 
5049 	/*
5050 	 * Now, "ung" is the number of bytes to unget from the buffer
5051 	 * and "*p" is the disp width of it. Fool "ldterm_rubout"
5052 	 * into thinking we're rubbing out ASCII characters.  Do that
5053 	 * for the display width of the character.
5054 	 *
5055 	 * Also we accumulate bytes of the character so that if the character
5056 	 * is a UTF-8 character, we will get the display width of the UTF-8
5057 	 * character.
5058 	 */
5059 	if (ung >= LDTERM_CS_MAX_BYTE_LENGTH) {
5060 		j = len = LDTERM_CS_MAX_BYTE_LENGTH;
5061 	} else {
5062 		j = len = ung;
5063 	}
5064 	for (i = 0; i < ung; i++) {	/* remove from buf */
5065 		if ((c = ldterm_unget(tp)) != (-1)) {
5066 			ldterm_trim(tp);
5067 			if (j > 0)
5068 				u8[--j] = (uchar_t)c;
5069 		}
5070 	}
5071 	if (*p == UNKNOWN_WIDTH) {
5072 		if (tp->t_csdata.codeset_type == LDTERM_CS_TYPE_UTF8) {
5073 			*p = ldterm_utf8_width(u8, len);
5074 		} else {
5075 			*p = 1;
5076 		}
5077 	}
5078 	for (i = 0; i < (int)*p; i++)	/* remove from screen */
5079 		ldterm_rubout(' ', q, ebsize, tp);
5080 	/*
5081 	 * Adjust the parallel array pointer.  Zero out the contents
5082 	 * of parallel array for this position, just to make sure...
5083 	 */
5084 	tp->t_eucp = p;
5085 	*p = 0;
5086 }
5087 
5088 
5089 /*
5090  * This is kind of a safety valve.  Whenever we see a bad sequence
5091  * come up, we call eucwarn.  It just tallies the junk until a
5092  * threshold is reached.  Then it prints ONE message on the console
5093  * and not any more. Hopefully, we can catch garbage; maybe it will
5094  * be useful to somebody.
5095  */
5096 static void
5097 ldterm_eucwarn(ldtermstd_state_t *tp)
5098 {
5099 	++tp->t_eucwarn;
5100 #ifdef DEBUG
5101 	if ((tp->t_eucwarn > EUC_WARNCNT) && !(tp->t_state & TS_WARNED)) {
5102 		cmn_err(CE_WARN,
5103 		    "ldterm: tty at addr %p in multi-byte mode --",
5104 		    (void *)tp);
5105 		cmn_err(CE_WARN,
5106 		    "Over %d bad EUC characters this session", EUC_WARNCNT);
5107 		tp->t_state |= TS_WARNED;
5108 	}
5109 #endif
5110 }
5111 
5112 
5113 /*
5114  * Copy an "eucioc_t" structure.  We use the structure with
5115  * incremented values for Codesets 2 & 3.  The specification in
5116  * eucioctl is that the sames values as the CSWIDTH definition at
5117  * user level are passed to us. When we copy it "in" to ourselves, we
5118  * do the increment.  That allows us to avoid treating each character
5119  * set separately for "t_eucleft" purposes. When we copy it "out" to
5120  * return it to the user, we decrement the values so the user gets
5121  * what it expects, and it matches CSWIDTH in the environment (if
5122  * things are consistent!).
5123  */
5124 static void
5125 cp_eucwioc(eucioc_t *from, eucioc_t *to, int dir)
5126 {
5127 	bcopy(from, to, EUCSIZE);
5128 	if (dir == EUCOUT) {	/* copying out to user */
5129 		if (to->eucw[2])
5130 			--to->eucw[2];
5131 		if (to->eucw[3])
5132 			--to->eucw[3];
5133 	} else {		/* copying in */
5134 		if (to->eucw[2])
5135 			++to->eucw[2];
5136 		if (to->eucw[3])
5137 			++to->eucw[3];
5138 	}
5139 }
5140 
5141 
5142 /*
5143  * Take the first byte of a multi-byte, or an ASCII char.  Return its
5144  * codeset. If it's NOT the first byte of an EUC, then the return
5145  * value may be garbage, as it's probably not SS2 or SS3, and
5146  * therefore must be in codeset 1.  Another bizarre catch here is the
5147  * fact that we don't do anything about the "C1" control codes.  In
5148  * real life, we should; but nobody's come up with a good way of
5149  * treating them.
5150  */
5151 
5152 static int
5153 ldterm_codeset(uchar_t codeset_type, uchar_t c)
5154 {
5155 
5156 	if (ISASCII(c))
5157 		return (0);
5158 
5159 	if (codeset_type != LDTERM_CS_TYPE_EUC)
5160 		return (1);
5161 
5162 	switch (c) {
5163 	case SS2:
5164 		return (2);
5165 	case SS3:
5166 		return (3);
5167 	default:
5168 		return (1);
5169 	}
5170 }
5171 
5172 /* The following two functions are additional EUC codeset specific methods. */
5173 /*
5174  * ldterm_dispwidth - Take the first byte of an EUC (or ASCII) and
5175  * return the display width.  Since this is intended mostly for
5176  * multi-byte handling, it returns EUC_TWIDTH for tabs so they can be
5177  * differentiated from EUC characters (assumption: EUC require fewer
5178  * than 255 columns).  Also, if it's a backspace and !flag, it
5179  * returns EUC_BSWIDTH.  Newline & CR also depend on flag.  This
5180  * routine SHOULD be cleaner than this, but we have the situation
5181  * where we may or may not be counting control characters as having a
5182  * column width. Therefore, the computation of ASCII is pretty messy.
5183  * The caller will be storing the value, and then switching on it
5184  * when it's used.  We really should define the EUC_TWIDTH and other
5185  * constants in a header so that the routine could be used in other
5186  * modules in the kernel.
5187  */
5188 static int
5189 __ldterm_dispwidth_euc(uchar_t c, void *p, int mode)
5190 {
5191 	ldtermstd_state_t *tp = (ldtermstd_state_t *)p;
5192 
5193 	if (ISASCII(c)) {
5194 		if (c <= '\037') {
5195 			switch (c) {
5196 			case '\t':
5197 				return (EUC_TWIDTH);
5198 			case '\b':
5199 				return (mode ? 2 : EUC_BSWIDTH);
5200 			case '\n':
5201 				return (EUC_NLWIDTH);
5202 			case '\r':
5203 				return (mode ? 2 : EUC_CRWIDTH);
5204 			default:
5205 				return (mode ? 2 : 0);
5206 			}
5207 		}
5208 		return (1);
5209 	}
5210 	switch (c) {
5211 	case SS2:
5212 		return (tp->eucwioc.scrw[2]);
5213 	case SS3:
5214 		return (tp->eucwioc.scrw[3]);
5215 	default:
5216 		return (tp->eucwioc.scrw[1]);
5217 	}
5218 }
5219 
5220 /*
5221  * ldterm_memwidth_euc - Take the first byte of an EUC (or an ASCII char)
5222  * and return its memory width.  The routine could have been
5223  * implemented to use only the codeset number, but that would require
5224  * the caller to have that value available.  Perhaps the user doesn't
5225  * want to make the extra call or keep the value of codeset around.
5226  * Therefore, we use the actual character with which they're
5227  * concerned.  This should never be called with anything but the
5228  * first byte of an EUC, otherwise it will return a garbage value.
5229  */
5230 static int
5231 __ldterm_memwidth_euc(uchar_t c, void *p)
5232 {
5233 	ldtermstd_state_t *tp = (ldtermstd_state_t *)p;
5234 
5235 	if (ISASCII(c))
5236 		return (1);
5237 	switch (c) {
5238 	case SS2:
5239 		return (tp->eucwioc.eucw[2]);
5240 	case SS3:
5241 		return (tp->eucwioc.eucw[3]);
5242 	default:
5243 		return (tp->eucwioc.eucw[1]);
5244 	}
5245 }
5246 
5247 
5248 /* The following two functions are PCCS codeset specific methods. */
5249 static int
5250 __ldterm_dispwidth_pccs(uchar_t c, void *p, int mode)
5251 {
5252 	ldtermstd_state_t *tp = (ldtermstd_state_t *)p;
5253 	int i;
5254 
5255 	if (ISASCII(c)) {
5256 		if (c <= '\037') {
5257 			switch (c) {
5258 			case '\t':
5259 				return (EUC_TWIDTH);
5260 			case '\b':
5261 				return (mode ? 2 : EUC_BSWIDTH);
5262 			case '\n':
5263 				return (EUC_NLWIDTH);
5264 			case '\r':
5265 				return (mode ? 2 : EUC_CRWIDTH);
5266 			default:
5267 				return (mode ? 2 : 0);
5268 			}
5269 		}
5270 		return (1);
5271 	}
5272 
5273 	for (i = 0; i < tp->t_csdata.csinfo_num; i++) {
5274 		if (c >= tp->t_csdata.eucpc_data[i].msb_start &&
5275 		    c <= tp->t_csdata.eucpc_data[i].msb_end)
5276 			return (tp->t_csdata.eucpc_data[i].screen_width);
5277 	}
5278 
5279 	/*
5280 	 * If this leading byte is not in the range list, either provided
5281 	 * locale data is not sufficient or we encountered an invalid
5282 	 * character. We return 1 in this case as a fallback value.
5283 	 */
5284 	return (1);
5285 }
5286 
5287 static int
5288 __ldterm_memwidth_pccs(uchar_t c, void *p)
5289 {
5290 	ldtermstd_state_t *tp = (ldtermstd_state_t *)p;
5291 	int i;
5292 
5293 	for (i = 0; i < tp->t_csdata.csinfo_num; i++) {
5294 		if (c >= tp->t_csdata.eucpc_data[i].msb_start &&
5295 		    c <= tp->t_csdata.eucpc_data[i].msb_end)
5296 			return (tp->t_csdata.eucpc_data[i].byte_length);
5297 	}
5298 
5299 	/*
5300 	 * If this leading byte is not in the range list, either provided
5301 	 * locale data is not sufficient or we encountered an invalid
5302 	 * character. We return 1 in this case as a fallback value.
5303 	 */
5304 	return (1);
5305 }
5306 
5307 
5308 /* The following two functions are UTF-8 codeset specific methods. */
5309 static int
5310 __ldterm_dispwidth_utf8(uchar_t c, void *p, int mode)
5311 {
5312 	ldtermstd_state_t *tp = (ldtermstd_state_t *)p;
5313 
5314 	if (ISASCII(c)) {
5315 		if (c <= '\037') {
5316 			switch (c) {
5317 			case '\t':
5318 				return (EUC_TWIDTH);
5319 			case '\b':
5320 				return (mode ? 2 : EUC_BSWIDTH);
5321 			case '\n':
5322 				return (EUC_NLWIDTH);
5323 			case '\r':
5324 				return (mode ? 2 : EUC_CRWIDTH);
5325 			default:
5326 				return (mode ? 2 : 0);
5327 			}
5328 		}
5329 		return (1);
5330 	}
5331 
5332 	/* This is to silence the lint. */
5333 	if (tp->t_csdata.codeset_type != LDTERM_CS_TYPE_UTF8)
5334 		return (1);
5335 
5336 	/*
5337 	 * If it is a valid leading byte of a UTF-8 character, we set
5338 	 * the width as 'UNKNOWN_WIDTH' for now. We need to have all
5339 	 * the bytes to figure out the display width.
5340 	 */
5341 	if (c >= (uchar_t)0xc0 && c <= (uchar_t)0xfd)
5342 		return (UNKNOWN_WIDTH);
5343 
5344 	/*
5345 	 * If it is an invalid leading byte, we just do our best by
5346 	 * giving the display width of 1.
5347 	 */
5348 	return (1);
5349 }
5350 
5351 
5352 static int
5353 __ldterm_memwidth_utf8(uchar_t c, void *p)
5354 {
5355 	ldtermstd_state_t *tp = (ldtermstd_state_t *)p;
5356 	int len;
5357 
5358 	/*
5359 	 * If the codeset type doesn't match, we treat them as
5360 	 * an illegal character and return 1.
5361 	 */
5362 	if (tp->t_csdata.codeset_type != LDTERM_CS_TYPE_UTF8)
5363 		return (1);
5364 
5365 	len = u8_number_of_bytes[c];
5366 
5367 	/*
5368 	 * If this is a start of an illegal character, we treat
5369 	 * such as an 1 byte character and screen out.
5370 	 */
5371 	return ((len <= 0) ? 1 : len);
5372 }
5373 
5374 static uchar_t
5375 ldterm_utf8_width(uchar_t *u8, int length)
5376 {
5377 	int i;
5378 	int j;
5379 	uint_t intcode = 0;
5380 
5381 	if (length == 0)
5382 		return ('\0');
5383 
5384 	j = u8_number_of_bytes[u8[0]] - 1;
5385 
5386 	/*
5387 	 * If the UTF-8 character is out of UTF-16 code range, or,
5388 	 * if it is either an ASCII character or an invalid leading byte for
5389 	 * a UTF-8 character, return 1.
5390 	 */
5391 	if (length > 4 || j <= 0)
5392 		return ('\1');
5393 
5394 	intcode = u8[0] & u8_masks_tbl[j];
5395 	for (i = 1; j > 0; j--, i++) {
5396 		/*
5397 		 * The following additional checking is needed to conform to
5398 		 * the "UTF-8 Corrigendum" introduced at the Unicode 3.1 and
5399 		 * then updated one more time at the Unicode 3.2.
5400 		 */
5401 		if (i == 1) {
5402 			if (u8[i] < u8_valid_min_2nd_byte[u8[0]] ||
5403 			    u8[i] > u8_valid_max_2nd_byte[u8[0]])
5404 				return ('\1');
5405 		} else if (u8[i] < (uchar_t)LDTERM_CS_TYPE_UTF8_MIN_BYTE ||
5406 		    u8[i] > (uchar_t)LDTERM_CS_TYPE_UTF8_MAX_BYTE)
5407 			return ('\1');
5408 
5409 		/*
5410 		 * All subsequent bytes of UTF-8 character has the following
5411 		 * binary encoding:
5412 		 *
5413 		 * 10xx xxxx
5414 		 *
5415 		 * hence left shift six bits to make space and then get
5416 		 * six bits from the new byte.
5417 		 */
5418 		intcode = (intcode << LDTERM_CS_TYPE_UTF8_SHIFT_BITS) |
5419 		    (u8[i] & LDTERM_CS_TYPE_UTF8_BIT_MASK);
5420 	}
5421 
5422 	i = 0;
5423 	if (intcode <= LDTERM_CS_TYPE_UTF8_MAX_P00) {
5424 		/* Basic Multilingual Plane. */
5425 		i = intcode / 4;
5426 		j = intcode % 4;
5427 		switch (j) {
5428 		case 0:
5429 			i = ldterm_ucode[0][i].u0;
5430 			break;
5431 		case 1:
5432 			i = ldterm_ucode[0][i].u1;
5433 			break;
5434 		case 2:
5435 			i = ldterm_ucode[0][i].u2;
5436 			break;
5437 		case 3:
5438 			i = ldterm_ucode[0][i].u3;
5439 			break;
5440 		}
5441 	} else if (intcode <= LDTERM_CS_TYPE_UTF8_MAX_P01) {
5442 		/* Secondary Multilingual Plane. */
5443 		intcode = intcode & (uint_t)0xffff;
5444 		i = intcode / 4;
5445 		j = intcode % 4;
5446 		switch (j) {
5447 		case 0:
5448 			i = ldterm_ucode[1][i].u0;
5449 			break;
5450 		case 1:
5451 			i = ldterm_ucode[1][i].u1;
5452 			break;
5453 		case 2:
5454 			i = ldterm_ucode[1][i].u2;
5455 			break;
5456 		case 3:
5457 			i = ldterm_ucode[1][i].u3;
5458 			break;
5459 		}
5460 	} else if ((intcode >= LDTERM_CS_TYPE_UTF8_MIN_CJKEXTB &&
5461 	    intcode <= LDTERM_CS_TYPE_UTF8_MAX_CJKEXTB) ||
5462 	    (intcode >= LDTERM_CS_TYPE_UTF8_MIN_CJKCOMP &&
5463 	    intcode <= LDTERM_CS_TYPE_UTF8_MAX_CJKCOMP) ||
5464 	    (intcode >= LDTERM_CS_TYPE_UTF8_MIN_P15 &&
5465 	    intcode <= LDTERM_CS_TYPE_UTF8_MAX_P15) ||
5466 	    (intcode >= LDTERM_CS_TYPE_UTF8_MIN_P16 &&
5467 	    intcode <= LDTERM_CS_TYPE_UTF8_MAX_P16)) {
5468 		/*
5469 		 * Supplementary Plane for CJK Ideographs and
5470 		 * Private Use Planes.
5471 		 */
5472 		return ('\2');
5473 	} else if ((intcode >= LDTERM_CS_TYPE_UTF8_MIN_P14 &&
5474 	    intcode <= LDTERM_CS_TYPE_UTF8_MAX_P14) ||
5475 	    (intcode >= LDTERM_CS_TYPE_UTF8_MIN_VARSEL &&
5476 	    intcode <= LDTERM_CS_TYPE_UTF8_MAX_VARSEL)) {
5477 		/*
5478 		 * Some Special Purpose Plane characters:
5479 		 * These are like control characters and not printable.
5480 		 */
5481 		return ('\0');
5482 	}
5483 
5484 	/*
5485 	 * We return the display width of 1 for all character code points
5486 	 * that we didn't catch from the above logic and also for combining
5487 	 * and conjoining characters with width value of zero.
5488 	 *
5489 	 * In particular, the reason why we are returning 1 for combining
5490 	 * and conjoining characters is because the GUI-based terminal
5491 	 * emulators are not yet capable of properly handling such characters
5492 	 * and in most of the cases, they just treat such characters as if
5493 	 * they occupy a display cell. If the terminal emulators are capable of
5494 	 * handling the characters correctly, then, this logic of returning
5495 	 * 1 should be revisited and changed. See CR 6660526 for more
5496 	 * details on this.
5497 	 */
5498 	return ((i == 0) ? '\1' : (uchar_t)i);
5499 }
5500