Print this page
14249 pseudo-terminal nomenclature should reflect POSIX
Change-Id: Ib4a3cef899ff4c71b09cb0dc6878863c5e8357bc
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/ptem.c
+++ new/usr/src/uts/common/io/ptem.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 23 /* All Rights Reserved */
24 24
25 25
26 26 /*
27 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 28 * Use is subject to license terms.
29 29 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
30 30 */
31 31
32 32 /*
33 33 * Description:
34 34 *
35 35 * The PTEM streams module is used as a pseudo driver emulator. Its purpose
36 36 * is to emulate the ioctl() functions of a terminal device driver.
37 37 */
38 38
39 39 #include <sys/types.h>
40 40 #include <sys/param.h>
41 41 #include <sys/stream.h>
42 42 #include <sys/stropts.h>
43 43 #include <sys/strsun.h>
44 44 #include <sys/termio.h>
45 45 #include <sys/pcb.h>
46 46 #include <sys/signal.h>
47 47 #include <sys/cred.h>
48 48 #include <sys/strtty.h>
49 49 #include <sys/errno.h>
50 50 #include <sys/cmn_err.h>
51 51 #include <sys/jioctl.h>
52 52 #include <sys/ptem.h>
53 53 #include <sys/ptms.h>
54 54 #include <sys/debug.h>
55 55 #include <sys/kmem.h>
56 56 #include <sys/ddi.h>
57 57 #include <sys/sunddi.h>
58 58 #include <sys/conf.h>
59 59 #include <sys/modctl.h>
60 60
61 61 extern struct streamtab pteminfo;
62 62
63 63 static struct fmodsw fsw = {
64 64 "ptem",
65 65 &pteminfo,
66 66 D_MTQPAIR | D_MP | _D_SINGLE_INSTANCE
67 67 };
68 68
69 69 static struct modlstrmod modlstrmod = {
70 70 &mod_strmodops, "pty hardware emulator", &fsw
71 71 };
72 72
73 73 static struct modlinkage modlinkage = {
74 74 MODREV_1, &modlstrmod, NULL
75 75 };
76 76
77 77 int
78 78 _init()
79 79 {
80 80 return (mod_install(&modlinkage));
81 81 }
82 82
83 83 int
84 84 _fini()
85 85 {
86 86 return (mod_remove(&modlinkage));
87 87 }
88 88
89 89 int
90 90 _info(struct modinfo *modinfop)
91 91 {
92 92 return (mod_info(&modlinkage, modinfop));
93 93 }
94 94
95 95 /*
96 96 * stream data structure definitions
97 97 */
98 98 static int ptemopen(queue_t *, dev_t *, int, int, cred_t *);
99 99 static int ptemclose(queue_t *, int, cred_t *);
100 100 static int ptemrput(queue_t *, mblk_t *);
101 101 static int ptemwput(queue_t *, mblk_t *);
102 102 static int ptemwsrv(queue_t *);
103 103
104 104 static struct module_info ptem_info = {
105 105 0xabcd,
106 106 "ptem",
107 107 0,
108 108 _TTY_BUFSIZ,
109 109 _TTY_BUFSIZ,
110 110 128
111 111 };
112 112
113 113 static struct qinit ptemrinit = {
114 114 ptemrput,
115 115 NULL,
116 116 ptemopen,
117 117 ptemclose,
118 118 NULL,
119 119 &ptem_info,
120 120 NULL
121 121 };
122 122
123 123 static struct qinit ptemwinit = {
124 124 ptemwput,
125 125 ptemwsrv,
126 126 ptemopen,
127 127 ptemclose,
128 128 nulldev,
129 129 &ptem_info,
130 130 NULL
131 131 };
132 132
133 133 struct streamtab pteminfo = {
134 134 &ptemrinit,
135 135 &ptemwinit,
136 136 NULL,
137 137 NULL
138 138 };
139 139
140 140 static void ptioc(queue_t *, mblk_t *, int);
141 141 static int ptemwmsg(queue_t *, mblk_t *);
142 142
143 143 /*
144 144 * ptemopen - open routine gets called when the module gets pushed onto the
145 145 * stream.
146 146 */
147 147 /* ARGSUSED */
148 148 static int
149 149 ptemopen(
150 150 queue_t *q, /* pointer to the read side queue */
151 151 dev_t *devp, /* pointer to stream tail's dev */
152 152 int oflag, /* the user open(2) supplied flags */
153 153 int sflag, /* open state flag */
154 154 cred_t *credp) /* credentials */
155 155 {
156 156 struct ptem *ntp; /* ptem entry for this PTEM module */
157 157 mblk_t *mop; /* an setopts mblk */
158 158 struct stroptions *sop;
159 159 struct termios *termiosp;
160 160 int len;
161 161
162 162 if (sflag != MODOPEN)
163 163 return (EINVAL);
164 164
165 165 if (q->q_ptr != NULL) {
166 166 /* It's already attached. */
167 167 return (0);
168 168 }
169 169
170 170 /*
171 171 * Allocate state structure.
172 172 */
173 173 ntp = kmem_alloc(sizeof (*ntp), KM_SLEEP);
174 174
175 175 /*
176 176 * Allocate a message block, used to pass the zero length message for
177 177 * "stty 0".
178 178 *
179 179 * NOTE: it's better to find out if such a message block can be
180 180 * allocated before it's needed than to not be able to
181 181 * deliver (for possible lack of buffers) when a hang-up
182 182 * occurs.
183 183 */
184 184 if ((ntp->dack_ptr = allocb(4, BPRI_MED)) == NULL) {
185 185 kmem_free(ntp, sizeof (*ntp));
186 186 return (EAGAIN);
187 187 }
188 188
189 189 /*
190 190 * Initialize an M_SETOPTS message to set up hi/lo water marks on
191 191 * stream head read queue and add controlling tty if not set.
192 192 */
193 193 mop = allocb(sizeof (struct stroptions), BPRI_MED);
194 194 if (mop == NULL) {
195 195 freemsg(ntp->dack_ptr);
196 196 kmem_free(ntp, sizeof (*ntp));
197 197 return (EAGAIN);
198 198 }
199 199 mop->b_datap->db_type = M_SETOPTS;
200 200 mop->b_wptr += sizeof (struct stroptions);
201 201 sop = (struct stroptions *)mop->b_rptr;
202 202 sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
203 203 sop->so_hiwat = _TTY_BUFSIZ;
204 204 sop->so_lowat = 256;
205 205
206 206 /*
207 207 * Cross-link.
208 208 */
209 209 ntp->q_ptr = q;
210 210 q->q_ptr = ntp;
211 211 WR(q)->q_ptr = ntp;
212 212
213 213 /*
214 214 * Get termios defaults. These are stored as
215 215 * a property in the "options" node.
216 216 */
217 217 if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0, "ttymodes",
218 218 (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS &&
219 219 len == sizeof (struct termios)) {
220 220
221 221 ntp->cflags = termiosp->c_cflag;
222 222 kmem_free(termiosp, len);
223 223 } else {
224 224 /*
225 225 * Gack! Whine about it.
226 226 */
227 227 cmn_err(CE_WARN, "ptem: Couldn't get ttymodes property!");
228 228 }
229 229 ntp->wsz.ws_row = 0;
230 230 ntp->wsz.ws_col = 0;
231 231 ntp->wsz.ws_xpixel = 0;
232 232 ntp->wsz.ws_ypixel = 0;
233 233
234 234 ntp->state = 0;
235 235
236 236 /*
237 237 * Commit to the open and send the M_SETOPTS off to the stream head.
238 238 */
239 239 qprocson(q);
240 240 putnext(q, mop);
241 241
242 242 return (0);
243 243 }
244 244
245 245
246 246 /*
247 247 * ptemclose - This routine gets called when the module gets popped off of the
248 248 * stream.
249 249 */
250 250 /* ARGSUSED */
251 251 static int
252 252 ptemclose(queue_t *q, int flag, cred_t *credp)
253 253 {
254 254 struct ptem *ntp; /* ptem entry for this PTEM module */
255 255
256 256 qprocsoff(q);
257 257 ntp = (struct ptem *)q->q_ptr;
258 258 freemsg(ntp->dack_ptr);
259 259 kmem_free(ntp, sizeof (*ntp));
260 260 q->q_ptr = WR(q)->q_ptr = NULL;
261 261 return (0);
262 262 }
263 263
264 264
265 265 /*
266 266 * ptemrput - Module read queue put procedure.
267 267 *
268 268 * This is called from the module or driver downstream.
269 269 */
270 270 static int
271 271 ptemrput(queue_t *q, mblk_t *mp)
272 272 {
273 273 struct iocblk *iocp; /* M_IOCTL data */
274 274 struct copyresp *resp; /* transparent ioctl response struct */
275 275 int error;
276 276
277 277 switch (mp->b_datap->db_type) {
278 278 case M_DELAY:
279 279 case M_READ:
280 280 freemsg(mp);
281 281 break;
282 282
283 283 case M_IOCTL:
284 284 iocp = (struct iocblk *)mp->b_rptr;
285 285
286 286 switch (iocp->ioc_cmd) {
287 287 case TCSBRK:
288 288 /*
289 289 * Send a break message upstream.
290 290 *
291 291 * XXX: Shouldn't the argument come into play in
292 292 * determining whether or not so send an M_BREAK?
293 293 * It certainly does in the write-side direction.
294 294 */
295 295 error = miocpullup(mp, sizeof (int));
296 296 if (error != 0) {
297 297 miocnak(q, mp, 0, error);
298 298 break;
299 299 }
300 300 if (!(*(int *)mp->b_cont->b_rptr)) {
301 301 if (!putnextctl(q, M_BREAK)) {
302 302 /*
303 303 * Send an NAK reply back
304 304 */
305 305 miocnak(q, mp, 0, EAGAIN);
306 306 break;
307 307 }
308 308 }
309 309 /*
310 310 * ACK it.
311 311 */
312 312 mioc2ack(mp, NULL, 0, 0);
313 313 qreply(q, mp);
314 314 break;
315 315
316 316 case JWINSIZE:
317 317 case TIOCGWINSZ:
318 318 case TIOCSWINSZ:
319 319 ptioc(q, mp, RDSIDE);
320 320 break;
321 321
322 322 case TIOCSIGNAL:
323 323 /*
324 324 * The following subtle logic is due to the fact that
325 325 * `mp' may be in any one of three distinct formats:
326 326 *
327 327 * 1. A transparent M_IOCTL with an intptr_t-sized
328 328 * payload containing the signal number.
329 329 *
330 330 * 2. An I_STR M_IOCTL with an int-sized payload
331 331 * containing the signal number.
332 332 *
333 333 * 3. An M_IOCDATA with an int-sized payload
334 334 * containing the signal number.
335 335 */
336 336 if (iocp->ioc_count == TRANSPARENT) {
337 337 intptr_t sig = *(intptr_t *)mp->b_cont->b_rptr;
338 338
339 339 if (sig < 1 || sig >= NSIG) {
340 340 /*
341 341 * it's transparent with pointer
342 342 * to the arg
343 343 */
344 344 mcopyin(mp, NULL, sizeof (int), NULL);
345 345 qreply(q, mp);
346 346 break;
347 347 }
348 348 }
349 349 ptioc(q, mp, RDSIDE);
350 350 break;
351 351
352 352 case TIOCREMOTE:
353 353 if (iocp->ioc_count != TRANSPARENT)
354 354 ptioc(q, mp, RDSIDE);
355 355 else {
356 356 mcopyin(mp, NULL, sizeof (int), NULL);
357 357 qreply(q, mp);
358 358 }
359 359 break;
360 360
361 361 default:
362 362 putnext(q, mp);
363 363 break;
364 364 }
365 365 break;
366 366
367 367 case M_IOCDATA:
368 368 resp = (struct copyresp *)mp->b_rptr;
369 369 if (resp->cp_rval) {
370 370 /*
371 371 * Just free message on failure.
372 372 */
373 373 freemsg(mp);
374 374 break;
375 375 }
376 376
377 377 /*
378 378 * Only need to copy data for the SET case.
379 379 */
380 380 switch (resp->cp_cmd) {
381 381
382 382 case TIOCSWINSZ:
383 383 case TIOCSIGNAL:
384 384 case TIOCREMOTE:
385 385 ptioc(q, mp, RDSIDE);
386 386 break;
387 387
388 388 case JWINSIZE:
389 389 case TIOCGWINSZ:
390 390 mp->b_datap->db_type = M_IOCACK;
391 391 mioc2ack(mp, NULL, 0, 0);
392 392 qreply(q, mp);
393 393 break;
↓ open down ↓ |
393 lines elided |
↑ open up ↑ |
394 394
395 395 default:
396 396 freemsg(mp);
397 397 break;
398 398 }
399 399 break;
400 400
401 401 case M_IOCACK:
402 402 case M_IOCNAK:
403 403 /*
404 - * We only pass write-side ioctls through to the master that
404 + * We only pass write-side ioctls through to the manager that
405 405 * we've already ACKed or NAKed to the stream head. Thus, we
406 406 * discard ones arriving from below, since they're redundant
407 407 * from the point of view of modules above us.
408 408 */
409 409 freemsg(mp);
410 410 break;
411 411
412 412 case M_HANGUP:
413 413 /*
414 414 * clear blocked state.
415 415 */
416 416 {
417 417 struct ptem *ntp = (struct ptem *)q->q_ptr;
418 418 if (ntp->state & OFLOW_CTL) {
419 419 ntp->state &= ~OFLOW_CTL;
420 420 qenable(WR(q));
421 421 }
422 422 }
423 423 /* FALLTHROUGH */
424 424 default:
425 425 putnext(q, mp);
426 426 break;
427 427 }
428 428 return (0);
429 429 }
430 430
431 431
432 432 /*
433 433 * ptemwput - Module write queue put procedure.
434 434 *
435 435 * This is called from the module or stream head upstream.
436 436 *
437 437 * XXX: This routine is quite lazy about handling allocation failures,
438 438 * basically just giving up and reporting failure. It really ought to
439 439 * set up bufcalls and only fail when it's absolutely necessary.
440 440 */
441 441 static int
442 442 ptemwput(queue_t *q, mblk_t *mp)
443 443 {
444 444 struct ptem *ntp = (struct ptem *)q->q_ptr;
445 445 struct iocblk *iocp; /* outgoing ioctl structure */
446 446 struct copyresp *resp;
447 447 unsigned char type = mp->b_datap->db_type;
448 448
449 449 if (type >= QPCTL) {
450 450 switch (type) {
451 451
452 452 case M_IOCDATA:
453 453 resp = (struct copyresp *)mp->b_rptr;
454 454 if (resp->cp_rval) {
455 455 /*
456 456 * Just free message on failure.
457 457 */
458 458 freemsg(mp);
459 459 break;
460 460 }
461 461
462 462 /*
463 463 * Only need to copy data for the SET case.
464 464 */
465 465 switch (resp->cp_cmd) {
466 466
467 467 case TIOCSWINSZ:
468 468 ptioc(q, mp, WRSIDE);
469 469 break;
470 470
471 471 case JWINSIZE:
472 472 case TIOCGWINSZ:
473 473 mioc2ack(mp, NULL, 0, 0);
474 474 qreply(q, mp);
475 475 break;
476 476
477 477 default:
478 478 freemsg(mp);
479 479 }
480 480 break;
481 481
482 482 case M_FLUSH:
483 483 if (*mp->b_rptr & FLUSHW) {
484 484 if ((ntp->state & IS_PTSTTY) &&
485 485 (*mp->b_rptr & FLUSHBAND))
486 486 flushband(q, *(mp->b_rptr + 1),
487 487 FLUSHDATA);
488 488 else
489 489 flushq(q, FLUSHDATA);
490 490 }
491 491 putnext(q, mp);
492 492 break;
493 493
494 494 case M_READ:
495 495 freemsg(mp);
496 496 break;
497 497
498 498 case M_STOP:
499 499 /*
500 500 * Set the output flow control state.
501 501 */
502 502 ntp->state |= OFLOW_CTL;
503 503 putnext(q, mp);
504 504 break;
505 505
506 506 case M_START:
507 507 /*
508 508 * Relieve the output flow control state.
509 509 */
510 510 ntp->state &= ~OFLOW_CTL;
511 511 putnext(q, mp);
512 512 qenable(q);
513 513 break;
514 514 default:
515 515 putnext(q, mp);
516 516 break;
517 517 }
518 518 return (0);
519 519 }
520 520 /*
521 521 * If our queue is nonempty or flow control persists
522 522 * downstream or module in stopped state, queue this message.
523 523 */
524 524 if (q->q_first != NULL || !bcanputnext(q, mp->b_band)) {
525 525 /*
526 526 * Exception: ioctls, except for those defined to
527 527 * take effect after output has drained, should be
528 528 * processed immediately.
529 529 */
530 530 switch (type) {
531 531
532 532 case M_IOCTL:
533 533 iocp = (struct iocblk *)mp->b_rptr;
534 534 switch (iocp->ioc_cmd) {
535 535 /*
536 536 * Queue these.
537 537 */
538 538 case TCSETSW:
539 539 case TCSETSF:
540 540 case TCSETAW:
541 541 case TCSETAF:
542 542 case TCSBRK:
543 543 break;
544 544
545 545 /*
546 546 * Handle all others immediately.
547 547 */
548 548 default:
549 549 (void) ptemwmsg(q, mp);
550 550 return (0);
551 551 }
552 552 break;
553 553
554 554 case M_DELAY: /* tty delays not supported */
555 555 freemsg(mp);
556 556 return (0);
557 557
558 558 case M_DATA:
559 559 if ((mp->b_wptr - mp->b_rptr) < 0) {
560 560 /*
561 561 * Free all bad length messages.
562 562 */
563 563 freemsg(mp);
564 564 return (0);
565 565 } else if ((mp->b_wptr - mp->b_rptr) == 0) {
566 566 if (!(ntp->state & IS_PTSTTY)) {
567 567 freemsg(mp);
568 568 return (0);
569 569 }
570 570 }
571 571 }
572 572 (void) putq(q, mp);
573 573 return (0);
574 574 }
575 575 /*
576 576 * fast path into ptemwmsg to dispose of mp.
577 577 */
578 578 if (!ptemwmsg(q, mp))
579 579 (void) putq(q, mp);
580 580 return (0);
581 581 }
582 582
583 583 /*
584 584 * ptem write queue service procedure.
585 585 */
586 586 static int
587 587 ptemwsrv(queue_t *q)
588 588 {
589 589 mblk_t *mp;
590 590
591 591 while ((mp = getq(q)) != NULL) {
592 592 if (!bcanputnext(q, mp->b_band) || !ptemwmsg(q, mp)) {
593 593 (void) putbq(q, mp);
594 594 break;
595 595 }
596 596 }
597 597 return (0);
598 598 }
599 599
600 600
601 601 /*
602 602 * This routine is called from both ptemwput and ptemwsrv to do the
603 603 * actual work of dealing with mp. ptmewput will have already
604 604 * dealt with high priority messages.
605 605 *
606 606 * Return 1 if the message was processed completely and 0 if not.
607 607 */
608 608 static int
609 609 ptemwmsg(queue_t *q, mblk_t *mp)
610 610 {
611 611 struct ptem *ntp = (struct ptem *)q->q_ptr;
612 612 struct iocblk *iocp; /* outgoing ioctl structure */
613 613 struct termio *termiop;
614 614 struct termios *termiosp;
615 615 mblk_t *dack_ptr; /* disconnect message ACK block */
616 616 mblk_t *pckt_msgp; /* message sent to the PCKT module */
617 617 mblk_t *dp; /* ioctl reply data */
618 618 tcflag_t cflags;
↓ open down ↓ |
204 lines elided |
↑ open up ↑ |
619 619 int error;
620 620
621 621 switch (mp->b_datap->db_type) {
622 622
623 623 case M_IOCTL:
624 624 /*
625 625 * Note: for each "set" type operation a copy
626 626 * of the M_IOCTL message is made and passed
627 627 * downstream. Eventually the PCKT module, if
628 628 * it has been pushed, should pick up this message.
629 - * If the PCKT module has not been pushed the master
629 + * If the PCKT module has not been pushed the manager
630 630 * side stream head will free it.
631 631 */
632 632 iocp = (struct iocblk *)mp->b_rptr;
633 633 switch (iocp->ioc_cmd) {
634 634
635 635 case TCSETAF:
636 636 case TCSETSF:
637 637 /*
638 638 * Flush the read queue.
639 639 */
640 640 if (putnextctl1(q, M_FLUSH, FLUSHR) == 0) {
641 641 miocnak(q, mp, 0, EAGAIN);
642 642 break;
643 643 }
644 644 /* FALLTHROUGH */
645 645
646 646 case TCSETA:
647 647 case TCSETAW:
648 648 case TCSETS:
649 649 case TCSETSW:
650 650
651 651 switch (iocp->ioc_cmd) {
652 652 case TCSETAF:
653 653 case TCSETA:
654 654 case TCSETAW:
655 655 error = miocpullup(mp, sizeof (struct termio));
656 656 if (error != 0) {
657 657 miocnak(q, mp, 0, error);
658 658 goto out;
659 659 }
660 660 cflags = ((struct termio *)
661 661 mp->b_cont->b_rptr)->c_cflag;
662 662 ntp->cflags =
663 663 (ntp->cflags & 0xffff0000 | cflags);
664 664 break;
665 665
666 666 case TCSETSF:
667 667 case TCSETS:
668 668 case TCSETSW:
669 669 error = miocpullup(mp, sizeof (struct termios));
670 670 if (error != 0) {
671 671 miocnak(q, mp, 0, error);
672 672 goto out;
673 673 }
674 674 cflags = ((struct termios *)
675 675 mp->b_cont->b_rptr)->c_cflag;
676 676 ntp->cflags = cflags;
677 677 break;
678 678 }
679 679
680 680 if ((cflags & CBAUD) == B0) {
681 681 /*
682 682 * Hang-up: Send a zero length message.
683 683 */
684 684 dack_ptr = ntp->dack_ptr;
685 685
686 686 if (dack_ptr) {
687 687 ntp->dack_ptr = NULL;
688 688 /*
689 689 * Send a zero length message
690 690 * downstream.
691 691 */
692 692 putnext(q, dack_ptr);
693 693 }
694 694 } else {
695 695 /*
696 696 * Make a copy of this message and pass it on
697 697 * to the PCKT module.
698 698 */
699 699 if ((pckt_msgp = copymsg(mp)) == NULL) {
700 700 miocnak(q, mp, 0, EAGAIN);
701 701 break;
702 702 }
703 703 putnext(q, pckt_msgp);
704 704 }
705 705 /*
706 706 * Send ACK upstream.
707 707 */
708 708 mioc2ack(mp, NULL, 0, 0);
709 709 qreply(q, mp);
710 710 out:
711 711 break;
712 712
713 713 case TCGETA:
714 714 dp = allocb(sizeof (struct termio), BPRI_MED);
715 715 if (dp == NULL) {
716 716 miocnak(q, mp, 0, EAGAIN);
717 717 break;
718 718 }
719 719 termiop = (struct termio *)dp->b_rptr;
720 720 termiop->c_cflag = (ushort_t)ntp->cflags;
721 721 mioc2ack(mp, dp, sizeof (struct termio), 0);
722 722 qreply(q, mp);
723 723 break;
724 724
725 725 case TCGETS:
726 726 dp = allocb(sizeof (struct termios), BPRI_MED);
727 727 if (dp == NULL) {
728 728 miocnak(q, mp, 0, EAGAIN);
729 729 break;
730 730 }
731 731 termiosp = (struct termios *)dp->b_rptr;
732 732 termiosp->c_cflag = ntp->cflags;
733 733 mioc2ack(mp, dp, sizeof (struct termios), 0);
734 734 qreply(q, mp);
735 735 break;
736 736
737 737 case TCSBRK:
738 738 error = miocpullup(mp, sizeof (int));
739 739 if (error != 0) {
740 740 miocnak(q, mp, 0, error);
741 741 break;
742 742 }
743 743
744 744 /*
745 745 * Need a copy of this message to pass it on to
746 746 * the PCKT module.
747 747 */
748 748 if ((pckt_msgp = copymsg(mp)) == NULL) {
749 749 miocnak(q, mp, 0, EAGAIN);
750 750 break;
751 751 }
752 752 /*
753 753 * Send a copy of the M_IOCTL to the PCKT module.
754 754 */
755 755 putnext(q, pckt_msgp);
756 756
757 757 /*
758 758 * TCSBRK meaningful if data part of message is 0
759 759 * cf. termio(7).
760 760 */
761 761 if (!(*(int *)mp->b_cont->b_rptr))
762 762 (void) putnextctl(q, M_BREAK);
763 763 /*
764 764 * ACK the ioctl.
765 765 */
766 766 mioc2ack(mp, NULL, 0, 0);
767 767 qreply(q, mp);
768 768 break;
769 769
770 770 case JWINSIZE:
771 771 case TIOCGWINSZ:
772 772 case TIOCSWINSZ:
773 773 ptioc(q, mp, WRSIDE);
774 774 break;
775 775
776 776 case TIOCSTI:
777 777 /*
778 778 * Simulate typing of a character at the terminal. In
779 779 * all cases, we acknowledge the ioctl and pass a copy
780 780 * of it along for the PCKT module to encapsulate. If
781 781 * not in remote mode, we also process the ioctl
782 782 * itself, looping the character given as its argument
783 783 * back around to the read side.
784 784 */
785 785
786 786 /*
787 787 * Need a copy of this message to pass on to the PCKT
788 788 * module.
789 789 */
790 790 if ((pckt_msgp = copymsg(mp)) == NULL) {
791 791 miocnak(q, mp, 0, EAGAIN);
792 792 break;
793 793 }
794 794 if ((ntp->state & REMOTEMODE) == 0) {
795 795 mblk_t *bp;
796 796
797 797 error = miocpullup(mp, sizeof (char));
798 798 if (error != 0) {
799 799 freemsg(pckt_msgp);
800 800 miocnak(q, mp, 0, error);
801 801 break;
802 802 }
803 803
804 804 /*
805 805 * The permission checking has already been
806 806 * done at the stream head, since it has to be
807 807 * done in the context of the process doing
808 808 * the call.
809 809 */
810 810 if ((bp = allocb(1, BPRI_MED)) == NULL) {
811 811 freemsg(pckt_msgp);
812 812 miocnak(q, mp, 0, EAGAIN);
813 813 break;
814 814 }
815 815 /*
816 816 * XXX: Is EAGAIN really the right response to
817 817 * flow control blockage?
818 818 */
819 819 if (!bcanputnext(RD(q), mp->b_band)) {
820 820 freemsg(bp);
821 821 freemsg(pckt_msgp);
822 822 miocnak(q, mp, 0, EAGAIN);
823 823 break;
824 824 }
825 825 *bp->b_wptr++ = *mp->b_cont->b_rptr;
826 826 qreply(q, bp);
827 827 }
828 828
829 829 putnext(q, pckt_msgp);
830 830 mioc2ack(mp, NULL, 0, 0);
831 831 qreply(q, mp);
832 832 break;
833 833
834 834 case PTSSTTY:
835 835 if (ntp->state & IS_PTSTTY) {
↓ open down ↓ |
196 lines elided |
↑ open up ↑ |
836 836 miocnak(q, mp, 0, EEXIST);
837 837 } else {
838 838 ntp->state |= IS_PTSTTY;
839 839 mioc2ack(mp, NULL, 0, 0);
840 840 qreply(q, mp);
841 841 }
842 842 break;
843 843
844 844 default:
845 845 /*
846 - * End of the line. The slave driver doesn't see any
847 - * ioctls that we don't explicitly pass along to it.
846 + * End of the line. The subsidiary driver doesn't see
847 + * any ioctls that we don't explicitly pass along to
848 + * it.
848 849 */
849 850 miocnak(q, mp, 0, EINVAL);
850 851 break;
851 852 }
852 853 break;
853 854
854 855 case M_DELAY: /* tty delays not supported */
855 856 freemsg(mp);
856 857 break;
857 858
858 859 case M_DATA:
859 860 if ((mp->b_wptr - mp->b_rptr) < 0) {
860 861 /*
861 862 * Free all bad length messages.
862 863 */
863 864 freemsg(mp);
864 865 break;
865 866 } else if ((mp->b_wptr - mp->b_rptr) == 0) {
866 867 if (!(ntp->state & IS_PTSTTY)) {
867 868 freemsg(mp);
868 869 break;
869 870 }
870 871 }
871 872 if (ntp->state & OFLOW_CTL)
872 873 return (0);
873 874 /* FALLTHROUGH */
874 875
875 876 default:
876 877 putnext(q, mp);
877 878 break;
878 879
879 880 }
880 881
881 882 return (1);
882 883 }
883 884
884 885 /*
885 886 * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called.
886 887 */
887 888 static void
888 889 ptioc(queue_t *q, mblk_t *mp, int qside)
889 890 {
890 891 struct ptem *tp;
891 892 struct iocblk *iocp;
892 893 struct winsize *wb;
893 894 struct jwinsize *jwb;
894 895 mblk_t *tmp;
895 896 mblk_t *pckt_msgp; /* message sent to the PCKT module */
896 897 int error;
897 898
898 899 iocp = (struct iocblk *)mp->b_rptr;
899 900 tp = (struct ptem *)q->q_ptr;
900 901
901 902 switch (iocp->ioc_cmd) {
902 903
903 904 case JWINSIZE:
904 905 /*
905 906 * For compatibility: If all zeros, NAK the message for dumb
906 907 * terminals.
907 908 */
908 909 if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
909 910 (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
910 911 miocnak(q, mp, 0, EINVAL);
911 912 return;
912 913 }
913 914
914 915 tmp = allocb(sizeof (struct jwinsize), BPRI_MED);
915 916 if (tmp == NULL) {
916 917 miocnak(q, mp, 0, EAGAIN);
917 918 return;
918 919 }
919 920
920 921 if (iocp->ioc_count == TRANSPARENT)
921 922 mcopyout(mp, NULL, sizeof (struct jwinsize), NULL, tmp);
922 923 else
923 924 mioc2ack(mp, tmp, sizeof (struct jwinsize), 0);
924 925
925 926 jwb = (struct jwinsize *)mp->b_cont->b_rptr;
926 927 jwb->bytesx = tp->wsz.ws_col;
927 928 jwb->bytesy = tp->wsz.ws_row;
928 929 jwb->bitsx = tp->wsz.ws_xpixel;
929 930 jwb->bitsy = tp->wsz.ws_ypixel;
930 931
931 932 qreply(q, mp);
932 933 return;
933 934
934 935 case TIOCGWINSZ:
935 936 /*
936 937 * If all zeros NAK the message for dumb terminals.
937 938 */
938 939 if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
939 940 (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
940 941 miocnak(q, mp, 0, EINVAL);
941 942 return;
942 943 }
943 944
944 945 tmp = allocb(sizeof (struct winsize), BPRI_MED);
945 946 if (tmp == NULL) {
946 947 miocnak(q, mp, 0, EAGAIN);
947 948 return;
948 949 }
949 950
950 951 mioc2ack(mp, tmp, sizeof (struct winsize), 0);
951 952
952 953 wb = (struct winsize *)mp->b_cont->b_rptr;
953 954 wb->ws_row = tp->wsz.ws_row;
954 955 wb->ws_col = tp->wsz.ws_col;
955 956 wb->ws_xpixel = tp->wsz.ws_xpixel;
956 957 wb->ws_ypixel = tp->wsz.ws_ypixel;
957 958
958 959 qreply(q, mp);
959 960 return;
960 961
961 962 case TIOCSWINSZ:
962 963 error = miocpullup(mp, sizeof (struct winsize));
963 964 if (error != 0) {
964 965 miocnak(q, mp, 0, error);
965 966 return;
966 967 }
967 968
968 969 wb = (struct winsize *)mp->b_cont->b_rptr;
969 970 /*
970 971 * Send a SIGWINCH signal if the row/col information has
971 972 * changed.
972 973 */
973 974 if ((tp->wsz.ws_row != wb->ws_row) ||
974 975 (tp->wsz.ws_col != wb->ws_col) ||
975 976 (tp->wsz.ws_xpixel != wb->ws_xpixel) ||
↓ open down ↓ |
118 lines elided |
↑ open up ↑ |
976 977 (tp->wsz.ws_ypixel != wb->ws_xpixel)) {
977 978 /*
978 979 * SIGWINCH is always sent upstream.
979 980 */
980 981 if (qside == WRSIDE)
981 982 (void) putnextctl1(RD(q), M_SIG, SIGWINCH);
982 983 else if (qside == RDSIDE)
983 984 (void) putnextctl1(q, M_SIG, SIGWINCH);
984 985 /*
985 986 * Message may have come in as an M_IOCDATA; pass it
986 - * to the master side as an M_IOCTL.
987 + * to the manager side as an M_IOCTL.
987 988 */
988 989 mp->b_datap->db_type = M_IOCTL;
989 990 if (qside == WRSIDE) {
990 991 /*
991 992 * Need a copy of this message to pass on to
992 993 * the PCKT module, only if the M_IOCTL
993 - * orginated from the slave side.
994 + * orginated from the subsidiary side.
994 995 */
995 996 if ((pckt_msgp = copymsg(mp)) == NULL) {
996 997 miocnak(q, mp, 0, EAGAIN);
997 998 return;
998 999 }
999 1000 putnext(q, pckt_msgp);
1000 1001 }
1001 1002 tp->wsz.ws_row = wb->ws_row;
1002 1003 tp->wsz.ws_col = wb->ws_col;
1003 1004 tp->wsz.ws_xpixel = wb->ws_xpixel;
1004 1005 tp->wsz.ws_ypixel = wb->ws_ypixel;
1005 1006 }
1006 1007
1007 1008 mioc2ack(mp, NULL, 0, 0);
1008 1009 qreply(q, mp);
1009 1010 return;
1010 1011
1011 1012 case TIOCSIGNAL: {
1012 1013 /*
1013 - * This ioctl can emanate from the master side in remote
1014 + * This ioctl can emanate from the manager side in remote
1014 1015 * mode only.
1015 1016 */
1016 1017 int sig;
1017 1018
1018 1019 if (DB_TYPE(mp) == M_IOCTL && iocp->ioc_count != TRANSPARENT) {
1019 1020 error = miocpullup(mp, sizeof (int));
1020 1021 if (error != 0) {
1021 1022 miocnak(q, mp, 0, error);
1022 1023 return;
1023 1024 }
1024 1025 }
1025 1026
1026 1027 if (DB_TYPE(mp) == M_IOCDATA || iocp->ioc_count != TRANSPARENT)
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
1027 1028 sig = *(int *)mp->b_cont->b_rptr;
1028 1029 else
1029 1030 sig = (int)*(intptr_t *)mp->b_cont->b_rptr;
1030 1031
1031 1032 if (sig < 1 || sig >= NSIG) {
1032 1033 miocnak(q, mp, 0, EINVAL);
1033 1034 return;
1034 1035 }
1035 1036
1036 1037 /*
1037 - * Send an M_PCSIG message up the slave's read side and
1038 - * respond back to the master with an ACK or NAK as
1038 + * Send an M_PCSIG message up the subsidiary's read side and
1039 + * respond back to the manager with an ACK or NAK as
1039 1040 * appropriate.
1040 1041 */
1041 1042 if (putnextctl1(q, M_PCSIG, sig) == 0) {
1042 1043 miocnak(q, mp, 0, EAGAIN);
1043 1044 return;
1044 1045 }
1045 1046
1046 1047 mioc2ack(mp, NULL, 0, 0);
1047 1048 qreply(q, mp);
1048 1049 return;
1049 1050 }
1050 1051
1051 1052 case TIOCREMOTE: {
1052 1053 int onoff;
1053 1054 mblk_t *mctlp;
1054 1055
1055 1056 if (DB_TYPE(mp) == M_IOCTL) {
1056 1057 error = miocpullup(mp, sizeof (int));
1057 1058 if (error != 0) {
1058 1059 miocnak(q, mp, 0, error);
1059 1060 return;
1060 1061 }
1061 1062 }
1062 1063
1063 1064 onoff = *(int *)mp->b_cont->b_rptr;
1064 1065
1065 1066 /*
1066 1067 * Send M_CTL up using the iocblk format.
1067 1068 */
1068 1069 mctlp = mkiocb(onoff ? MC_NO_CANON : MC_DO_CANON);
1069 1070 if (mctlp == NULL) {
1070 1071 miocnak(q, mp, 0, EAGAIN);
1071 1072 return;
1072 1073 }
1073 1074 mctlp->b_datap->db_type = M_CTL;
1074 1075 putnext(q, mctlp);
1075 1076
1076 1077 /*
1077 1078 * ACK the ioctl.
1078 1079 */
1079 1080 mioc2ack(mp, NULL, 0, 0);
1080 1081 qreply(q, mp);
1081 1082
1082 1083 /*
1083 1084 * Record state change.
1084 1085 */
1085 1086 if (onoff)
1086 1087 tp->state |= REMOTEMODE;
1087 1088 else
1088 1089 tp->state &= ~REMOTEMODE;
1089 1090 return;
1090 1091 }
1091 1092
1092 1093 default:
1093 1094 putnext(q, mp);
1094 1095 return;
1095 1096 }
1096 1097 }
↓ open down ↓ |
48 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX