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