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