1/* vi: set sw=4 ts=4: 2 * 3 * term.c 4 * 5 * General purpose terminal handling library. 6 * 7 * Nick Patavalis (npat@inaccessnetworks.com) 8 * 9 * originaly by Pantelis Antoniou (panto@intranet.gr), Nick Patavalis 10 * 11 * Documentation can be found in the header file "term.h". 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation; either version 2 of the 16 * License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, but 19 * WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 26 * USA 27 * 28 * $Id$ 29 */ 30 31#include <stdlib.h> 32#include <stdio.h> 33#include <string.h> 34#include <errno.h> 35#include <unistd.h> 36#ifdef __linux__ 37#include <termio.h> 38#else 39#include <termios.h> 40#endif /* of __linux__ */ 41 42#include "term.h" 43 44/***************************************************************************/ 45 46static struct term_s { 47 int init; 48 int fd[MAX_TERMS]; 49 struct termios origtermios[MAX_TERMS]; 50 struct termios currtermios[MAX_TERMS]; 51 struct termios nexttermios[MAX_TERMS]; 52} term; 53 54/***************************************************************************/ 55 56int term_errno; 57 58static const char * const term_err_str[] = { 59 [TERM_EOK] = "No error", 60 [TERM_ENOINIT] = "Framework is uninitialized", 61 [TERM_EFULL] = "Framework is full", 62 [TERM_ENOTFOUND] = "Filedes not in the framework", 63 [TERM_EEXISTS] = "Filedes already in the framework", 64 [TERM_EATEXIT] = "Cannot install atexit handler", 65 [TERM_EISATTY] = "Filedes is not a tty", 66 [TERM_EFLUSH] = "Cannot flush the device", 67 [TERM_EGETATTR] = "Cannot get the device attributes", 68 [TERM_ESETATTR] = "Cannot set the device attributes", 69 [TERM_EBAUD] = "Invalid baud rate", 70 [TERM_ESETOSPEED] = "Cannot set the output speed", 71 [TERM_ESETISPEED] = "Cannot set the input speed", 72 [TERM_EPARITY] = "Invalid parity mode", 73 [TERM_EDATABITS] = "Invalid number of databits", 74 [TERM_EFLOW] = "Invalid flowcontrol mode", 75 [TERM_EDTRDOWN] = "Cannot lower DTR", 76 [TERM_EDTRUP] = "Cannot raise DTR", 77 [TERM_EDRAIN] = "Cannot drain the device", 78 [TERM_EBREAK] = "Cannot send break sequence" 79}; 80 81static char term_err_buff[1024]; 82 83const char * 84term_strerror (int terrnum, int errnum) 85{ 86 const char *rval; 87 88 switch(terrnum) { 89 case TERM_EFLUSH: 90 case TERM_EGETATTR: 91 case TERM_ESETATTR: 92 case TERM_ESETOSPEED: 93 case TERM_ESETISPEED: 94 case TERM_EDRAIN: 95 case TERM_EBREAK: 96 snprintf(term_err_buff, sizeof(term_err_buff), 97 "%s: %s", term_err_str[terrnum], strerror(errnum)); 98 rval = term_err_buff; 99 break; 100 case TERM_EOK: 101 case TERM_ENOINIT: 102 case TERM_EFULL: 103 case TERM_ENOTFOUND: 104 case TERM_EEXISTS: 105 case TERM_EATEXIT: 106 case TERM_EISATTY: 107 case TERM_EBAUD: 108 case TERM_EPARITY: 109 case TERM_EDATABITS: 110 case TERM_EFLOW: 111 case TERM_EDTRDOWN: 112 case TERM_EDTRUP: 113 snprintf(term_err_buff, sizeof(term_err_buff), 114 "%s", term_err_str[terrnum]); 115 rval = term_err_buff; 116 break; 117 default: 118 rval = NULL; 119 break; 120 } 121 122 return rval; 123} 124 125int 126term_perror (const char *prefix) 127{ 128 return fprintf(stderr, "%s %s\n", 129 prefix, term_strerror(term_errno, errno)); 130} 131 132/***************************************************************************/ 133 134static int 135term_find_next_free (void) 136{ 137 int rval, i; 138 139 do { /* dummy */ 140 if ( ! term.init ) { 141 term_errno = TERM_ENOINIT; 142 rval = -1; 143 break; 144 } 145 146 for (i = 0; i < MAX_TERMS; i++) 147 if ( term.fd[i] == -1 ) break; 148 149 if ( i == MAX_TERMS ) { 150 term_errno = TERM_EFULL; 151 rval = -1; 152 break; 153 } 154 155 rval = i; 156 } while (0); 157 158 return rval; 159} 160 161/***************************************************************************/ 162 163static int 164term_find (int fd) 165{ 166 int rval, i; 167 168 do { /* dummy */ 169 if ( ! term.init ) { 170 term_errno = TERM_ENOINIT; 171 rval = -1; 172 break; 173 } 174 175 for (i = 0; i < MAX_TERMS; i++) 176 if (term.fd[i] == fd) break; 177 178 if ( i == MAX_TERMS ) { 179 term_errno = TERM_ENOTFOUND; 180 rval = -1; 181 break; 182 } 183 184 rval = i; 185 } while (0); 186 187 return rval; 188} 189 190/***************************************************************************/ 191 192static void 193term_exitfunc (void) 194{ 195 int r, i; 196 197 do { /* dummy */ 198 if ( ! term.init ) 199 break; 200 201 for (i = 0; i < MAX_TERMS; i++) { 202 if (term.fd[i] == -1) 203 continue; 204 do { /* dummy */ 205 r = tcflush(term.fd[i], TCIOFLUSH); 206 if ( r < 0 ) break; 207 r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); 208 if ( r < 0 ) break; 209 } while (0); 210 if ( r < 0 ) { 211 char *tname; 212 213 tname = ttyname(term.fd[i]); 214 if ( ! tname ) tname = "UNKNOWN"; 215 fprintf(stderr, "%s: reset failed for dev %s: %s\n", 216 __FUNCTION__, tname, strerror(errno)); 217 } 218 term.fd[i] = -1; 219 } 220 } while (0); 221} 222 223/***************************************************************************/ 224 225int 226term_lib_init (void) 227{ 228 int rval, r, i; 229 230 rval = 0; 231 232 do { /* dummy */ 233 if ( term.init ) { 234 /* reset all terms back to their original settings */ 235 for (i = 0; i < MAX_TERMS; i++) { 236 if (term.fd[i] == -1) 237 continue; 238 do { 239 r = tcflush(term.fd[i], TCIOFLUSH); 240 if ( r < 0 ) break; 241 r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); 242 if ( r < 0 ) break; 243 } while (0); 244 if ( r < 0 ) { 245 char *tname; 246 247 tname = ttyname(term.fd[i]); 248 if ( ! tname ) tname = "UNKNOWN"; 249 fprintf(stderr, "%s: reset failed for dev %s: %s\n", 250 __FUNCTION__, tname, strerror(errno)); 251 } 252 term.fd[i] = -1; 253 } 254 } else { 255 /* initialize term structure. */ 256 for (i = 0; i < MAX_TERMS; i++) 257 term.fd[i] = -1; 258 if ( atexit(term_exitfunc) != 0 ) { 259 term_errno = TERM_EATEXIT; 260 rval = -1; 261 break; 262 } 263 /* ok. term struct is now initialized. */ 264 term.init = 1; 265 } 266 } while(0); 267 268 return rval; 269} 270 271/***************************************************************************/ 272 273int 274term_add (int fd) 275{ 276 int rval, r, i; 277 278 rval = 0; 279 280 do { /* dummy */ 281 i = term_find(fd); 282 if ( i >= 0 ) { 283 term_errno = TERM_EEXISTS; 284 rval = -1; 285 break; 286 } 287 288 if ( ! isatty(fd) ) { 289 term_errno = TERM_EISATTY; 290 rval = -1; 291 break; 292 } 293 294 i = term_find_next_free(); 295 if ( i < 0 ) { 296 rval = -1; 297 break; 298 } 299 300 r = tcgetattr(fd, &term.origtermios[i]); 301 if ( r < 0 ) { 302 term_errno = TERM_EGETATTR; 303 rval = -1; 304 break; 305 } 306 307 term.currtermios[i] = term.origtermios[i]; 308 term.nexttermios[i] = term.origtermios[i]; 309 term.fd[i] = fd; 310 } while (0); 311 312 return rval; 313} 314 315/***************************************************************************/ 316 317int 318term_remove(int fd) 319{ 320 int rval, r, i; 321 322 rval = 0; 323 324 do { /* dummy */ 325 i = term_find(fd); 326 if ( i < 0 ) { 327 rval = -1; 328 break; 329 } 330 331 do { /* dummy */ 332 r = tcflush(term.fd[i], TCIOFLUSH); 333 if ( r < 0 ) { 334 term_errno = TERM_EFLUSH; 335 rval = -1; 336 break; 337 } 338 r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); 339 if ( r < 0 ) { 340 term_errno = TERM_ESETATTR; 341 rval = -1; 342 break; 343 } 344 } while (0); 345 346 term.fd[i] = -1; 347 } while (0); 348 349 return rval; 350} 351 352/***************************************************************************/ 353 354int 355term_erase(int fd) 356{ 357 int rval, i; 358 359 rval = 0; 360 361 do { /* dummy */ 362 i = term_find(fd); 363 if ( i < 0 ) { 364 rval = -1; 365 break; 366 } 367 368 term.fd[i] = -1; 369 } while (0); 370 371 return rval; 372} 373 374/***************************************************************************/ 375 376int 377term_replace (int oldfd, int newfd) 378{ 379 int rval, r, i; 380 381 rval = 0; 382 383 do { /* dummy */ 384 385 i = term_find(oldfd); 386 if ( i < 0 ) { 387 rval = -1; 388 break; 389 } 390 391 r = tcsetattr(newfd, TCSAFLUSH, &term.currtermios[i]); 392 if ( r < 0 ) { 393 term_errno = TERM_ESETATTR; 394 rval = -1; 395 break; 396 } 397 398 term.fd[i] = newfd; 399 400 } while (0); 401 402 return rval; 403} 404 405/***************************************************************************/ 406 407int 408term_reset (int fd) 409{ 410 int rval, r, i; 411 412 rval = 0; 413 414 do { /* dummy */ 415 416 i = term_find(fd); 417 if ( i < 0 ) { 418 rval = -1; 419 break; 420 } 421 422 r = tcflush(term.fd[i], TCIOFLUSH); 423 if ( r < 0 ) { 424 term_errno = TERM_EFLUSH; 425 rval = -1; 426 break; 427 } 428 r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]); 429 if ( r < 0 ) { 430 term_errno = TERM_ESETATTR; 431 rval = -1; 432 break; 433 } 434 435 term.currtermios[i] = term.origtermios[i]; 436 term.nexttermios[i] = term.origtermios[i]; 437 } while (0); 438 439 return rval; 440} 441 442/***************************************************************************/ 443 444int 445term_revert (int fd) 446{ 447 int rval, i; 448 449 rval = 0; 450 451 do { /* dummy */ 452 453 i = term_find(fd); 454 if ( i < 0 ) { 455 rval = -1; 456 break; 457 } 458 459 term.nexttermios[i] = term.currtermios[i]; 460 461 } while (0); 462 463 return rval; 464} 465 466/***************************************************************************/ 467 468int 469term_refresh (int fd) 470{ 471 int rval, r, i; 472 473 rval = 0; 474 475 do { /* dummy */ 476 477 i = term_find(fd); 478 if ( i < 0 ) { 479 rval = -1; 480 break; 481 } 482 483 r = tcgetattr(fd, &term.currtermios[i]); 484 if ( r < 0 ) { 485 term_errno = TERM_EGETATTR; 486 rval = -1; 487 break; 488 } 489 490 } while (0); 491 492 return rval; 493} 494 495/***************************************************************************/ 496 497int 498term_apply (int fd) 499{ 500 int rval, r, i; 501 502 rval = 0; 503 504 do { /* dummy */ 505 506 i = term_find(fd); 507 if ( i < 0 ) { 508 rval = -1; 509 break; 510 } 511 512 r = tcsetattr(term.fd[i], TCSAFLUSH, &term.nexttermios[i]); 513 if ( r < 0 ) { 514 term_errno = TERM_ESETATTR; 515 rval = -1; 516 break; 517 } 518 519 term.currtermios[i] = term.nexttermios[i]; 520 521 } while (0); 522 523 return rval; 524} 525 526/***************************************************************************/ 527 528int 529term_set_raw (int fd) 530{ 531 int rval, i; 532 533 rval = 0; 534 535 do { /* dummy */ 536 537 i = term_find(fd); 538 if ( i < 0 ) { 539 rval = -1; 540 break; 541 } 542 543 /* BSD raw mode */ 544 cfmakeraw(&term.nexttermios[i]); 545 /* one byte at a time, no timer */ 546 term.nexttermios[i].c_cc[VMIN] = 1; 547 term.nexttermios[i].c_cc[VTIME] = 0; 548 549 } while (0); 550 551 return rval; 552} 553 554/***************************************************************************/ 555 556int 557term_set_baudrate (int fd, int baudrate) 558{ 559 int rval, r, i; 560 speed_t spd; 561 struct termios tio; 562 563 rval = 0; 564 565 do { /* dummy */ 566 567 i = term_find(fd); 568 if ( i < 0 ) { 569 rval = -1; 570 break; 571 } 572 573 tio = term.nexttermios[i]; 574 575 switch (baudrate) { 576 case 0: 577 spd = B0; 578 break; 579 case 50: 580 spd = B50; 581 break; 582 case 75: 583 spd = B75; 584 break; 585 case 110: 586 spd = B110; 587 break; 588 case 134: 589 spd = B134; 590 break; 591 case 150: 592 spd = B150; 593 break; 594 case 200: 595 spd = B200; 596 break; 597 case 300: 598 spd = B300; 599 break; 600 case 600: 601 spd = B600; 602 break; 603 case 1200: 604 spd = B1200; 605 break; 606 case 1800: 607 spd = B1800; 608 break; 609 case 2400: 610 spd = B2400; 611 break; 612 case 4800: 613 spd = B4800; 614 break; 615 case 9600: 616 spd = B9600; 617 break; 618 case 19200: 619 spd = B19200; 620 break; 621 case 38400: 622 spd = B38400; 623 break; 624 case 57600: 625 spd = B57600; 626 break; 627 case 115200: 628 spd = B115200; 629 break; 630 case 230400: 631 spd = B230400; 632 break; 633 default: 634 term_errno = TERM_EBAUD; 635 rval = -1; 636 break; 637 } 638 if ( rval < 0 ) break; 639 640 r = cfsetospeed(&tio, spd); 641 if ( r < 0 ) { 642 term_errno = TERM_ESETOSPEED; 643 rval = -1; 644 break; 645 } 646 647 r = cfsetispeed(&tio, spd); 648 if ( r < 0 ) { 649 term_errno = TERM_ESETISPEED; 650 rval = -1; 651 break; 652 } 653 654 term.nexttermios[i] = tio; 655 656 } while (0); 657 658 return rval; 659} 660 661/***************************************************************************/ 662 663int 664term_set_parity (int fd, enum parity_e parity) 665{ 666 int rval, i; 667 struct termios *tiop; 668 669 rval = 0; 670 671 do { /* dummy */ 672 673 i = term_find(fd); 674 if ( i < 0 ) { 675 rval = -1; 676 break; 677 } 678 679 tiop = &term.nexttermios[i]; 680 681 switch (parity) { 682 case P_EVEN: 683 tiop->c_cflag = (tiop->c_cflag & ~(PARENB | PARODD)) | PARENB; 684 break; 685 case P_ODD: 686 tiop->c_cflag = (tiop->c_cflag & ~(PARENB | PARODD)) | PARODD; 687 break; 688 case P_NONE: 689 tiop->c_cflag = (tiop->c_cflag & ~(PARENB | PARODD)); 690 break; 691 default: 692 term_errno = TERM_EPARITY; 693 rval = -1; 694 break; 695 } 696 if ( rval < 0 ) break; 697 698 } while (0); 699 700 return rval; 701} 702 703/***************************************************************************/ 704 705int 706term_set_databits (int fd, int databits) 707{ 708 int rval, i; 709 struct termios *tiop; 710 711 rval = 0; 712 713 do { /* dummy */ 714 715 i = term_find(fd); 716 if ( i < 0 ) { 717 rval = -1; 718 break; 719 } 720 721 tiop = &term.nexttermios[i]; 722 723 switch (databits) { 724 case 5: 725 tiop->c_cflag = (tiop->c_cflag & ~CSIZE) | CS5; 726 break; 727 case 6: 728 tiop->c_cflag = (tiop->c_cflag & ~CSIZE) | CS6; 729 break; 730 case 7: 731 tiop->c_cflag = (tiop->c_cflag & ~CSIZE) | CS7; 732 break; 733 case 8: 734 tiop->c_cflag = (tiop->c_cflag & ~CSIZE) | CS8; 735 break; 736 default: 737 term_errno = TERM_EDATABITS; 738 rval = -1; 739 break; 740 } 741 if ( rval < 0 ) break; 742 743 } while (0); 744 745 return rval; 746} 747 748/***************************************************************************/ 749 750int 751term_set_flowcntrl (int fd, enum flowcntrl_e flowcntl) 752{ 753 int rval, i; 754 struct termios *tiop; 755 756 rval = 0; 757 758 do { /* dummy */ 759 760 i = term_find(fd); 761 if ( i < 0 ) { 762 rval = -1; 763 break; 764 } 765 766 tiop = &term.nexttermios[i]; 767 768 switch (flowcntl) { 769 case FC_RTSCTS: 770 tiop->c_cflag |= CRTSCTS; 771 tiop->c_iflag &= ~(IXON | IXOFF | IXANY); 772 break; 773 case FC_XONXOFF: 774 tiop->c_cflag &= ~(CRTSCTS); 775 tiop->c_iflag |= IXON | IXOFF; 776 break; 777 case FC_NONE: 778 tiop->c_cflag &= ~(CRTSCTS); 779 tiop->c_iflag &= ~(IXON | IXOFF | IXANY); 780 break; 781 default: 782 term_errno = TERM_EFLOW; 783 rval = -1; 784 break; 785 } 786 if ( rval < 0 ) break; 787 788 } while (0); 789 790 return rval; 791} 792 793/***************************************************************************/ 794 795int 796term_set_local(int fd, int local) 797{ 798 int rval, i; 799 struct termios *tiop; 800 801 rval = 0; 802 803 do { /* dummy */ 804 805 i = term_find(fd); 806 if ( i < 0 ) { 807 rval = -1; 808 break; 809 } 810 811 tiop = &term.nexttermios[i]; 812 813 if ( local ) 814 tiop->c_cflag |= CLOCAL; 815 else 816 tiop->c_cflag &= ~CLOCAL; 817 818 } while (0); 819 820 return rval; 821} 822 823/***************************************************************************/ 824 825int 826term_set_hupcl (int fd, int on) 827{ 828 int rval, i; 829 struct termios *tiop; 830 831 rval = 0; 832 833 do { /* dummy */ 834 835 i = term_find(fd); 836 if ( i < 0 ) { 837 rval = -1; 838 break; 839 } 840 841 tiop = &term.nexttermios[i]; 842 843 if ( on ) 844 tiop->c_cflag |= HUPCL; 845 else 846 tiop->c_cflag &= ~HUPCL; 847 848 } while (0); 849 850 return rval; 851} 852 853/***************************************************************************/ 854 855int 856term_set(int fd, 857 int raw, 858 int baud, enum parity_e parity, int bits, enum flowcntrl_e fc, 859 int local, int hup_close) 860{ 861 int rval, r, i, ni; 862 struct termios tio; 863 864 rval = 0; 865 866 do { /* dummy */ 867 868 i = term_find(fd); 869 if ( i < 0 ) { 870 ni = term_add(fd); 871 if ( ni < 0 ) { 872 rval = -1; 873 break; 874 } 875 } else { 876 ni = i; 877 } 878 879 tio = term.nexttermios[ni]; 880 881 do { /* dummy */ 882 883 if (raw) { 884 r = term_set_raw(fd); 885 if ( r < 0 ) { rval = -1; break; } 886 } 887 888 r = term_set_baudrate(fd, baud); 889 if ( r < 0 ) { rval = -1; break; } 890 891 r = term_set_parity(fd, parity); 892 if ( r < 0 ) { rval = -1; break; } 893 894 r = term_set_databits(fd, bits); 895 if ( r < 0 ) { rval = -1; break; } 896 897 r = term_set_flowcntrl(fd, fc); 898 if ( r < 0 ) { rval = -1; break; } 899 900 r = term_set_local(fd, local); 901 if ( r < 0 ) { rval = -1; break; } 902 903 r = term_set_hupcl(fd, hup_close); 904 if ( r < 0 ) { rval = -1; break; } 905 906 } while (0); 907 908 if ( rval < 0 ) { 909 if ( i < 0 ) 910 /* new addition. must be removed */ 911 term.fd[ni] = -1; 912 else 913 /* just revert to previous settings */ 914 term.nexttermios[ni] = tio; 915 } 916 917 } while (0); 918 919 return rval; 920} 921 922/***************************************************************************/ 923 924int 925term_pulse_dtr (int fd) 926{ 927 int rval, r, i; 928 929 rval = 0; 930 931 do { /* dummy */ 932 933 i = term_find(fd); 934 if ( i < 0 ) { 935 rval = -1; 936 break; 937 } 938 939#ifdef __linux__ 940 { 941 int opins = TIOCM_DTR; 942 943 r = ioctl(fd, TIOCMBIC, &opins); 944 if ( r < 0 ) { 945 term_errno = TERM_EDTRDOWN; 946 rval = -1; 947 break; 948 } 949 950 sleep(1); 951 952 r = ioctl(fd, TIOCMBIS, &opins); 953 if ( r < 0 ) { 954 term_errno = TERM_EDTRUP; 955 rval = -1; 956 break; 957 } 958 } 959#else 960 { 961 struct termios tio, tioold; 962 963 r = tcgetattr(fd, &tio); 964 if ( r < 0 ) { 965 term_errno = TERM_ESETATTR; 966 rval = -1; 967 break; 968 } 969 970 tioold = tio; 971 972 cfsetospeed(&tio, B0); 973 cfsetispeed(&tio, B0); 974 r = tcsetattr(fd, TCSANOW, &tio); 975 if ( r < 0 ) { 976 term_errno = TERM_ESETATTR; 977 rval = -1; 978 break; 979 } 980 981 sleep(1); 982 983 r = tcsetattr(fd, TCSANOW, &tioold); 984 if ( r < 0 ) { 985 term.currtermios[i] = tio; 986 term_errno = TERM_ESETATTR; 987 rval = -1; 988 break; 989 } 990 } 991#endif /* of __linux__ */ 992 993 } while (0); 994 995 return rval; 996} 997 998/***************************************************************************/ 999 1000int 1001term_raise_dtr(int fd) 1002{ 1003 int rval, r, i; 1004 1005 rval = 0; 1006 1007 do { /* dummy */ 1008 1009 i = term_find(fd); 1010 if ( i < 0 ) { 1011 rval = -1; 1012 break; 1013 } 1014 1015#ifdef __linux__ 1016 { 1017 int opins = TIOCM_DTR; 1018 1019 r = ioctl(fd, TIOCMBIS, &opins); 1020 if ( r < 0 ) { 1021 term_errno = TERM_EDTRUP; 1022 rval = -1; 1023 break; 1024 } 1025 } 1026#else 1027 r = tcsetattr(fd, TCSANOW, &term.currtermios[i]); 1028 if ( r < 0 ) { 1029 /* FIXME: perhaps try to update currtermios */ 1030 term_errno = TERM_ESETATTR; 1031 rval = -1; 1032 break; 1033 } 1034#endif /* of __linux__ */ 1035 } while (0); 1036 1037 return rval; 1038} 1039 1040/***************************************************************************/ 1041 1042 1043int 1044term_lower_dtr(int fd) 1045{ 1046 int rval, r, i; 1047 1048 rval = 0; 1049 1050 do { /* dummy */ 1051 1052 i = term_find(fd); 1053 if ( i < 0 ) { 1054 rval = -1; 1055 break; 1056 } 1057 1058#ifdef __linux__ 1059 { 1060 int opins = TIOCM_DTR; 1061 1062 r = ioctl(fd, TIOCMBIC, &opins); 1063 if ( r < 0 ) { 1064 term_errno = TERM_EDTRDOWN; 1065 rval = -1; 1066 break; 1067 } 1068 } 1069#else 1070 { 1071 struct termios tio; 1072 1073 r = tcgetattr(fd, &tio); 1074 if ( r < 0 ) { 1075 term_errno = TERM_EGETATTR; 1076 rval = -1; 1077 break; 1078 } 1079 term.currtermios[i] = tio; 1080 1081 cfsetospeed(&tio, B0); 1082 cfsetispeed(&tio, B0); 1083 1084 r = tcsetattr(fd, TCSANOW, &tio); 1085 if ( r < 0 ) { 1086 term_errno = TERM_ESETATTR; 1087 rval = -1; 1088 break; 1089 } 1090 } 1091#endif /* of __linux__ */ 1092 } while (0); 1093 1094 return rval; 1095} 1096 1097/***************************************************************************/ 1098 1099int 1100term_drain(int fd) 1101{ 1102 int rval, r; 1103 1104 rval = 0; 1105 1106 do { /* dummy */ 1107 1108 r = term_find(fd); 1109 if ( r < 0 ) { 1110 rval = -1; 1111 break; 1112 } 1113 1114 do { 1115 r = tcdrain(fd); 1116 } while ( r < 0 && errno == EINTR); 1117 if ( r < 0 ) { 1118 term_errno = TERM_EDRAIN; 1119 rval = -1; 1120 break; 1121 } 1122 1123 } while (0); 1124 1125 return rval; 1126} 1127 1128/***************************************************************************/ 1129 1130int 1131term_flush(int fd) 1132{ 1133 int rval, r; 1134 1135 rval = 0; 1136 1137 do { /* dummy */ 1138 1139 r = term_find(fd); 1140 if ( r < 0 ) { 1141 rval = -1; 1142 break; 1143 } 1144 1145 r = tcflush(fd, TCIOFLUSH); 1146 if ( r < 0 ) { 1147 rval = -1; 1148 break; 1149 } 1150 1151 } while (0); 1152 1153 return rval; 1154} 1155 1156/***************************************************************************/ 1157 1158int 1159term_break(int fd) 1160{ 1161 int rval, r; 1162 1163 rval = 0; 1164 1165 do { /* dummy */ 1166 1167 r = term_find(fd); 1168 if ( r < 0 ) { 1169 rval = -1; 1170 break; 1171 } 1172 1173 r = tcsendbreak(fd, 0); 1174 if ( r < 0 ) { 1175 term_errno = TERM_EBREAK; 1176 rval = -1; 1177 break; 1178 } 1179 1180 } while (0); 1181 1182 return rval; 1183} 1184 1185/**************************************************************************/ 1186 1187/* 1188 * Local Variables: 1189 * mode:c 1190 * tab-width: 4 1191 * c-basic-offset: 4 1192 * End: 1193 */ 1194