Home | History | Annotate | Download | only in io
      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