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