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] || c == tp->t_modes.c_cc[VERASE2]) { 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 }