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