|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.6 ! root 5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /*
14:
15: * read/write routines for TTY devices
16:
17: */
18:
19:
20:
21: #include "mint.h"
22:
23:
24:
1.1.1.6 ! root 25: /* emulate mdm0 ioctls too */
! 26:
! 27: #define MDM0_IOCTLS
! 28:
! 29: #ifdef MDM0_IOCTLS
! 30:
! 31: #define TIOCGHUPCL (('T'<< 8) | 98)
! 32:
! 33: #define TIOCSHUPCL (('T'<< 8) | 99)
! 34:
! 35: #define TIOCGSOFTCAR (('T'<< 8) | 100)
! 36:
! 37: #define TIOCSSOFTCAR (('T'<< 8) | 101)
! 38:
! 39: #endif
! 40:
! 41:
! 42:
! 43: static void _erase P_((FILEPTR *, int, int));
1.1 root 44:
45: static int escseq P_((struct tty *, int));
46:
47:
48:
49: /* setting a special character to this value disables it */
50:
51: #define UNDEF 0
52:
53:
54:
1.1.1.6 ! root 55: #define HAS_WRITEB(f) (((f)->fc.fs != &bios_filesys || \
! 56:
! 57: (((struct bios_file *)(f)->fc.index)->drvsize > \
! 58:
! 59: offsetof (DEVDRV, writeb))) && \
! 60:
! 61: (f)->dev->writeb)
! 62:
! 63: extern FILESYS bios_filesys;
! 64:
1.1 root 65:
66:
67: /* default terminal characteristics */
68:
69:
70:
71: struct tty default_tty = {
72:
73: 0, /* process group */
74:
75: 0, /* state */
76:
77: 0, /* use_cnt */
78:
1.1.1.6 ! root 79: 0, /* aux_cnt */
1.1 root 80:
81: {
82:
83: 13, 13, /* input speed == output speed == 9600 baud */
84:
85: CTRL('H'), /* erase */
86:
87: CTRL('U'), /* kill */
88:
1.1.1.6 ! root 89: T_ECHO|T_CRMOD|T_TOSTOP|T_XKEY|T_ECHOCTL, /* flags */
1.1 root 90:
91: },
92:
93: {
94:
95: CTRL('C'), /* interrupt */
96:
97: CTRL('\\'), /* quit */
98:
99: CTRL('Q'), /* start */
100:
101: CTRL('S'), /* stop */
102:
103: CTRL('D'), /* EOF */
104:
105: '\r' /* alternate end of line */
106:
107: },
108:
109: {
110:
111: CTRL('Z'), /* suspend */
112:
113: CTRL('Y'), /* suspend after read */
114:
115: CTRL('R'), /* reprint */
116:
1.1.1.6 ! root 117: CTRL('O'), /* flush output */
1.1 root 118:
1.1.1.2 root 119: CTRL('W'), /* erase word */
1.1 root 120:
1.1.1.2 root 121: CTRL('V') /* quote next char */
1.1 root 122:
123: },
124:
125: {
126:
127: 0, 0, 0, 0 /* window size is unknown */
128:
129: },
130:
131: 0, /* no process is selecting us for reading */
132:
133: 0, /* or for writing */
134:
1.1.1.6 ! root 135: 0, /* use default XKEY map */
! 136:
! 137: 0, /* not currently hanging up */
! 138:
! 139: 1, 0 /* RAW reads need 1 char, no timeout */
1.1 root 140:
141: };
142:
143:
144:
145: #define _put(f, c) (tty_putchar((f), (c), RAW))
146:
147:
148:
149: static void
150:
1.1.1.6 ! root 151: _erase(f, c, mode)
1.1 root 152:
153: FILEPTR *f;
154:
1.1.1.6 ! root 155: int c, mode;
1.1 root 156:
157: {
158:
159: _put(f, '\010');
160:
161: _put(f, ' ');
162:
163: _put(f, '\010');
164:
165: /* watch out for control characters -- they're printed as e.g. "^C" */
166:
1.1.1.2 root 167: /* BUG: \t is messed up. We really need to keep track of the output
168:
169: * column
170:
171: */
172:
1.1.1.6 ! root 173: if ((mode & T_ECHOCTL) && c >= 0 && c < ' ' && c != '\t') {
1.1 root 174:
175: _put(f, '\010'); _put(f, ' '); _put(f, '\010');
176:
177: }
178:
179: }
180:
181:
182:
183: #define put(f, c) { if (mode & T_ECHO) _put(f, c); }
184:
1.1.1.6 ! root 185: #define erase(f, c) { if (mode & T_ECHO) _erase(f, c, mode); }
1.1 root 186:
187:
188:
189: long
190:
191: tty_read(f, buf, nbytes)
192:
193: FILEPTR *f;
194:
195: void *buf;
196:
197: long nbytes;
198:
199: {
200:
201: long r;
202:
203: long bytes_read = 0;
204:
205: unsigned char ch, *ptr;
206:
207: int rdmode, mode;
208:
209: struct tty *tty;
210:
211:
212:
213: tty = (struct tty *)f->devinfo;
214:
215: assert(tty != 0);
216:
217:
218:
219: if (f->flags & O_HEAD) { /* pty server side? */
220:
221: rdmode = RAW; /* yes -- always raw mode */
222:
223: mode = T_RAW;
224:
225: }
226:
227: else if (curproc->domain == DOM_MINT) { /* MiNT domain process? */
228:
229: mode = tty->sg.sg_flags;
230:
231: rdmode = COOKED|NOECHO;
232:
233: if ( mode & (T_RAW | T_CBREAK) ) {
234:
235: rdmode = (mode & T_RAW) ? RAW : COOKED;
236:
237: }
238:
239: if (mode & T_XKEY)
240:
241: rdmode |= ESCSEQ;
242:
243: }
244:
245: else {
246:
247: rdmode = COOKED|NOECHO;
248:
1.1.1.6 ! root 249: mode = T_TOS | T_ECHO | T_ECHOCTL;
! 250:
! 251: }
! 252:
! 253:
! 254:
! 255: if (nbytes == 0) return bytes_read;
! 256:
! 257:
! 258:
! 259: /* if RAW or CBREAK do VTIME: select for input, return on timeout */
! 260:
! 261: if (tty->vtime && (mode & (T_RAW|T_CBREAK)) &&
! 262:
! 263: !(f->flags & (O_NDELAY|O_HEAD)) &&
! 264:
! 265: (!(tty->state & TS_ESC) || !(rdmode & ESCSEQ))) {
! 266:
! 267: long r, bytes = 0;
! 268:
! 269:
! 270:
! 271: if ((r = (*f->dev->select)(f, (long)curproc, O_RDONLY)) != 1) {
! 272:
! 273: TIMEOUT *t;
! 274:
! 275:
! 276:
! 277: curproc->wait_cond = (long)wakeselect; /* flag */
! 278:
! 279: t = addtimeout((long)tty->vtime, (void (*)P_((PROC *)))wakeselect);
! 280:
! 281: if (!t) {
! 282:
! 283: (*f->dev->unselect)(f, (long)curproc, O_RDONLY);
! 284:
! 285: return ENSMEM;
! 286:
! 287: }
! 288:
! 289: while (curproc->wait_cond == (long)wakeselect) {
! 290:
! 291: TRACE(("sleeping in tty_read (VTIME)"));
! 292:
! 293: if (sleep(SELECT_Q|0x100, (long)wakeselect))
! 294:
! 295: break;
! 296:
! 297: }
! 298:
! 299: canceltimeout(t);
! 300:
! 301: }
! 302:
! 303: (void)(*f->dev->ioctl)(f, FIONREAD, &bytes);
! 304:
! 305: if (!r) {
! 306:
! 307: extern short select_coll; /* in dosfile.c */
! 308:
! 309: (*f->dev->unselect)(f, (long)curproc, O_RDONLY);
! 310:
! 311: wake(SELECT_Q, (long)&select_coll);
! 312:
! 313: }
! 314:
! 315: if (!bytes)
! 316:
! 317: return bytes_read;
1.1 root 318:
319: }
320:
1.1.1.6 ! root 321: #if 1
! 322:
! 323: /* see if we can do fast RAW byte IO thru the device driver... */
! 324:
! 325: if (rdmode == RAW &&
! 326:
! 327: (!(tty->state & TS_ESC) || !(rdmode & ESCSEQ) ||
! 328:
! 329: (f->flags & O_HEAD)) &&
! 330:
! 331: (f->fc.fs != &bios_filesys ||
! 332:
! 333: (nbytes > 1 &&
! 334:
! 335: ((struct bios_file *)f->fc.index)->drvsize >
! 336:
! 337: offsetof (DEVDRV, readb))) &&
! 338:
! 339: f->dev->readb &&
! 340:
! 341: ((f->flags & O_HEAD) || ((tty->state &= ~TS_COOKED), !tty->pgrp) ||
! 342:
! 343: tty->pgrp == curproc->pgrp ||
! 344:
! 345: f->fc.dev != curproc->control->fc.dev ||
! 346:
! 347: f->fc.index != curproc->control->fc.index) &&
! 348:
! 349: !(tty->state & TS_BLIND) &&
! 350:
! 351: (r = (*f->dev->readb)(f, buf, nbytes)) != EUNDEV)
! 352:
! 353: return r;
! 354:
! 355: #endif
! 356:
1.1 root 357:
358:
359: ptr = buf;
360:
361:
362:
363: while (bytes_read < nbytes) {
364:
365: r = tty_getchar(f, rdmode);
366:
367: if (r < 0) {
368:
1.1.1.2 root 369: tty_error:
370:
371: DEBUG(("tty_read: tty_getchar returned %ld", r));
1.1 root 372:
373: return (bytes_read) ? bytes_read : r;
374:
375: }
376:
377: else if (r == MiNTEOF)
378:
379: return bytes_read;
380:
381: ch = r & 0xff;
382:
383:
384:
1.1.1.6 ! root 385: if ( (rdmode & COOKED) && (mode & T_CRMOD) && (ch == '\r') )
1.1 root 386:
387: ch = '\n';
388:
389:
390:
391: /* 1 character reads in TOS mode are always raw */
392:
393: if (nbytes == 1 && (mode & T_TOS)) {
394:
395: put(f, ch);
396:
397: *ptr = ch;
398:
399: return 1;
400:
401: }
402:
403:
404:
405: /* T_CBREAK mode doesn't do erase or kill processing */
406:
407: /* also note that setting a special character to UNDEF disables it */
408:
409:
410:
411: if (rdmode & COOKED && !(mode & T_CBREAK) && ch != UNDEF) {
412:
413: if ((char)ch == tty->sg.sg_erase) { /* backspace */
414:
415: if (bytes_read > 0) {
416:
417: --ptr;
418:
419: erase(f, *ptr);
420:
421: bytes_read--;
422:
423: }
424:
425: continue;
426:
427: }
428:
1.1.1.2 root 429: else if ((mode & T_TOS) && ch == CTRL('X')) {
1.1 root 430:
431: while (bytes_read > 0) {
432:
433: --ptr;
434:
435: erase(f, *ptr);
436:
437: bytes_read--;
438:
439: }
440:
441: continue;
442:
443: }
444:
445: else if ((char)ch ==tty->ltc.t_rprntc ||
446:
447: (char)ch == tty->sg.sg_kill) {
448:
449: if (mode & T_TOS)
450:
451: put(f, '#');
452:
453: put(f, '\r');
454:
455: put(f, '\n');
456:
457: ptr = buf;
458:
459: if ((char)ch == tty->sg.sg_kill) {
460:
461: bytes_read = 0;
462:
463: }
464:
465: else {
466:
467: for (r = 0; r < bytes_read; r++, ptr++)
468:
469: put(f, *ptr);
470:
471: }
472:
473: continue;
474:
475: }
476:
1.1.1.2 root 477: else if ((char)ch == tty->ltc.t_werasc) {
478:
479: while (bytes_read > 0 &&
480:
481: !(ptr[-1] == ' ' || ptr[-1] == '\t')) {
482:
483: ptr--;
484:
485: erase(f, *ptr);
486:
487: bytes_read--;
488:
489: }
490:
491: continue;
492:
493: }
494:
495: else if ((char)ch == tty->ltc.t_lnextc) {
496:
1.1.1.6 ! root 497: if (mode & T_ECHOCTL) {
! 498:
! 499: put(f, '^');
! 500:
! 501: put(f, '\b');
1.1.1.2 root 502:
1.1.1.6 ! root 503: }
1.1.1.2 root 504:
505: r = tty_getchar(f, RAW);
506:
1.1.1.6 ! root 507: if (rdmode & COOKED)
! 508:
! 509: tty->state |= TS_COOKED;
! 510:
! 511: else
! 512:
! 513: tty->state &= ~TS_COOKED;
! 514:
! 515:
! 516:
1.1.1.2 root 517: if (r < 0)
518:
519: goto tty_error;
520:
521: else if (r == MiNTEOF)
522:
523: return bytes_read;
524:
525: ch = r & 0xff;
526:
527: goto stuff_it;
528:
529: }
530:
1.1 root 531: else if ((char)ch == tty->tc.t_eofc && !(mode & T_TOS))
532:
533: return bytes_read;
534:
535: }
536:
537:
538:
539: /* both T_CBREAK and T_COOKED modes have to do signals, though */
540:
541: if ((rdmode & COOKED) && ch != UNDEF) {
542:
543: if ((char)ch == tty->tc.t_intrc
544:
545: || (char)ch == tty->tc.t_quitc
546:
547: || (char)ch == tty->ltc.t_dsuspc
548:
549: || (char)ch == tty->ltc.t_suspc
550:
551: ) {
552:
553: /* the device driver raised the appropriate signal; if we get here, the
554:
555: signal was caught by the user (or ignored). flush buffers and continue
556:
557: */
558:
559: if (!(tty->sg.sg_flags & T_NOFLSH)) {
560:
1.1.1.2 root 561: DEBUG(("tty_read: flushing input"));
1.1 root 562:
563: bytes_read = 0;
564:
565: ptr = buf;
566:
567: }
568:
569: continue;
570:
571: }
572:
1.1.1.6 ! root 573: else if ((char)ch == tty->ltc.t_flushc) {
! 574:
! 575: continue;
! 576:
! 577: }
! 578:
1.1 root 579: else if (ch == '\n' || (char)ch == tty->tc.t_brkc) {
580:
581: put(f, '\r');
582:
583: if (!(mode & T_TOS)) {
584:
1.1.1.2 root 585: *ptr = ch;
1.1 root 586:
587: put(f, '\n');
588:
589: bytes_read++;
590:
1.1.1.6 ! root 591: if (rdmode & COOKED)
! 592:
! 593: tty->state |= TS_COOKED;
! 594:
! 595: else
! 596:
! 597: tty->state &= ~TS_COOKED;
! 598:
1.1 root 599: }
600:
601: return bytes_read;
602:
603: }
604:
605:
606:
607: }
608:
609:
610:
611: /* do the following for both RAW and COOKED mode */
612:
1.1.1.2 root 613: stuff_it:
614:
1.1 root 615: *ptr++ = ch;
616:
1.1.1.6 ! root 617: if ((mode & T_ECHOCTL) &&
! 618:
! 619: ch < ' ' && ch != '\t') { /* ch is unsigned */
1.1 root 620:
621: put(f, '^'); put(f, ch+'@');
622:
623: }
624:
625: else
626:
627: put(f, ch);
628:
629: bytes_read++;
630:
631:
632:
633: /* for RAW mode, if there are no more characters then break */
634:
635: if ( (mode & (T_RAW|T_CBREAK)) &&
636:
637: !((rdmode & ESCSEQ) && (tty->state & TS_ESC))) {
638:
639: r = 1;
640:
641: (void)(*f->dev->ioctl)(f, FIONREAD, &r);
642:
643: if (r <= 0) break;
644:
645: }
646:
647: }
648:
1.1.1.6 ! root 649: if (rdmode & COOKED)
! 650:
! 651: tty->state |= TS_COOKED;
! 652:
! 653: else
1.1 root 654:
1.1.1.6 ! root 655: tty->state &= ~TS_COOKED;
1.1 root 656:
657: return bytes_read;
658:
659: }
660:
661:
662:
1.1.1.6 ! root 663: /* job control checks */
! 664:
! 665: /* AKP: added T_TOSTOP; don't stop BG output if T_TOSTOP is clear */
! 666:
! 667: /*
! 668:
! 669: entropy: only do the job control if SIGTTOU is neither blocked nor ignored,
! 670:
! 671: and only for the controlling tty (IEEE 1003.1-1990 7.1.1.4 79-87).
! 672:
! 673: BUG: if the process group is orphaned and SIGTTOU *is not* blocked
! 674:
! 675: or ignored, we should return EIO instead of signalling.
! 676:
! 677: */
! 678:
! 679: INLINE void
! 680:
! 681: tty_checkttou (f, tty)
! 682:
! 683: FILEPTR *f;
! 684:
! 685: struct tty *tty;
! 686:
! 687: {
! 688:
! 689: if (tty->pgrp && tty->pgrp != curproc->pgrp &&
! 690:
! 691: (tty->sg.sg_flags & T_TOSTOP) &&
! 692:
! 693: (curproc->sighandle[SIGTTOU] != SIG_IGN) &&
! 694:
! 695: ((curproc->sigmask & (1L << SIGTTOU)) == 0L) &&
! 696:
! 697: (f->fc.dev == curproc->control->fc.dev) &&
! 698:
! 699: (f->fc.index == curproc->control->fc.index)) {
! 700:
! 701: TRACE(("job control: tty pgrp is %d proc pgrp is %d",
! 702:
! 703: tty->pgrp, curproc->pgrp));
! 704:
! 705: killgroup(curproc->pgrp, SIGTTOU, 1);
! 706:
! 707: check_sigs();
! 708:
! 709: }
! 710:
! 711: }
! 712:
! 713:
! 714:
1.1 root 715: long
716:
717: tty_write(f, buf, nbytes)
718:
719: FILEPTR *f;
720:
721: const void *buf;
722:
723: long nbytes;
724:
725: {
726:
727: unsigned const char *ptr;
728:
729: long c;
730:
731: long bytes_written;
732:
733: int mode, rwmode;
734:
735: struct tty *tty;
736:
737: int use_putchar = 0;
738:
739: static long cr_char = '\r';
740:
741: #define LBUFSIZ 128
742:
743: long lbuf[LBUFSIZ];
744:
745:
746:
747: tty = (struct tty *)f->devinfo;
748:
749: assert(tty != 0);
750:
751:
752:
1.1.1.6 ! root 753: ptr = (unsigned const char *)buf;
1.1 root 754:
755: if (f->flags & O_HEAD) {
756:
757: use_putchar = 1;
758:
759: mode = T_RAW;
760:
761: }
762:
763: else if (curproc->domain == DOM_TOS)
764:
765: /* for TOS programs, 1 byte writes are always in raw mode */
766:
767: mode = (nbytes == 1) ? T_RAW : T_TOS;
768:
769: else
770:
771: mode = tty->sg.sg_flags;
772:
773:
774:
775: rwmode = (mode & T_RAW) ? RAW : COOKED;
776:
777:
778:
779: bytes_written = 0;
780:
781:
782:
783: /*
784:
785: * "mode" can now be reduced to just T_CRMODE or not
786:
787: */
788:
789: if ((curproc->domain == DOM_MINT) && (mode & T_CRMOD) &&
790:
791: !(mode & T_RAW))
792:
793: mode = T_CRMOD;
794:
795: else
796:
797: mode = 0;
798:
799:
800:
1.1.1.6 ! root 801: if (nbytes == 0) return bytes_written;
! 802:
! 803: #if 1
! 804:
! 805: /* see if we can do fast RAW byte IO thru the device driver... */
! 806:
! 807: if (!use_putchar && HAS_WRITEB(f)) {
! 808:
! 809:
! 810:
! 811: tty_checkttou (f, tty);
! 812:
! 813: if (rwmode & COOKED)
! 814:
! 815: tty->state |= TS_COOKED;
! 816:
! 817: else
! 818:
! 819: tty->state &= ~TS_COOKED;
! 820:
! 821: if (tty->state & TS_BLIND)
! 822:
! 823: return bytes_written;
! 824:
! 825: if (mode) { /* i.e. T_CRMODE */
! 826:
! 827: if ((*f->dev->writeb)(f, buf, 0L) != EUNDEV) {
! 828:
! 829: /* write in big chunks if possible; lines if CRMODE
! 830:
! 831: * (if we get here flow control is taken care of by the device)
! 832:
! 833: */
! 834:
! 835: long bytes_to_write = 0;
! 836:
! 837: unsigned const char *s = ptr;
! 838:
! 839:
! 840:
! 841: while (nbytes-- > 0) {
! 842:
! 843: if (*ptr++ == '\n') {
! 844:
! 845: if (0 != (bytes_to_write = ptr-s-1)) {
! 846:
! 847: c = (*f->dev->writeb)(f, (const char *)s,
! 848:
! 849: bytes_to_write);
! 850:
! 851: bytes_written += c;
! 852:
! 853: if (c != bytes_to_write) {
! 854:
! 855: if (c < 0)
! 856:
! 857: bytes_written = c;
! 858:
! 859: return bytes_written;
! 860:
! 861: }
! 862:
! 863: }
! 864:
! 865: s = ptr-1;
! 866:
! 867: c = (*f->dev->writeb)(f, "\r", 1);
! 868:
! 869: if (c != 1) {
! 870:
! 871: if (c < 0)
! 872:
! 873: bytes_written = c;
! 874:
! 875: return bytes_written;
! 876:
! 877: }
! 878:
! 879: }
! 880:
! 881: }
! 882:
! 883: if (0 != (bytes_to_write = ptr-s)) {
! 884:
! 885: c = (*f->dev->writeb)(f, (const char *)s, bytes_to_write);
! 886:
! 887: bytes_written += c;
! 888:
! 889: if (c < 0)
! 890:
! 891: bytes_written = c;
! 892:
! 893: }
! 894:
! 895: return bytes_written;
! 896:
! 897: }
! 898:
! 899: } else if ((c = (*f->dev->writeb)(f, buf, nbytes)) != EUNDEV)
! 900:
! 901: return c;
! 902:
! 903: }
! 904:
! 905: #endif
! 906:
! 907:
! 908:
1.1 root 909: /*
910:
911: * we always write at least 1 byte with tty_putchar, since that takes
912:
913: * care of job control and terminal states. After that, we may be able
914:
915: * to use (*f->dev->write) directly.
916:
917: */
918:
919:
920:
921: c = *ptr++;
922:
923:
924:
925: if (c == '\n' && mode) { /* remember, "mode" now means CRMOD */
926:
927: tty_putchar(f, cr_char, rwmode);
928:
929: }
930:
931: tty_putchar(f, c, rwmode);
932:
933: nbytes--;
934:
935: bytes_written++;
936:
937:
938:
939: if (use_putchar) {
940:
941: while (nbytes-- > 0) {
942:
943: c = *ptr++;
944:
945: if (c == '\n' && mode)
946:
947: tty_putchar(f, cr_char, rwmode);
948:
949: tty_putchar(f, c, rwmode);
950:
951: bytes_written++;
952:
953: }
954:
955: } else {
956:
957: /* write in big chunks if possible; but never more than 1 line
958:
959: * (so that ^S/^Q can happen reasonably quickly for the user)
960:
961: */
962:
963: long bytes_to_write = 0;
964:
965: long *s = lbuf;
966:
967:
968:
969: while (nbytes-- > 0) {
970:
971: c = *ptr++;
972:
973: if (c == '\n') {
974:
975: if (bytes_to_write) {
976:
977: (*f->dev->write)(f, (char *)lbuf,
978:
979: bytes_to_write);
980:
981: bytes_to_write = 0;
982:
983: s = lbuf;
984:
985: }
986:
987: if (mode) /* i.e. T_CRMODE */
988:
989: tty_putchar(f, cr_char, rwmode);
990:
991: tty_putchar(f, (long)c, rwmode);
992:
993: bytes_written++;
994:
995: } else {
996:
997: *s++ = c;
998:
999: bytes_written++;
1000:
1001: bytes_to_write += 4;
1002:
1003: if (bytes_to_write >= LBUFSIZ*4) {
1004:
1005: (*f->dev->write)(f, (char *)lbuf,
1006:
1007: bytes_to_write);
1008:
1009: bytes_to_write = 0;
1010:
1011: s = lbuf;
1012:
1013: }
1014:
1015: }
1016:
1017: }
1018:
1019: if (bytes_to_write) {
1020:
1021: (*f->dev->write)(f, (char *)lbuf, bytes_to_write);
1022:
1023: }
1024:
1025: }
1026:
1027:
1028:
1029: return bytes_written;
1030:
1031: }
1032:
1033:
1034:
1035: /* some notable scan codes */
1036:
1037: #define K_INSERT 0x52
1038:
1039: #define K_HOME 0x47
1040:
1041: #define K_UNDO 0x61
1042:
1043: #define K_HELP 0x62
1044:
1045: #define CURS_UP 0x48
1046:
1047: #define CURS_DN 0x50
1048:
1049: #define CURS_RT 0x4d
1050:
1051: #define CURS_LF 0x4b
1052:
1053: #define F_1 0x3b
1054:
1055: #define F_10 0x44
1056:
1057: #define F_11 0x54
1058:
1059: #define F_20 0x5d
1060:
1061: #define ALT_1 0x78
1062:
1063: #define ALT_0 0x81
1064:
1065:
1066:
1067: /* Default function key table:
1068:
1069: * entries: 0-9 are F1-F10
1070:
1071: * 10-19 are F11-F20
1072:
1073: * 20-23 are cursor up, down, right, and left
1074:
1075: * 24-27 are help, undo, insert, and home
1076:
1077: * 28-31 are shift+cursor up, down, right, and left
1078:
1079: */
1080:
1081:
1082:
1083: static char vt52xkey[256] = {
1084:
1085: '\033', 'P', 0, 0, 0, 0, 0, 0,
1086:
1087: '\033', 'Q', 0, 0, 0, 0, 0, 0,
1088:
1089: '\033', 'R', 0, 0, 0, 0, 0, 0,
1090:
1091: '\033', 'S', 0, 0, 0, 0, 0, 0,
1092:
1093: '\033', 'T', 0, 0, 0, 0, 0, 0,
1094:
1095: '\033', 'U', 0, 0, 0, 0, 0, 0,
1096:
1097: '\033', 'V', 0, 0, 0, 0, 0, 0,
1098:
1099: '\033', 'W', 0, 0, 0, 0, 0, 0,
1100:
1101: '\033', 'X', 0, 0, 0, 0, 0, 0,
1102:
1103: '\033', 'Y', 0, 0, 0, 0, 0, 0,
1104:
1105: '\033', 'p', 0, 0, 0, 0, 0, 0,
1106:
1107: '\033', 'q', 0, 0, 0, 0, 0, 0,
1108:
1109: '\033', 'r', 0, 0, 0, 0, 0, 0,
1110:
1111: '\033', 's', 0, 0, 0, 0, 0, 0,
1112:
1113: '\033', 't', 0, 0, 0, 0, 0, 0,
1114:
1115: '\033', 'u', 0, 0, 0, 0, 0, 0,
1116:
1117: '\033', 'v', 0, 0, 0, 0, 0, 0,
1118:
1119: '\033', 'w', 0, 0, 0, 0, 0, 0,
1120:
1121: '\033', 'x', 0, 0, 0, 0, 0, 0,
1122:
1123: '\033', 'y', 0, 0, 0, 0, 0, 0,
1124:
1125: '\033', 'A', 0, 0, 0, 0, 0, 0,
1126:
1127: '\033', 'B', 0, 0, 0, 0, 0, 0,
1128:
1129: '\033', 'C', 0, 0, 0, 0, 0, 0,
1130:
1131: '\033', 'D', 0, 0, 0, 0, 0, 0,
1132:
1133: '\033', 'H', 0, 0, 0, 0, 0, 0,
1134:
1135: '\033', 'K', 0, 0, 0, 0, 0, 0,
1136:
1137: '\033', 'I', 0, 0, 0, 0, 0, 0,
1138:
1139: '\033', 'E', 0, 0, 0, 0, 0, 0,
1140:
1141: '\033', 'a', 0, 0, 0, 0, 0, 0,
1142:
1143: '\033', 'b', 0, 0, 0, 0, 0, 0,
1144:
1145: '\033', 'c', 0, 0, 0, 0, 0, 0,
1146:
1147: '\033', 'd', 0, 0, 0, 0, 0, 0,
1148:
1149: };
1150:
1151:
1152:
1153: static char unxbaud P_((long));
1154:
1155:
1156:
1157: /* convert a number describing the baud rate into a Unix
1158:
1159: * style baud rate number. Returns the Unix baud rate,
1160:
1161: * or 16 (EXTA) if the rate is unknown
1162:
1163: */
1164:
1165:
1166:
1167: #define EXTA 16
1168:
1169:
1170:
1171: static long ubaud[EXTA] = {
1172:
1173: 0L, 50L, 75L, 110L, 134L, 150L, 200L, 300L,
1174:
1175: 600L, 1200L, 1800L, 2400L, 4800L, 9600L, 19200L, 38400L
1176:
1177: };
1178:
1179:
1180:
1181: static char
1182:
1183: unxbaud(baud)
1184:
1185: long baud;
1186:
1187: {
1188:
1189: int i;
1190:
1191: for (i = 1; i < EXTA; i++) {
1192:
1193: if (ubaud[i] == baud)
1194:
1195: break;
1196:
1197: }
1198:
1199: return i;
1200:
1201: }
1202:
1203:
1204:
1.1.1.2 root 1205: #define tosbaud(c) ( ((c) < 0 || (c) >= EXTA) ? -1L : ubaud[(unsigned)c] )
1.1 root 1206:
1207:
1208:
1209: long
1210:
1211: tty_ioctl(f, mode, arg)
1212:
1213: FILEPTR *f;
1214:
1215: int mode;
1216:
1217: void *arg;
1218:
1219: {
1220:
1221: struct sgttyb *sg;
1222:
1223: struct tchars *tc;
1224:
1225: struct ltchars *ltc;
1226:
1227: struct tty *tty;
1228:
1229: struct winsize *sz;
1230:
1231: struct xkey *xk;
1232:
1233: char *xktab;
1234:
1235: int i;
1236:
1237: long baud;
1238:
1239: short flags;
1240:
1.1.1.6 ! root 1241: long outq;
! 1242:
1.1 root 1243:
1244:
1245: if (!is_terminal(f)) {
1246:
1.1.1.2 root 1247: DEBUG(("tty_ioctl(mode %x): file is not a tty", mode));
1.1 root 1248:
1249: return EINVFN;
1250:
1251: }
1252:
1253: tty = (struct tty *)f->devinfo;
1254:
1255: assert(tty != 0);
1256:
1257:
1258:
1259: switch(mode) {
1260:
1.1.1.6 ! root 1261: case FIONREAD:
1.1 root 1262:
1.1.1.6 ! root 1263: {
1.1 root 1264:
1.1.1.6 ! root 1265: long r;
1.1 root 1266:
1267:
1268:
1.1.1.6 ! root 1269: r = (*f->dev->ioctl)(f, FIONREAD, (void *)arg);
1.1 root 1270:
1.1.1.6 ! root 1271: if (r || (f->flags & O_HEAD))
1.1 root 1272:
1.1.1.6 ! root 1273: return r;
1.1 root 1274:
1.1.1.6 ! root 1275: if (tty->state & TS_BLIND)
1.1 root 1276:
1.1.1.6 ! root 1277: *(long *)arg = 0;
1.1 root 1278:
1.1.1.6 ! root 1279: if ((tty->sg.sg_flags & T_XKEY) && (tty->state & TS_ESC) &&
1.1 root 1280:
1.1.1.6 ! root 1281: !*(long *)arg)
1.1 root 1282:
1.1.1.6 ! root 1283: *(long *)arg = 1;
1.1 root 1284:
1.1.1.6 ! root 1285: return 0;
1.1 root 1286:
1.1.1.6 ! root 1287: }
1.1 root 1288:
1.1.1.6 ! root 1289: case FIONWRITE:
1.1 root 1290:
1.1.1.6 ! root 1291: {
1.1 root 1292:
1.1.1.6 ! root 1293: long r;
1.1 root 1294:
1295:
1296:
1.1.1.6 ! root 1297: r = (*f->dev->ioctl)(f, FIONWRITE, (void *)arg);
1.1 root 1298:
1.1.1.6 ! root 1299: if (r || (f->flags & O_HEAD))
1.1 root 1300:
1.1.1.6 ! root 1301: return r;
1.1 root 1302:
1.1.1.6 ! root 1303: if ((tty->state & (TS_BLIND|TS_HOLD)))
1.1 root 1304:
1.1.1.6 ! root 1305: *(long *)arg = 0;
1.1 root 1306:
1.1.1.6 ! root 1307: return 0;
1.1 root 1308:
1.1.1.6 ! root 1309: }
1.1 root 1310:
1.1.1.6 ! root 1311: case TIOCSBRK:
1.1 root 1312:
1.1.1.6 ! root 1313: if (!(tty->state & TS_BLIND) || (f->flags & O_HEAD))
1.1 root 1314:
1.1.1.6 ! root 1315: return (*f->dev->ioctl)(f, TIOCSBRK, (void *)arg);
1.1 root 1316:
1.1.1.6 ! root 1317: return 0;
1.1 root 1318:
1.1.1.6 ! root 1319: case TIOCFLUSH:
1.1 root 1320:
1.1.1.6 ! root 1321: {
1.1 root 1322:
1.1.1.6 ! root 1323: long r;
1.1 root 1324:
1325:
1326:
1.1.1.6 ! root 1327: r = (*f->dev->ioctl)(f, TIOCFLUSH, (void *)arg);
1.1 root 1328:
1.1.1.6 ! root 1329: if (r || (f->flags & O_HEAD))
! 1330:
! 1331: return r;
! 1332:
! 1333: if (!arg || (*(int *)arg & 1))
! 1334:
! 1335: tty->state &= ~TS_ESC;
! 1336:
! 1337: return 0;
! 1338:
! 1339: }
! 1340:
! 1341: case TIOCGETP:
! 1342:
! 1343: {
! 1344:
! 1345: unsigned long bits[2] = {-1, TF_FLAGS};
! 1346:
! 1347: sg = (struct sgttyb *)arg;
! 1348:
! 1349: /* get input and output baud rates from the terminal device */
! 1350:
! 1351: baud = -1L;
! 1352:
! 1353: (*f->dev->ioctl)(f, TIOCIBAUD, &baud);
! 1354:
! 1355: tty->sg.sg_ispeed = unxbaud(baud);
! 1356:
! 1357: baud = -1L;
! 1358:
! 1359: (*f->dev->ioctl)(f, TIOCOBAUD, &baud);
! 1360:
! 1361: tty->sg.sg_ospeed = unxbaud(baud);
! 1362:
! 1363: /* get terminal flags */
! 1364:
! 1365: flags = 0;
! 1366:
! 1367: if ((*f->dev->ioctl)(f, TIOCSFLAGSB, &bits) == 0) {
! 1368:
! 1369: tty->sg.sg_flags &= ~TF_FLAGS;
! 1370:
! 1371: tty->sg.sg_flags |= (*bits & TF_FLAGS);
! 1372:
! 1373: } else if ((*f->dev->ioctl)(f, TIOCGFLAGS, &flags) == 0) {
! 1374:
! 1375: tty->sg.sg_flags &= ~TF_FLAGS;
! 1376:
! 1377: tty->sg.sg_flags |= (flags & TF_FLAGS);
! 1378:
! 1379: }
! 1380:
! 1381: *sg = tty->sg;
! 1382:
! 1383: return 0;
! 1384:
! 1385: }
! 1386:
! 1387: case TIOCSETP:
! 1388:
! 1389: while (((*f->dev->ioctl)(f, TIOCOUTQ, &outq) == 0) && outq)
! 1390:
! 1391: nap(200);
! 1392:
! 1393: /* FALL THROUGH */
! 1394:
! 1395: case TIOCSETN:
! 1396:
! 1397: {
! 1398:
! 1399: unsigned long bits[2];
! 1400:
! 1401: static unsigned short v[] = {1, 0};
! 1402:
! 1403: unsigned short oflags = tty->sg.sg_flags;
! 1404:
! 1405:
! 1406:
! 1407: sg = (struct sgttyb *)arg;
! 1408:
! 1409: tty->sg = *sg;
! 1410:
! 1411: /* change tty state */
! 1412:
! 1413: if (sg->sg_flags & T_RAW) {
! 1414:
! 1415: tty->state &= ~TS_COOKED;
! 1416:
! 1417: } else {
! 1418:
! 1419: tty->state |= TS_COOKED;
! 1420:
! 1421: }
! 1422:
! 1423: if (!(sg->sg_flags & T_XKEY)) {
! 1424:
! 1425: tty->state &= ~TS_ESC;
! 1426:
! 1427: }
! 1428:
! 1429: /* set baud rates */
! 1430:
! 1431: baud = tosbaud(sg->sg_ispeed);
! 1432:
! 1433: (*f->dev->ioctl)(f, TIOCIBAUD, &baud);
! 1434:
! 1435: baud = tosbaud(sg->sg_ospeed);
! 1436:
! 1437: (*f->dev->ioctl)(f, TIOCOBAUD, &baud);
! 1438:
! 1439: /* reset VMIN/VTIME */
! 1440:
! 1441: if ((*f->dev->ioctl)(f, TIOCSVMIN, &v) < 0) {
! 1442:
! 1443: tty->vmin = 1;
! 1444:
! 1445: tty->vtime = 0;
! 1446:
! 1447: }
! 1448:
! 1449: /* set parity, etc. */
! 1450:
! 1451: flags = TF_8BIT;
! 1452:
! 1453: if (sg->sg_flags & (T_EVENP|T_ODDP)) {
! 1454:
! 1455: flags = TF_7BIT;
! 1456:
! 1457: }
! 1458:
! 1459: flags |= (sg->sg_flags & TF_FLAGS);
! 1460:
! 1461: /* default allow breaks to SIGINT unless RAW and no echo... */
! 1462:
! 1463: if (!(sg->sg_flags & T_RAW) || (sg->sg_flags & T_ECHO))
! 1464:
! 1465: flags |= TF_BRKINT;
! 1466:
! 1467: /* leave local mode bit alone */
! 1468:
! 1469: bits[0] = (unsigned)flags; bits[1] = ~TF_CAR;
! 1470:
! 1471: if ((*f->dev->ioctl)(f, TIOCSFLAGSB, &bits) >= 0)
! 1472:
! 1473: return 0;
! 1474:
! 1475: /* if TIOCSFLAGSB failed clear TF_CAR, assume the device doesn't
! 1476:
! 1477: * know about carrier anyway... */
! 1478:
! 1479: if ((*f->dev->ioctl)(f, TIOCSFLAGS, &flags) >= 0)
! 1480:
! 1481: return 0;
! 1482:
! 1483: /* cannot set flags, don't save them */
! 1484:
! 1485: tty->sg.sg_flags = (tty->sg.sg_flags & ~TF_FLAGS)|
! 1486:
! 1487: (oflags & TF_FLAGS);
! 1488:
! 1489: return 0;
! 1490:
! 1491: }
! 1492:
! 1493: case TIOCGETC:
! 1494:
! 1495: tc = (struct tchars *)arg;
! 1496:
! 1497: *tc = tty->tc;
! 1498:
! 1499: return 0;
! 1500:
! 1501: case TIOCSETC:
1.1 root 1502:
1503: tc = (struct tchars *)arg;
1504:
1505: tty->tc = *tc;
1506:
1507: return 0;
1508:
1509: case TIOCGLTC:
1510:
1511: ltc = (struct ltchars *)arg;
1512:
1513: *ltc = tty->ltc;
1514:
1515: return 0;
1516:
1517: case TIOCSLTC:
1518:
1519: ltc = (struct ltchars *)arg;
1520:
1521: tty->ltc = *ltc;
1522:
1523: return 0;
1524:
1525: case TIOCGWINSZ:
1526:
1527: sz = (struct winsize *)arg;
1528:
1529: *sz = tty->wsiz;
1530:
1531: return 0;
1532:
1533: case TIOCSWINSZ:
1534:
1535: sz = (struct winsize *)arg;
1536:
1.1.1.6 ! root 1537: if (sz->ws_row != tty->wsiz.ws_row
! 1538:
! 1539: || sz->ws_col != tty->wsiz.ws_col
! 1540:
! 1541: || sz->ws_xpixel != tty->wsiz.ws_xpixel
! 1542:
! 1543: || sz->ws_ypixel != tty->wsiz.ws_ypixel)
! 1544:
! 1545: i = 1;
! 1546:
! 1547: else
! 1548:
! 1549: i = 0;
! 1550:
1.1 root 1551: tty->wsiz = *sz;
1552:
1.1.1.6 ! root 1553: if (i && tty->pgrp) killgroup(tty->pgrp, SIGWINCH, 1);
! 1554:
1.1 root 1555: return 0;
1556:
1557: case TIOCGPGRP:
1558:
1559: *((long *)arg) = tty->pgrp;
1560:
1561: return 0;
1562:
1563: case TIOCSPGRP:
1564:
1.1.1.6 ! root 1565: if (!tty->pgrp) {
! 1566:
! 1567: tty->pgrp = (*((long *)arg) & 0x00007fffL);
! 1568:
! 1569:
! 1570:
! 1571: if (!(f->flags & O_NDELAY) && (tty->state & TS_BLIND))
! 1572:
! 1573: (*f->dev->ioctl)(f, TIOCWONLINE, 0);
! 1574:
! 1575: } else {
! 1576:
! 1577: tty->pgrp = (*((long *)arg) & 0x00007fffL);
! 1578:
! 1579: }
1.1 root 1580:
1581: return 0;
1582:
1583: case TIOCSTART:
1584:
1.1.1.6 ! root 1585: /* tty in the middle of a hangup? */
! 1586:
! 1587: if (tty->hup_ospeed)
! 1588:
! 1589: return 0;
! 1590:
! 1591: /* if the device has writeb writers may sleep for TS_HOLD (instead of polling),
! 1592:
! 1593: * tell the device and wake them up
! 1594:
! 1595: */
! 1596:
! 1597: if (HAS_WRITEB(f)) {
! 1598:
! 1599: (void)(*f->dev->ioctl)(f, TIOCSTART, &tty->state);
! 1600:
! 1601: tty->state &= ~TS_HOLD;
! 1602:
! 1603: wake (IO_Q, (long)&tty->state);
! 1604:
! 1605: }
! 1606:
1.1 root 1607: tty->state &= ~TS_HOLD;
1608:
1.1.1.6 ! root 1609: if (tty->wsel) {
! 1610:
! 1611: long r = 0;
! 1612:
! 1613:
! 1614:
! 1615: (void)(*f->dev->ioctl)(f, FIONWRITE, &r);
! 1616:
! 1617: if (r && !(tty->state & TS_BLIND))
! 1618:
! 1619: wakeselect (tty->wsel);
! 1620:
! 1621: }
! 1622:
1.1 root 1623: return 0;
1624:
1625: case TIOCSTOP:
1626:
1.1.1.6 ! root 1627: if (HAS_WRITEB(f))
! 1628:
! 1629: (void)(*f->dev->ioctl)(f, TIOCSTOP, &tty->state);
! 1630:
1.1 root 1631: tty->state |= TS_HOLD;
1632:
1633: return 0;
1634:
1635: case TIOCGXKEY:
1636:
1637: xk = (struct xkey *)arg;
1638:
1639: i = xk->xk_num;
1640:
1641: if (i < 0 || i > 31) return ERANGE;
1642:
1643: xktab = tty->xkey;
1644:
1645: if (!xktab) xktab = vt52xkey;
1646:
1647: xktab += i*8;
1648:
1649: for (i = 0; i < 8; i++)
1650:
1651: xk->xk_def[i] = *xktab++;
1652:
1653: return 0;
1654:
1655: case TIOCSXKEY:
1656:
1657: xk = (struct xkey *)arg;
1658:
1659: xktab = tty->xkey;
1660:
1661: if (!xktab) {
1662:
1663: xktab = kmalloc((long)256);
1664:
1665: if (!xktab) return ENSMEM;
1666:
1667: for (i = 0; i < 256; i++)
1668:
1669: xktab[i] = vt52xkey[i];
1670:
1671: tty->xkey = xktab;
1672:
1673: }
1674:
1675: i = xk->xk_num;
1676:
1677: if (i < 0 || i > 31) return ERANGE;
1678:
1679: xktab += i*8;
1680:
1681: for (i = 0; i < 7; i++)
1682:
1683: xktab[i] = xk->xk_def[i];
1684:
1685: xktab[7] = 0;
1686:
1687: return 0;
1688:
1.1.1.6 ! root 1689: /*
! 1690:
! 1691: * change tty->state bits... really only makes sense to touch TS_HPCL
! 1692:
! 1693: * or maybe TS_COOKED. (TS_HOLD is already handled by TIOCSTART/STOP)
! 1694:
! 1695: */
! 1696:
! 1697: case TIOCSSTATEB:
! 1698:
! 1699: {
! 1700:
! 1701: long mask = ((long *)arg)[1] & ~(TS_HOLD|TS_BLIND);
! 1702:
! 1703: if (!(tty->sg.sg_flags & T_XKEY))
! 1704:
! 1705: mask &= ~TS_ESC;
! 1706:
! 1707: if (*(long *)arg != -1)
! 1708:
! 1709: tty->state = (tty->state & ~mask) | (*((long *)arg) & mask);
! 1710:
! 1711: *(long *)arg = tty->state;
! 1712:
! 1713: return 0;
! 1714:
! 1715: }
! 1716:
! 1717: case TIOCGSTATE:
! 1718:
! 1719: *(long *)arg = tty->state;
! 1720:
! 1721: return 0;
! 1722:
! 1723: /* hang up on close, handled by kernel if the device understands TIOCOBAUD */
! 1724:
! 1725: case TIOCHPCL:
! 1726:
! 1727: tty->state |= TS_HPCL;
! 1728:
! 1729: return 0;
! 1730:
! 1731: /* set/reset local mode */
! 1732:
! 1733: case TIOCNCAR:
! 1734:
! 1735: case TIOCCAR:
! 1736:
! 1737: {
! 1738:
! 1739: unsigned long bits[2] = {0, TF_CAR};
! 1740:
! 1741: if (mode == TIOCCAR)
! 1742:
! 1743: *bits = TF_CAR;
! 1744:
! 1745: (*f->dev->ioctl)(f, TIOCSFLAGSB, &bits);
! 1746:
! 1747: /*
! 1748:
! 1749: * if the ioctl failed the device does not know about carrier but don't
! 1750:
! 1751: * return an error then since its the same as carrier always on
! 1752:
! 1753: * (and anyway who puts a dialup line on a port that doesn't know
! 1754:
! 1755: * how to SIGHUP or hang up safely... :)
! 1756:
! 1757: */
! 1758:
! 1759: return 0;
! 1760:
! 1761: }
! 1762:
! 1763: /* emulate some new calls, they only get here when a device does not know them:
! 1764:
! 1765: */
! 1766:
! 1767: case TIOCSFLAGSB:
! 1768:
! 1769: {
! 1770:
! 1771: long fnew, mask = ((unsigned long *)arg)[1];
! 1772:
! 1773: if (*(long *)arg < 0) {
! 1774:
! 1775: (*f->dev->ioctl)(f, TIOCGFLAGS, &flags);
! 1776:
! 1777: *((unsigned long *)arg) = flags;
! 1778:
! 1779: return 0;
! 1780:
! 1781: }
! 1782:
! 1783: flags = 0;
! 1784:
! 1785: if (mask != -1)
! 1786:
! 1787: (*f->dev->ioctl)(f, TIOCGFLAGS, &flags);
! 1788:
! 1789: fnew = (flags & ~mask) | (*((unsigned long *)arg) & mask);
! 1790:
! 1791: if (mask == -1 || fnew != flags) {
! 1792:
! 1793: flags = fnew;
! 1794:
! 1795: (*f->dev->ioctl)(f, TIOCSFLAGS, &flags);
! 1796:
! 1797: (*f->dev->ioctl)(f, TIOCGFLAGS, &flags);
! 1798:
! 1799: }
! 1800:
! 1801: *(unsigned long *)arg = flags;
! 1802:
! 1803: return 0;
! 1804:
! 1805: }
! 1806:
! 1807: /*
! 1808:
! 1809: * tty_read handles VTIME itself but doing VMIN > 1 without support
! 1810:
! 1811: * from the device won't be very efficient
! 1812:
! 1813: */
! 1814:
! 1815: case TIOCGVMIN:
! 1816:
! 1817: ((unsigned short *)arg)[0] = 1; /* VMIN */
! 1818:
! 1819: ((unsigned short *)arg)[1] = tty->vtime; /* VTIME */
! 1820:
! 1821: return 0;
! 1822:
! 1823: case TIOCSVMIN:
! 1824:
! 1825: tty->vmin = 1;
! 1826:
! 1827: tty->vtime = ((unsigned short *)arg)[1];
! 1828:
! 1829: return 0;
! 1830:
! 1831: /* devices that don't know about carrier are always online... */
! 1832:
! 1833: case TIOCWONLINE:
! 1834:
! 1835: return 0;
! 1836:
! 1837: /* if the device didn't do TIOC[GS]FLAGS try transforming into TIOCSFLAGSB */
! 1838:
! 1839: case TIOCGFLAGS:
! 1840:
! 1841: case TIOCSFLAGS:
! 1842:
! 1843: {
! 1844:
! 1845: unsigned long bits[2] = {-1, (unsigned short)-1};
! 1846:
! 1847: long r;
! 1848:
! 1849:
! 1850:
! 1851: if (mode == TIOCSFLAGS)
! 1852:
! 1853: bits[0] = *(unsigned short *)arg;
! 1854:
! 1855: r = (*f->dev->ioctl)(f, TIOCSFLAGSB, &bits);
! 1856:
! 1857: if (!r && mode == TIOCGFLAGS)
! 1858:
! 1859: *((unsigned short *)arg) = *bits;
! 1860:
! 1861: return r;
! 1862:
! 1863: }
! 1864:
! 1865: #ifdef MDM0_IOCTLS
! 1866:
! 1867: /*
! 1868:
! 1869: * transform mdm0 ioctls, to allow old binaries run on new devices
! 1870:
! 1871: * note this does nothing for the other way around i.e. transform the
! 1872:
! 1873: * BSD ones (TIOCCAR/HPCL etc.) for mdm0...
! 1874:
! 1875: */
! 1876:
! 1877: case TIOCGHUPCL:
! 1878:
! 1879: *(short *)arg = tty->state & TS_HPCL ? 1 : 0;
! 1880:
! 1881: return 0;
! 1882:
! 1883: case TIOCSHUPCL:
! 1884:
! 1885: flags = *(short *)arg;
! 1886:
! 1887: *(short *)arg = tty->state & TS_HPCL ? 1 : 0;
! 1888:
! 1889: if (flags)
! 1890:
! 1891: tty->state |= TS_HPCL;
! 1892:
! 1893: else
! 1894:
! 1895: tty->state &= ~TS_HPCL;
! 1896:
! 1897: return 0;
! 1898:
! 1899: case TIOCGSOFTCAR:
! 1900:
! 1901: {
! 1902:
! 1903: long bits[2];
! 1904:
! 1905: flags = 1;
! 1906:
! 1907: bits[0] = -1; bits[1] = TF_CAR;
! 1908:
! 1909: if ((*f->dev->ioctl)(f, TIOCSFLAGSB, &bits) >= 0)
! 1910:
! 1911: flags = bits[0] & TF_CAR ? 0 : 1;
! 1912:
! 1913: *(short *)arg = flags;
! 1914:
! 1915: return 0;
! 1916:
! 1917: }
! 1918:
! 1919: case TIOCSSOFTCAR:
! 1920:
! 1921: {
! 1922:
! 1923: long bits[2];
! 1924:
! 1925: flags = 1;
! 1926:
! 1927: bits[0] = *(short *)arg ? 0 : TF_CAR; bits[1] = TF_CAR;
! 1928:
! 1929: if ((*f->dev->ioctl)(f, TIOCSFLAGSB, &bits) >= 0)
! 1930:
! 1931: flags = bits[0] & TF_CAR ? 0 : 1;
! 1932:
! 1933: *(short *)arg = flags;
! 1934:
! 1935: return 0;
! 1936:
! 1937: }
! 1938:
! 1939: #endif /* MDM0_IOCTLS */
! 1940:
1.1 root 1941: default:
1942:
1.1.1.2 root 1943: DEBUG(("tty_ioctl: bad function call"));
1.1 root 1944:
1945: return EINVFN;
1946:
1947: }
1948:
1949: }
1950:
1951:
1952:
1953: /*
1954:
1955: * function for translating extended characters (e.g. cursor keys, or
1956:
1957: * ALT+key sequences) into either escape sequences or meta characters.
1958:
1959: * for escape sequences, we return the the first character of the
1960:
1961: * sequence (normally ESC) and set the tty's state so that subsequent
1962:
1963: * calls to tty_getchar will pick up the remaining characters.
1964:
1965: * Note that escape sequences are limited to 7 characters at most.
1966:
1967: */
1968:
1969:
1970:
1971: static int
1972:
1973: escseq(tty, scan)
1974:
1975: struct tty *tty;
1976:
1977: int scan;
1978:
1979: {
1980:
1981: char *tab;
1982:
1983: int i;
1984:
1985:
1986:
1987: switch(scan) {
1988:
1989: case CURS_UP: i = 20; break;
1990:
1991: case CURS_DN: i = 21; break;
1992:
1993: case CURS_RT: i = 22; break;
1994:
1995: case CURS_LF: i = 23; break;
1996:
1997: case K_HELP: i = 24; break;
1998:
1999: case K_UNDO: i = 25; break;
2000:
2001: case K_INSERT:i = 26; break;
2002:
2003: case K_HOME: i = 27; break;
2004:
2005: case CURS_UP+0x100: i = 28; break;
2006:
2007: case CURS_DN+0x100: i = 29; break;
2008:
2009: case CURS_RT+0x100: i = 30; break;
2010:
2011: case CURS_LF+0x100: i = 31; break;
2012:
2013: default:
2014:
2015: if (scan >= F_1 && scan <= F_10) {
2016:
2017: i = scan - F_1;
2018:
2019: } else if (scan >= F_11 && scan <= F_20) {
2020:
2021: i = 10 + scan - F_11;
2022:
2023: } else
2024:
2025: i = -1;
2026:
2027: }
2028:
2029:
2030:
2031: if (i >= 0) { /* an extended escape sequence */
2032:
2033: tab = tty->xkey;
2034:
2035: if (!tab) tab = vt52xkey;
2036:
2037: i *= 8;
2038:
2039: scan = tab[i++];
2040:
2041: if (scan) {
2042:
2043: if (tab[i] == 0) i = 0;
2044:
2045: tty->state = (tty->state & ~TS_ESC) | i;
2046:
2047: }
2048:
2049: return scan;
2050:
2051: }
2052:
2053:
2054:
2055: if (scan >= ALT_1 && scan <= ALT_0) {
2056:
2057: scan -= (ALT_1-1);
2058:
2059: if (scan == 10) scan = 0;
2060:
2061: return (scan + '0') | 0x80;
2062:
2063: }
2064:
2065:
2066:
1.1.1.2 root 2067: tab = *( ((char **)Keytbl((void *)-1UL, (void *)-1UL, (void *)-1UL)) + 2 ); /* gratuitous (void *) for Lattice */
1.1 root 2068:
2069: scan = tab[scan];
2070:
2071: if (scan >= 'A' && scan <= 'Z') return scan | 0x80;
2072:
2073: return 0;
2074:
2075: }
2076:
2077:
2078:
2079: long
2080:
2081: tty_getchar(f, mode)
2082:
2083: FILEPTR *f;
2084:
2085: int mode;
2086:
2087: {
2088:
2089: struct tty *tty = (struct tty *)f->devinfo;
2090:
2091: char c, *tab;
2092:
2093: long r, ret;
2094:
2095: int scan;
2096:
2097: int master = f->flags & O_HEAD;
2098:
2099:
2100:
2101: assert(tty);
2102:
2103:
2104:
2105: /* pty masters never worry about job control and always read in raw mode */
2106:
2107: if (master) {
2108:
2109: ret = (*f->dev->read)(f, (char *)&r, 4L);
2110:
2111: return (ret != 4L) ? MiNTEOF : r;
2112:
2113: }
2114:
2115:
2116:
2117: /* job control check */
2118:
1.1.1.3 root 2119:
2120:
1.1.1.6 ! root 2121: /*
! 2122:
! 2123: entropy: only do the job control if SIGTTIN is neither blocked nor ignored,
! 2124:
! 2125: and only for the controlling tty (IEEE 1003.1-1990 7.1.1.4 70-78).
! 2126:
! 2127: BUG: if the process group is orphaned or SIGTTIN *is* blocked or ignored,
! 2128:
! 2129: we should return EIO instead of signalling.
! 2130:
! 2131: */
! 2132:
! 2133:
! 2134:
! 2135: if ((tty->pgrp && tty->pgrp != curproc->pgrp) &&
! 2136:
! 2137: (f->fc.dev == curproc->control->fc.dev) &&
! 2138:
! 2139: (f->fc.index == curproc->control->fc.index)) {
1.1 root 2140:
1.1.1.2 root 2141: TRACE(("job control: tty pgrp is %d proc pgrp is %d",
1.1 root 2142:
1.1.1.2 root 2143: tty->pgrp, curproc->pgrp));
1.1 root 2144:
1.1.1.6 ! root 2145: killgroup(curproc->pgrp, SIGTTIN, 1);
! 2146:
! 2147: check_sigs();
1.1 root 2148:
2149: }
2150:
2151:
2152:
2153: if (mode & COOKED)
2154:
2155: tty->state |= TS_COOKED;
2156:
2157: else
2158:
2159: tty->state &= ~TS_COOKED;
2160:
2161:
2162:
2163: c = UNDEF+1; /* set to UNDEF when we successfully read a character */
2164:
2165:
2166:
2167: /* we may be in the middle of an escape sequence */
2168:
1.1.1.2 root 2169: scan = (tty->state & TS_ESC);
2170:
2171: if (scan != 0) {
1.1 root 2172:
2173: if (mode & ESCSEQ) {
2174:
2175: tab = tty->xkey ? tty->xkey : vt52xkey;
2176:
2177: r = (unsigned char) tab[scan++];
2178:
2179: if (r) {
2180:
2181: c = UNDEF;
2182:
2183: if (tab[scan] == 0) scan = 0;
2184:
2185: }
2186:
2187: else
2188:
2189: scan = 0;
2190:
2191: tty->state = (tty->state & ~TS_ESC) | scan;
2192:
2193: }
2194:
2195: else
2196:
2197: tty->state &= ~TS_ESC;
2198:
2199: }
2200:
2201:
2202:
2203: while (c != UNDEF) {
2204:
1.1.1.6 ! root 2205: if (tty->state & TS_BLIND) {
! 2206:
! 2207: TRACE(("tty_getchar: offline"));
! 2208:
! 2209: return MiNTEOF;
! 2210:
! 2211: }
! 2212:
1.1 root 2213: ret = (*f->dev->read)(f, (char *)&r, 4L);
2214:
2215: if (ret != 4L) {
2216:
1.1.1.2 root 2217: DEBUG(("EOF on tty device"));
1.1 root 2218:
2219: return MiNTEOF;
2220:
2221: }
2222:
2223: c = r & 0x00ff;
2224:
1.1.1.2 root 2225: scan = (int)((r & 0x00ff0000L) >> 16);
1.1 root 2226:
2227: if ( (c == 0) && (mode & ESCSEQ) && scan) {
2228:
2229: c = UNDEF;
2230:
2231: /* translate cursor keys, etc. into escape sequences or
2232:
2233: * META characters
2234:
2235: */
2236:
2237: r = escseq(tty, scan);
2238:
2239: } else if ((mode & ESCSEQ) && ((scan == CURS_UP && c == '8') ||
2240:
2241: (scan == CURS_DN && c == '2') ||
2242:
2243: (scan == CURS_RT && c == '6') ||
2244:
2245: (scan == CURS_LF && c == '4'))) {
2246:
2247: c = UNDEF;
2248:
2249: r = escseq(tty, scan+0x100);
2250:
2251: } else if (mode & COOKED) {
2252:
2253: if (c == UNDEF)
2254:
2255: ; /* do nothing */
2256:
1.1.1.6 ! root 2257: else if (c == tty->ltc.t_dsuspc) {
! 2258:
! 2259: killgroup(curproc->pgrp, SIGTSTP, 1);
1.1 root 2260:
1.1.1.6 ! root 2261: check_sigs();
1.1 root 2262:
1.1.1.6 ! root 2263: } else if (c == tty->tc.t_intrc) {
1.1 root 2264:
1.1.1.6 ! root 2265: killgroup(curproc->pgrp, SIGINT, 1);
1.1 root 2266:
1.1.1.6 ! root 2267: check_sigs();
1.1.1.5 root 2268:
1.1.1.6 ! root 2269: } else if (c == tty->tc.t_quitc) {
1.1.1.5 root 2270:
1.1.1.6 ! root 2271: killgroup(curproc->pgrp, SIGQUIT, 1);
1.1 root 2272:
1.1.1.6 ! root 2273: check_sigs();
! 2274:
! 2275: } else if (c == tty->tc.t_stopc)
! 2276:
! 2277: tty_ioctl(f, TIOCSTOP, 0);
1.1 root 2278:
1.1.1.3 root 2279: else if (c == tty->tc.t_startc)
1.1 root 2280:
1.1.1.6 ! root 2281: tty_ioctl(f, TIOCSTART, 0);
1.1 root 2282:
2283: else
2284:
2285: c = UNDEF;
2286:
2287: }
2288:
2289: else
2290:
2291: c = UNDEF;
2292:
2293: }
2294:
2295:
2296:
2297: if (mode & ECHO)
2298:
2299: tty_putchar(f, r, mode);
2300:
2301:
2302:
2303: return r;
2304:
2305: }
2306:
2307:
2308:
2309: /*
2310:
2311: * tty_putchar: returns number of bytes successfully written
2312:
2313: */
2314:
2315:
2316:
2317: long
2318:
2319: tty_putchar(f, data, mode)
2320:
2321: FILEPTR *f;
2322:
2323: long data;
2324:
2325: int mode;
2326:
2327: {
2328:
2329: struct tty *tty;
2330:
2331: int master; /* file is pty master side */
2332:
2333: char ch;
2334:
2335:
2336:
2337: tty = (struct tty *)f->devinfo;
2338:
2339:
2340:
2341: master = f->flags & O_HEAD;
2342:
2343:
2344:
2345: /* pty masters don't need to worry about job control */
2346:
2347: if (master) {
2348:
2349: ch = data & 0xff;
2350:
2351:
2352:
2353: if ( (tty->state & TS_COOKED) && ch != UNDEF) {
2354:
1.1.1.6 ! root 2355: long r = 1;
! 2356:
! 2357:
! 2358:
1.1 root 2359: /* see if we're putting control characters into the buffer */
2360:
2361: if (ch == tty->tc.t_intrc) {
2362:
1.1.1.6 ! root 2363: killgroup(tty->pgrp, SIGINT, 1);
! 2364:
! 2365: if (!(tty->sg.sg_flags & T_NOFLSH))
! 2366:
! 2367: tty_ioctl(f, TIOCFLUSH, &r);
1.1 root 2368:
1.1.1.6 ! root 2369: tty_ioctl (f, TIOCSTART, 0);
1.1 root 2370:
2371: return 4L;
2372:
2373: }
2374:
2375: else if (ch == tty->tc.t_quitc) {
2376:
1.1.1.6 ! root 2377: killgroup(tty->pgrp, SIGQUIT, 1);
1.1 root 2378:
1.1.1.6 ! root 2379: if (!(tty->sg.sg_flags & T_NOFLSH))
! 2380:
! 2381: tty_ioctl(f, TIOCFLUSH, &r);
! 2382:
! 2383: tty_ioctl (f, TIOCSTART, 0);
1.1 root 2384:
2385: return 4L;
2386:
2387: }
2388:
2389: else if (ch == tty->ltc.t_suspc) {
2390:
1.1.1.6 ! root 2391: killgroup(tty->pgrp, SIGTSTP, 1);
! 2392:
! 2393: if (!(tty->sg.sg_flags & T_NOFLSH))
! 2394:
! 2395: tty_ioctl(f, TIOCFLUSH, &r);
1.1 root 2396:
1.1.1.6 ! root 2397: tty_ioctl (f, TIOCSTART, 0);
1.1 root 2398:
2399: return 4L;
2400:
2401: }
2402:
2403: else if (ch == tty->tc.t_stopc) {
2404:
1.1.1.6 ! root 2405: tty_ioctl (f, TIOCSTOP, 0);
1.1 root 2406:
2407: return 4L;
2408:
2409: }
2410:
2411: else if (ch == tty->tc.t_startc) {
2412:
1.1.1.6 ! root 2413: tty_ioctl (f, TIOCSTART, 0);
! 2414:
! 2415: return 4L;
! 2416:
! 2417: }
! 2418:
! 2419: else if (ch == tty->ltc.t_flushc) {
! 2420:
! 2421: long r = 2;
! 2422:
! 2423: tty_ioctl (f, TIOCFLUSH, &r);
1.1 root 2424:
2425: return 4L;
2426:
2427: }
2428:
2429: else if (tty->state & TS_HOLD) {
2430:
2431: return 0;
2432:
2433: }
2434:
2435: }
2436:
2437: goto do_putchar;
2438:
2439: }
2440:
1.1.1.6 ! root 2441: #if 1
! 2442:
! 2443: tty_checkttou(f, tty);
! 2444:
! 2445: #else
! 2446:
1.1 root 2447: /* job control checks */
2448:
2449: /* AKP: added T_TOSTOP; don't stop BG output if T_TOSTOP is clear */
2450:
1.1.1.6 ! root 2451: /*
! 2452:
! 2453: entropy: only do the job control if SIGTTOU is neither blocked nor ignored,
! 2454:
! 2455: and only for the controlling tty (IEEE 1003.1-1990 7.1.1.4 79-87).
! 2456:
! 2457: BUG: if the process group is orphaned and SIGTTOU *is not* blocked
! 2458:
! 2459: or ignored, we should return EIO instead of signalling.
! 2460:
! 2461: */
! 2462:
1.1.1.3 root 2463: if (tty->pgrp && tty->pgrp != curproc->pgrp &&
1.1 root 2464:
1.1.1.6 ! root 2465: (tty->sg.sg_flags & T_TOSTOP) &&
! 2466:
! 2467: (curproc->sighandle[SIGTTOU] != SIG_IGN) &&
! 2468:
! 2469: ((curproc->sigmask & (1L << SIGTTOU)) == 0L) &&
! 2470:
! 2471: (f->fc.dev == curproc->control->fc.dev) &&
! 2472:
! 2473: (f->fc.index == curproc->control->fc.index)) {
1.1 root 2474:
1.1.1.2 root 2475: TRACE(("job control: tty pgrp is %d proc pgrp is %d",
1.1 root 2476:
1.1.1.2 root 2477: tty->pgrp, curproc->pgrp));
1.1 root 2478:
1.1.1.6 ! root 2479: killgroup(curproc->pgrp, SIGTTOU, 1);
1.1 root 2480:
2481: }
2482:
1.1.1.6 ! root 2483: #endif
! 2484:
1.1 root 2485:
2486:
2487: if (mode & COOKED) {
2488:
2489: tty->state |= TS_COOKED;
2490:
1.1.1.6 ! root 2491: while (tty->state & (TS_HOLD|TS_BLIND)) {
! 2492:
! 2493: short bdev;
! 2494:
! 2495: extern DEVDRV bios_tdevice;
! 2496:
! 2497:
! 2498:
! 2499: if (tty->state & TS_BLIND) {
! 2500:
! 2501: TRACE(("tty_putchar: offline"));
! 2502:
! 2503: return 0;
! 2504:
! 2505: }
1.1.1.5 root 2506:
2507: #if 1
2508:
2509: /* hack: BIOS devices != console never reset TS_HOLD themselves
2510:
2511: unless another process happens to call tty_getchar on them while
2512:
2513: we're here. someone has a better fix? :-( -nox
2514:
2515: */
2516:
2517: /* BIOS device definitions */
2518:
2519: #define CONSDEV 2
2520:
2521: if (f->dev == &bios_tdevice &&
2522:
1.1.1.6 ! root 2523: (bdev=f->fc.aux) != CONSDEV) {
! 2524:
! 2525: long c;
1.1.1.5 root 2526:
2527:
2528:
1.1.1.6 ! root 2529: if (!bconstat(bdev) ||
1.1.1.5 root 2530:
1.1.1.6 ! root 2531: (c = bconin(bdev) & 0x7fffffffL) == UNDEF)
1.1.1.5 root 2532:
2533: ; /* do nothing */
2534:
2535: else if (c == tty->ltc.t_suspc) {
2536:
1.1.1.6 ! root 2537: tty_ioctl(f, TIOCSTART, 0);
1.1.1.5 root 2538:
1.1.1.6 ! root 2539: killgroup(tty->pgrp, SIGTSTP, 1);
1.1.1.5 root 2540:
2541: } else if (c == tty->tc.t_intrc) {
2542:
1.1.1.6 ! root 2543: tty_ioctl(f, TIOCSTART, 0);
1.1.1.5 root 2544:
1.1.1.6 ! root 2545: killgroup(tty->pgrp, SIGINT, 1);
1.1.1.5 root 2546:
2547: } else if (c == tty->tc.t_quitc) {
2548:
1.1.1.6 ! root 2549: tty_ioctl(f, TIOCSTART, 0);
1.1.1.5 root 2550:
1.1.1.6 ! root 2551: killgroup(tty->pgrp, SIGQUIT, 1);
1.1.1.5 root 2552:
2553: } else if (c == tty->tc.t_startc)
2554:
1.1.1.6 ! root 2555: tty_ioctl(f, TIOCSTART, 0);
! 2556:
! 2557: else if (c == tty->ltc.t_flushc) {
! 2558:
! 2559: long r = 2;
! 2560:
! 2561: tty_ioctl(f, TIOCFLUSH, &r);
! 2562:
! 2563: }
1.1.1.5 root 2564:
2565: }
2566:
1.1.1.6 ! root 2567: else
! 2568:
1.1.1.5 root 2569: #endif
1.1 root 2570:
1.1.1.6 ! root 2571: if (HAS_WRITEB(f)) {
! 2572:
! 2573: /* if the device has writeb assume it wakes us when TS_HOLD resets */
! 2574:
! 2575: sleep (IO_Q, (long)&tty->state);
! 2576:
! 2577: continue;
! 2578:
! 2579: }
! 2580:
1.1 root 2581: nap(60); /* sleep for 60 milliseconds */
2582:
1.1.1.5 root 2583: }
2584:
1.1 root 2585: }
2586:
2587: else
2588:
2589: tty->state &= ~TS_COOKED;
2590:
2591:
2592:
2593: do_putchar:
2594:
2595: return (*f->dev->write)(f, (char *)&data, 4L);
2596:
2597: }
2598:
1.1.1.6 ! root 2599:
! 2600:
! 2601: /*
! 2602:
! 2603: * special select() function that takes T_XKEY into account
! 2604:
! 2605: */
! 2606:
! 2607: long
! 2608:
! 2609: tty_select(FILEPTR *f, long proc, int mode)
! 2610:
! 2611: {
! 2612:
! 2613: struct tty *tty;
! 2614:
! 2615:
! 2616:
! 2617: tty = (struct tty *)f->devinfo;
! 2618:
! 2619: if (mode == O_RDONLY && (tty->sg.sg_flags & T_XKEY) &&
! 2620:
! 2621: (tty->state & TS_ESC))
! 2622:
! 2623: return 1;
! 2624:
! 2625: return (*f->dev->select)(f, proc, mode);
! 2626:
! 2627: }
! 2628:
! 2629:
! 2630:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.