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