home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume25 / ted / part02 / sysdep.c < prev   
Encoding:
C/C++ Source or Header  |  1991-11-06  |  11.3 KB  |  451 lines

  1. /*
  2. ** This software is Copyright (c) 1991 by Daniel Weaver.
  3. **
  4. ** Permission is hereby granted to copy, distribute or otherwise
  5. ** use any part of this package as long as you do not try to make
  6. ** money from it or pretend that you wrote it.  This copyright
  7. ** notice must be maintained in any copy made.
  8. **
  9. ** Use of this software constitutes acceptance for use in an AS IS
  10. ** condition. There are NO warranties with regard to this software.
  11. ** In no event shall the author be liable for any damages whatsoever
  12. ** arising out of or in connection with the use or performance of this
  13. ** software.  Any use of this software is at the user's own risk.
  14. **
  15. **  If you make modifications to this software that you feel
  16. **  increases it usefulness for the rest of the community, please
  17. **  email the changes, enhancements, bug fixes as well as any and
  18. **  all ideas to me. This software is going to be maintained and
  19. **  enhanced as deemed necessary by the community.
  20. */
  21. /*
  22.  * Operating system dependant functions.  Such as special tty handler
  23.  * modes.
  24.  */
  25.  
  26. #include <sys/errno.h>
  27. #if defined(vax) || defined(_AIX)
  28. #include <fcntl.h>
  29. #else
  30. #include <sys/fcntl.h>
  31. #endif
  32. #include <curses.h>
  33. #include <signal.h>
  34. #include "ted.h"
  35.  
  36. /* The appropriate speeds for various termio settings. */
  37. int speeds[] =
  38.     {
  39.     0,        /*  B0, */
  40.     50,        /*  B50, */
  41.     75,        /*  B75, */
  42.     110,    /*  B110, */
  43.     134,    /*  B134, */
  44.     150,    /*  B150, */
  45.     200,    /*  B200, */
  46.     300,    /*  B300, */
  47.     600,    /*  B600, */
  48.     1200,    /*  B1200, */
  49.     1800,    /*  B1800, */
  50.     2400,    /*  B2400, */
  51.     4800,    /*  B4800, */
  52.     9600,    /*  B9600, */
  53.     19200,    /*  EXTA, */
  54.     38400,    /*  EXTB, */
  55.     0,
  56.     };
  57.  
  58. /* error report location for ioctl's */
  59. extern int errno;
  60.  
  61. #ifdef ICANON  /* ATT UNIX */
  62. #define SLEEP(x)
  63. #define TTY_IS_NOECHO    !(new_modes.c_lflag & ECHO)
  64. #define TTY_IS_OUT_TRANS (new_modes.c_oflag & OPOST)
  65. #define TTY_IS_CHAR_MODE !(new_modes.c_lflag & ICANON)
  66.  
  67. struct termio old_modes, new_modes;
  68.  
  69. tty_raw(minch, mask)
  70. int minch, mask;
  71.    {  /* set tty to raw noecho */
  72.       new_modes = old_modes;
  73. #ifdef SELECT
  74.       new_modes.c_cc[VMIN]=1;
  75. #else
  76.       new_modes.c_cc[VMIN]=minch;
  77. #endif
  78.       new_modes.c_cc[VTIME]=2;
  79.       new_modes.c_lflag &=
  80.          ~(ISIG|ICANON|XCASE|ECHO|ECHOE|ECHOK|ECHONL);
  81. #ifdef LOBLK
  82.       new_modes.c_lflag &= ~LOBLK;
  83. #endif
  84.       new_modes.c_oflag &= ~(OPOST|OLCUC|TABDLY);
  85.       if (mask == ALLOW_PARITY)
  86.          {
  87.             new_modes.c_cflag &= ~(CSIZE|PARENB|HUPCL);
  88.             new_modes.c_cflag |= CS8;
  89.          }
  90.       new_modes.c_iflag &=
  91.          ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|
  92.          IUCLC|IXON|IXANY|IXOFF);
  93.       if (not_a_tty) return;
  94.       ioctl(fileno(stdin), TCSETAW, &new_modes);
  95.    }
  96.  
  97.  
  98. int
  99. tty_meta_prep()
  100.    {  /* print a warning before the meta key test */
  101.       if (not_a_tty) return 0;
  102.       if ((old_modes.c_cflag & CSIZE) == CS8) return 0;
  103.       ptext("The meta key test must be run with the");
  104.       ptext(" terminal set for 8 data bits.  Two stop bits");
  105.       ptext(" may also be needed for correct display.  I will");
  106.       ptext(" transmit 8 bit data but if the terminal is set for");
  107.       ptext(" 7 bit data, garbage may appear on the screen.");
  108.       return 1;
  109.    }
  110.  
  111.  
  112. tty_set()
  113.    {  /* set tty to special modes */
  114.       new_modes = old_modes;
  115.       new_modes.c_cc[VMIN]=1;
  116.       new_modes.c_cc[VTIME]=1;
  117.       new_modes.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL);
  118.       new_modes.c_oflag &= ~(ONLCR|OCRNL|ONLRET|OFILL);
  119.       if (char_mask == ALLOW_PARITY) new_modes.c_iflag &= ~ISTRIP;
  120.       switch (select_xon_xoff) {
  121.          case 0:
  122.             new_modes.c_iflag &= ~(IXON|IXOFF);
  123.             break;
  124.          case 1:
  125. #if sequent
  126.             /* the sequent System V emulation is broken */
  127.             new_modes = old_modes;
  128.             new_modes.c_cc[VEOL] = 6;  /* control F  (ACK) */
  129. #endif
  130.             new_modes.c_iflag |= IXON | IXOFF;
  131.             break;
  132.          }
  133.       switch (select_delay_type) {
  134.          case 0:
  135.             new_modes.c_oflag &=
  136.                ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
  137.             break;
  138.          case 1:
  139.             new_modes.c_oflag &=
  140.                ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
  141.             new_modes.c_oflag |= NL1 | CR2;
  142.             break;
  143.          }
  144.       if (!(new_modes.c_oflag & ~OPOST)) new_modes.c_oflag &= ~OPOST;
  145.       if (not_a_tty) return;
  146.       ioctl(fileno(stdin), TCSETAW, &new_modes);
  147.    }
  148.  
  149.  
  150. tty_reset()
  151.    {  /* reset the tty to the original modes */
  152.       fflush(stdout);
  153.       if (not_a_tty) return;
  154.       ioctl(fileno(stdin), TCSETAW, &old_modes);
  155.    }
  156.  
  157.  
  158. tty_init()
  159.    {  /* ATT terminal init */
  160.       int flags;
  161.  
  162. #ifdef F_GETFL
  163.       flags = fcntl(fileno(stdin), F_GETFL, 0);
  164.       nodelay_read = flags & O_NDELAY;
  165. #else
  166.       nodelay_read = FALSE;
  167. #endif
  168.       not_a_tty = FALSE;
  169.       if (ioctl(fileno(stdin), TCGETA, &old_modes) == -1)
  170.          {
  171.             if (errno == ENOTTY)
  172.                {
  173.                   tty_frame_size = 20;
  174.                   not_a_tty = TRUE;
  175.                   return;
  176.                }
  177.             printf("ioctl error: %d\n", errno);
  178.             exit(1);
  179.          }
  180.       /* if TAB3 is set then setterm() wipes out tabs (ht) */
  181.       new_modes = old_modes;
  182.       new_modes.c_oflag &= ~TABDLY;
  183.       if (ioctl(fileno(stdin), TCSETAW, &new_modes) == -1)
  184.          {
  185.             printf("ioctl error: %d\n", errno);
  186.             exit(1);
  187.          }
  188. #ifdef sequent
  189.       /* the sequent ATT emulation is broken soooo. */
  190.       old_modes.c_cflag &= ~(CSIZE | CSTOPB);
  191.       old_modes.c_cflag |= CS7 | PARENB;
  192. #endif
  193.       catchsig();
  194.       tty_baud_rate = speeds[old_modes.c_cflag & CBAUD];
  195.          switch (old_modes.c_cflag & CSIZE) {
  196.             case CS5:  tty_frame_size = 10;  break;
  197.             case CS6:  tty_frame_size = 12;  break;
  198.             case CS7:  tty_frame_size = 14;  break;
  199.             case CS8:  tty_frame_size = 16;  break;
  200.          }
  201.       tty_frame_size += 2 +
  202.          ((old_modes.c_cflag & PARENB) ? 2 : 0) +
  203.          ((old_modes.c_cflag & CSTOPB) ? 4 : 2);
  204.       tty_abort = old_modes.c_cc[VINTR];
  205.    }
  206.  
  207.  
  208. #else  /* berkeley */
  209. #define SLEEP(x) sleep(x)
  210. #define TTY_IS_NOECHO    !(new_modes.sg_flags & ECHO)
  211. #define TTY_IS_OUT_TRANS ((new_modes.sg_flags & (CBREAK|RAW|CRMOD)) == CRMOD)
  212. #define TTY_IS_CHAR_MODE ((new_modes.sg_flags & (CBREAK|RAW)) != 0)
  213.  
  214. struct sgttyb old_modes, new_modes;
  215.  
  216. tty_raw(minch, mask)
  217. int minch, mask;
  218.    {  /* set tty to raw noecho */
  219.       fflush(stdout);
  220.       new_modes = old_modes;
  221.       new_modes.sg_flags |= RAW;
  222.       new_modes.sg_flags &= ~(ALLDELAY | ECHO | CRMOD | CBREAK);
  223.       if (not_a_tty) return;
  224.       ioctl(fileno(stdin), TIOCSETP, &new_modes);
  225.    }
  226.  
  227. int
  228. tty_meta_prep()
  229.    {  /* print a warning before the meta key test */
  230.       if (not_a_tty) return 0;
  231.       ptext("The meta key test must be run with the");
  232.       ptext(" terminal set for 8 data bits.  Two stop bits");
  233.       ptext(" may also be needed for correct display.");
  234.       return 1;
  235.    }
  236.  
  237. extern short ospeed;
  238.  
  239. tty_set()
  240.    {  /* set tty modes */
  241.       fflush(stdout);
  242.       new_modes = old_modes;
  243.       new_modes.sg_flags &= ~(ECHO | CRMOD | CBREAK | RAW);
  244.       if (select_delay_type == 0 & select_xon_xoff == 0)
  245.          {
  246.             new_modes.sg_flags |= RAW;
  247.          }
  248.       else new_modes.sg_flags |= CBREAK;
  249.       switch (select_delay_type) {
  250.          case 0:
  251.             new_modes.sg_flags &= ~(ALLDELAY);
  252.             break;
  253.          case 1:
  254.             new_modes.sg_flags &= ~(ALLDELAY);
  255.             new_modes.sg_flags |= NL2 | CR1;
  256.             break;
  257.          }
  258. #ifdef TANDEM
  259.       switch (select_xon_xoff) {
  260.          case 0:
  261.             new_modes.sg_flags &= ~TANDEM;
  262.             break;
  263.          case 1:
  264.             new_modes.sg_flags |= TANDEM;
  265.             break;
  266.          }
  267. #endif
  268.       if (select_pads == 1) ospeed = -1;
  269.       if (not_a_tty) return;
  270.       ioctl(fileno(stdin), TIOCSETP, &new_modes);
  271.    }
  272.  
  273.  
  274. tty_reset()
  275.    {  /* reset the tty to the original modes */
  276.       fflush(stdout);
  277.       if (not_a_tty) return;
  278.       ioctl(fileno(stdin), TIOCSETP, &old_modes);
  279.    }
  280.  
  281.  
  282. tty_init()
  283.    {  /* Berkeley Unix tty init */
  284.       struct tchars tc;
  285.  
  286.       not_a_tty = nodelay_read = FALSE;
  287.       if (ioctl(fileno(stdin), TIOCGETC, &tc) == -1)
  288.          {
  289.             if (errno == ENOTTY)
  290.                {
  291.                   not_a_tty = TRUE;
  292.                   return;
  293.                }
  294.             printf("ioctl error: %d\n", errno);
  295.             exit(1);
  296.          }
  297.       tty_abort = tc.t_intrc;
  298.       if (ioctl(fileno(stdin), TIOCGETP, &old_modes) == -1)
  299.          {
  300.             printf("ioctl error: %d\n", errno);
  301.             exit(1);
  302.          }
  303.       catchsig();
  304.       tty_baud_rate = speeds[old_modes.sg_ospeed];
  305.       tty_frame_size = 22;  /* 8 data bits, 2 stop bits,    1 start bit */
  306.       tty_frame_size = 20;  /* 8 data bits, 1 stop bit,     1 start bit */
  307. #ifdef vax
  308.       tty_frame_size = 21;  /* 8 data bits, 1.5 stop bits,  1 start bit */
  309. #endif
  310.       if (ospeed < 0) ospeed = old_modes.sg_ospeed;
  311.    }
  312. #endif
  313.  
  314. int
  315. stty_query(q)
  316. int q;
  317.    {  /* return information about the terminal */
  318.       switch (q) {
  319.          case TTY_NOECHO:
  320.             return TTY_IS_NOECHO;
  321.          case TTY_OUT_TRANS:
  322.             return TTY_IS_OUT_TRANS;
  323.          case TTY_CHAR_MODE:
  324.             return TTY_IS_CHAR_MODE;
  325.       }
  326.    }
  327.  
  328. #ifdef SELECT
  329. int
  330. char_ready()
  331. {
  332.     struct _timeval {
  333.         long tv_sec;
  334.         long tv_usec;
  335.     };
  336.     int ifds, ofds, efds, n;
  337.     struct _timeval tv;
  338.  
  339.     ifds = 1 << fileno(stdin);
  340.     ofds = efds = 0;
  341.     tv.tv_sec = 0;
  342.     tv.tv_usec = 200000;
  343.     n = select(20, &ifds, &ofds, &efds, &tv);
  344.     return (n != 0);
  345. }
  346. #else
  347. #ifdef FIONREAD
  348. int
  349. char_ready()
  350.    {
  351.       int i, j;
  352.  
  353.       /* the following loop has to be tuned for each computer */
  354.          for (j = 0; j < 1000; j++) {
  355.             ioctl(fileno(stdin), FIONREAD, &i);
  356.             if (i) return i;
  357.          }
  358.       return i;
  359.    }
  360. #else
  361. #define char_ready() 1
  362. #endif
  363. #endif
  364.  
  365.  
  366. nite_nite()
  367.    {  /* go to sleep */
  368.       SLEEP(1);
  369.    }
  370.  
  371.  
  372. read_key(buf, max)
  373. char *buf;
  374. int max;
  375.    {  /* read one function key from the input stream */
  376.       int got, ask;
  377.       char *s;
  378.  
  379.       *buf = '\0';
  380.       s = buf;
  381.       fflush(stdout);
  382.       /* ATT unix may return 0 or 1, Berkeley Unix should be 1 */
  383.          while (read(fileno(stdin), s, 1) == 0);
  384.       ++s;
  385.       --max;
  386.          while (max > 0 && (ask = char_ready())) {
  387.             if (ask > max) ask = max;
  388.             if (got = read(fileno(stdin), s, ask)) s += got;
  389.             else break;
  390.             max -= got;
  391.          }
  392.       *s = '\0';
  393.       /* strip high order bits (if any) */
  394.          for (s = buf; *s; *s++ &= char_mask);
  395.    }
  396.  
  397.  
  398. ignoresig( )
  399. {
  400.     /* ignore signals */
  401.     signal(SIGINT, SIG_IGN);
  402.     signal(SIGHUP, SIG_IGN);
  403.     signal(SIGQUIT, SIG_IGN);
  404.     signal(SIGTERM, SIG_IGN);
  405. }
  406.  
  407.     /*  onintr( )
  408.      *
  409.      *  is the interrupt handling routine
  410.      *  onintr turns off interrupts while doing clean-up
  411.      *
  412.      *  onintr always exits fatally
  413.      */
  414.  
  415.  
  416. onintr()
  417. {
  418.     ignoresig();
  419.     tty_reset();
  420.     exit(1);
  421. }
  422.  
  423.  
  424.     /*  catchsig( )
  425.      *
  426.      *  set up to field interrupts (via function onintr( ))
  427.      *  so that if interrupted we can restore the correct terminal modes
  428.      *
  429.      *  catchsig simply returns
  430.      */
  431.  
  432.  
  433. catchsig( )
  434. {
  435.     /* EXTERNAL VARIABLE USED */
  436.     extern        onintr( );
  437.  
  438.     if ((signal(SIGINT, SIG_IGN)) == SIG_DFL)
  439.         signal(SIGINT, onintr);
  440.  
  441.     if ((signal(SIGHUP, SIG_IGN)) == SIG_DFL)
  442.         signal(SIGHUP, onintr);
  443.  
  444.     if ((signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
  445.         signal(SIGQUIT, onintr);
  446.  
  447.     if ((signal(SIGTERM, SIG_IGN)) == SIG_DFL)
  448.         signal(SIGTERM, onintr);
  449.  
  450. }
  451.