home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / jove-4.16-src.tgz / tar.out / bsd / jove / unix.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  12KB  |  512 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
  3.  * provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is *
  5.  * included in all the files.                                           *
  6.  ************************************************************************/
  7.  
  8. #include <errno.h>
  9.  
  10. #include "jove.h"
  11.  
  12. #ifdef UNIX /* the body is the rest of the file */
  13.  
  14. #include "fp.h"
  15.  
  16. #ifdef BIFF
  17. # include <sys/stat.h>
  18. #endif
  19.  
  20. #include "chars.h"
  21. #include "term.h"    /* ospeed */
  22. #include "ttystate.h"
  23. #include "util.h"
  24.  
  25.  
  26. #ifdef SGTTY
  27. struct sgttyb    sg[2];
  28. #endif
  29.  
  30. #ifdef TERMIO
  31. struct termio    sg[2];
  32. #endif
  33.  
  34. #ifdef TERMIOS
  35. struct termios    sg[2];
  36. #endif
  37.  
  38. #ifdef USE_TIOCSLTC
  39. struct ltchars    ls[2];
  40. #endif /* USE_TIOCSLTC */
  41.  
  42. #ifdef SGTTY
  43.  
  44. # ifdef TIOCGETC
  45. struct tchars    tc[2];
  46. # endif
  47.  
  48. # ifdef LPASS8    /* use 4.3BSD's LPASS8 instead of raw for meta-key */
  49. int    lmword[2];        /* local mode word */
  50. # endif
  51.  
  52. #endif /* SGTTY */
  53.  
  54.  
  55. /* Set tty to original (if !n) or JOVE (if n) modes.
  56.  * This is designed to be idempotent: it can be called
  57.  * several times with the same argument without damage.
  58.  */
  59.  
  60. bool    OKXonXoff = NO;    /* VAR: XON/XOFF can be used as ordinary chars */
  61. ZXchar    IntChar = CTL(']');    /* VAR: ttysetattr sets this to generate SIGINT */
  62.  
  63. #ifdef BIFF
  64. bool    DisBiff = NO;        /* VAR: turn off/on biff with entering/exiting jove */
  65. #endif /* BIFF */
  66.  
  67. void
  68. ttysetattr(n)
  69. bool    n;    /* also used as subscript! */
  70. {
  71.     static bool    prev_n = NO;
  72.  
  73.     if (!prev_n) {
  74.         /* Previously, the tty was not in JOVE mode.
  75.          * Find out the current settings:
  76.          * do the ioctls or whatever to fill in NO half
  77.          * of each appropriate tty state pair.
  78.          * NOTE: the nested tangle of ifdefs is intended to follow
  79.          * the structure of the definitions in ttystate.c.
  80.          */
  81. #ifdef SGTTY
  82.         (void) gtty(0, &sg[NO]);
  83. #endif
  84.  
  85. #ifdef TERMIO
  86.         (void) ioctl(0, TCGETA, (UnivPtr) &sg[NO]);
  87. #endif
  88.  
  89. #ifdef TERMIOS
  90.         (void) tcgetattr(0, &sg[NO]);
  91. #endif
  92.  
  93. #ifdef USE_TIOCSLTC
  94.         (void) ioctl(0, TIOCGLTC, (UnivPtr) &ls[NO]);
  95. #endif /* USE_TIOCSLTC */
  96.  
  97. #ifdef SGTTY
  98.  
  99. # ifdef TIOCGETC
  100.         (void) ioctl(0, TIOCGETC, (UnivPtr) &tc[NO]);
  101. # endif
  102.  
  103. # ifdef LPASS8    /* use 4.3BSD's LPASS8 instead of raw for meta-key */
  104.         (void) ioctl(0, TIOCLGET, (UnivPtr) &lmword[NO]);
  105. # endif
  106.  
  107. #endif /* SGTTY */
  108.  
  109. /* extract some info from results */
  110.  
  111. #if defined(TERMIO) || defined(TERMIOS)
  112. # ifdef TAB3
  113.         TABS = (sg[NO].c_oflag & TABDLY) != TAB3;
  114. # endif
  115. # ifdef TERMIOS
  116.         ospeed = cfgetospeed(&sg[NO]);
  117. # else /* ! TERMIOS */
  118. #  ifdef CBAUD
  119.         ospeed = sg[NO].c_cflag & CBAUD;
  120. #  else /* ! CBAUD */
  121.         ospeed = B9600;    /* XXX */
  122. #  endif /* CBAUD */
  123. # endif /* TERMIOS */
  124. #endif /* defined(TERMIO) || defined(TERMIOS) */
  125.  
  126. #ifdef SGTTY
  127.         TABS = !(sg[NO].sg_flags & XTABS);
  128.         ospeed = sg[NO].sg_ospeed;
  129. #endif /* SGTTY */
  130.     }
  131.  
  132.     /* Fill in YES half of each appropriate tty state pair.
  133.      * They are filled in as late as possible so that each will
  134.      * reflect the latest settings of controling variables.
  135.      * NOTE: the nested tangle of ifdefs is intended to follow
  136.      * the structure of the definitions in ttystate.c.
  137.      */
  138.  
  139.     sg[YES] = sg[NO];
  140.  
  141. #ifdef SGTTY
  142.     sg[YES].sg_flags &= ~(XTABS|ECHO|CRMOD);
  143. # ifdef LPASS8
  144.     sg[YES].sg_flags |= CBREAK;
  145. # else
  146.     sg[YES].sg_flags |= (MetaKey ? RAW : CBREAK);
  147. # endif
  148. #endif
  149.  
  150. #if defined(TERMIO) || defined(TERMIOS)
  151.     if (OKXonXoff)
  152.         sg[YES].c_iflag &= ~(IXON | IXOFF);
  153.     sg[YES].c_iflag &= ~(INLCR|ICRNL|IGNCR | (MetaKey? ISTRIP : 0));
  154.     sg[YES].c_lflag &= ~(ICANON|ECHO);
  155.     sg[YES].c_oflag &= ~(OPOST);
  156.  
  157.     /* Set all those c_cc elements that we must.
  158.      * For peculiar systems, one might wish to predefine JVDISABLE
  159.      * in the configuration.  For example, on some unnamed
  160.      * versions of the Convex OS, it would be good to
  161.      * define it as (sg[YES].c_cc[VDISABLE]), saving a system call.
  162.      * Note that the only uses of JDISABLE are in this block,
  163.      * so the macro may safely refer to things in this context.
  164.      */
  165.     {
  166. # ifndef JVDISABLE
  167. #  ifdef _POSIX_VDISABLE
  168. #   define JVDISABLE    _POSIX_VDISABLE
  169. #  else /* !_POSIX_VDISABLE */
  170. #   ifdef _PC_VDISABLE
  171.         /* Cache the result of fpathconf to reduce the number of syscalls.
  172.          * We don't handle the error return (-1) because there isn't
  173.          * anything better to do with it.
  174.          */
  175.         cc_t    jvd = fpathconf(0, _PC_VDISABLE);
  176. #    define JVDISABLE    jvd
  177. #   else /* !_PC_VDISABLE */
  178. #    define JVDISABLE    0
  179. #   endif /* !_PC_VDISABLE */
  180. #  endif /* !_POSIX_VDISABLE */
  181. # endif /* JVDISABLE */
  182.  
  183.         sg[YES].c_cc[VINTR] = IntChar;
  184.  
  185. # ifdef VQUIT
  186.         sg[YES].c_cc[VQUIT] = JVDISABLE;
  187. # endif
  188.         /* VERASE, VKILL, VEOL2 irrelevant */
  189.         /* Beware aliasing! VMIN is VEOF and VTIME is VEOL */
  190. # ifdef VSWTCH
  191.         sg[YES].c_cc[VSWTCH] = JVDISABLE;
  192. # endif
  193.  
  194.         /* Under at least one system (SunOS 4.0), <termio.h>
  195.          * mistakenly defines the extra V symbols of <termios.h>
  196.          * without extending the c_cc array in struct termio
  197.          * to hold them!  This is why the following goo is doubly
  198.          * ifdefed.  It turns out that we don't use <termio.h>
  199.          * on SunOS 4.0, so the problem may be moot.
  200.          */
  201.  
  202. # ifdef TERMIOS
  203. #  ifdef VSUSP
  204.         sg[YES].c_cc[VSUSP] = JVDISABLE;
  205. #  endif
  206. #  ifdef VDSUSP
  207.         sg[YES].c_cc[VDSUSP] = JVDISABLE;
  208. #  endif
  209. #  ifdef VDISCARD
  210.         /* ??? Under Solaris 2.1 needs VDISCARD disabled, or it will
  211.          * be processed by the tty driver, but not under SysVR4!
  212.          */
  213.         sg[YES].c_cc[VDISCARD] = JVDISABLE;    /* flush output */
  214. #  endif
  215. #  ifdef VLNEXT
  216.         sg[YES].c_cc[VLNEXT] = JVDISABLE;    /* literal next char */
  217. #  endif
  218. # endif /* TERMIOS */
  219.  
  220.         sg[YES].c_cc[VMIN] = 1;
  221.         sg[YES].c_cc[VTIME] = 1;
  222.     }
  223. #endif /* defined(TERMIO) || defined(TERMIOS) */
  224.  
  225. #ifdef USE_TIOCSLTC
  226.     ls[YES] = ls[NO];
  227.     ls[YES].t_suspc = (char) -1;
  228.     ls[YES].t_dsuspc = (char) -1;
  229.     ls[YES].t_flushc = (char) -1;
  230.     ls[YES].t_lnextc = (char) -1;
  231. #endif /* USE_TIOCSLTC */
  232.  
  233. #ifdef SGTTY
  234.  
  235. # ifdef TIOCGETC
  236.     tc[YES] = tc[NO];
  237.     tc[YES].t_intrc = IntChar;
  238.     tc[YES].t_quitc = (char) -1;
  239.     if (OKXonXoff) {
  240.         tc[YES].t_stopc = (char) -1;
  241.         tc[YES].t_startc = (char) -1;
  242.     }
  243. # endif
  244.  
  245. # ifdef LPASS8    /* use 4.3BSD's LPASS8 instead of raw for meta-key */
  246.     lmword[YES] = lmword[NO];
  247.  
  248.     if (MetaKey)
  249.         lmword[YES] |= LPASS8;
  250.  
  251. #  ifdef LLITOUT
  252.     /* ??? under what conditions should we turn on LLITOUT flag? */
  253. #  endif /* LLITOUT */
  254.  
  255. #  ifdef LTILDE
  256.     if (Hazeltine)
  257.         lmword[YES] &= ~LTILDE;
  258. #  endif /* LTILDE */
  259.  
  260. # endif /* LPASS8 */
  261.  
  262. #endif /* SGTTY */
  263.  
  264.     /* Set tty state according to appropriate entry of each state pair.
  265.      * NOTE: the nested tangle of ifdefs is intended to follow
  266.      * the structure of the definitions in ttystate.c.
  267.      */
  268.  
  269. #ifdef SGTTY
  270. #  ifdef TIOCSETN
  271.     (void) ioctl(0, TIOCSETN, (UnivPtr) &sg[n]);
  272. #  else
  273.     (void) stty(0, &sg[n]);
  274. #  endif
  275. #endif
  276.  
  277. #ifdef TERMIO
  278.     do ; while (ioctl(0, TCSETAW, (UnivPtr) &sg[n]) < 0 && errno == EINTR);
  279. #endif
  280.  
  281. #ifdef TERMIOS
  282.     do ; while (tcsetattr(0, TCSADRAIN, &sg[n]) < 0 && errno == EINTR);
  283. #endif
  284.  
  285. #ifdef USE_TIOCSLTC
  286.     (void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[n]);
  287. #endif /* USE_TIOCSLTC */
  288.  
  289. #ifdef SGTTY
  290.  
  291. # ifdef TIOCGETC
  292.     (void) ioctl(0, TIOCSETC, (UnivPtr) &tc[n]);
  293. # endif
  294.  
  295. # ifdef LPASS8    /* use 4.3BSD's LPASS8 instead of raw for meta-key */
  296.     (void) ioctl(0, TIOCLSET, (UnivPtr) &lmword[n]);    /* local mode word */
  297. # endif
  298.  
  299. #endif /* SGTTY */
  300.  
  301. #ifdef BIFF
  302.  
  303.     /* biff state is an honorary part of the tty state.
  304.      * On the other hand, it is different from the rest of the state
  305.      * since we only want to examine the setting if DisBiff
  306.      * has been set by the user.  For this reason, the code is
  307.      * somewhat more intricate.
  308.      */
  309.     {
  310. #        define BS_UNEXAMINED    0    /* we don't know if biff is enabled */
  311. #        define BS_DISABLED    1    /* we have disabled biff */
  312. #        define BS_UNCHANGED    2    /* we didn't disable biff */
  313.         static int    biff_state = BS_UNEXAMINED;
  314.  
  315.         static struct stat    tt_stat;
  316. # if !defined(USE_FSTAT) || !defined(USE_FCHMOD)
  317.         static char    *tt_name = NULL;    /* name of the control tty */
  318.         extern char    *ttyname proto((int));    /* for systems w/o fstat */
  319. # endif
  320.  
  321.         if (n && DisBiff) {
  322.             /* biff supression is our business */
  323.             if (biff_state == BS_UNEXAMINED) {
  324.                 /* and we haven't looked after it */
  325.                 biff_state = BS_UNCHANGED;    /* at least so far */
  326.                 if (
  327. # ifdef USE_FSTAT
  328.                     fstat(0, &tt_stat) != -1
  329. # else
  330.                     ((tt_name != NULL) || (tt_name = ttyname(0)) != NULL)
  331.                     && stat(tt_name, &tt_stat) != -1
  332. # endif
  333.                 && (tt_stat.st_mode & S_IEXEC))
  334.                 {
  335.                     /* so let's suppress it */
  336. # ifdef USE_FCHMOD
  337.                     (void) fchmod(0, tt_stat.st_mode & ~S_IEXEC);
  338.                     biff_state = BS_DISABLED;
  339. # else
  340.                     if ((tt_name != NULL || (tt_name = ttyname(0)) != NULL)
  341.                     && chmod(tt_name, tt_stat.st_mode & ~S_IEXEC) != -1)
  342.                     {
  343.                         /* Note: only change biff_state if we were able to
  344.                          * get the tt_name -- this prevents the other
  345.                          * chmod from blowing up.
  346.                          */
  347.                         biff_state = BS_DISABLED;
  348.                     }
  349. # endif
  350.                 }
  351.             }
  352.         } else {
  353.             /* any biff suppression should be undone */
  354.             if (biff_state == BS_DISABLED) {
  355.                 /* and we did suppress it, so we enable it */
  356. # ifdef USE_FCHMOD
  357.                 (void) fchmod(0, tt_stat.st_mode);
  358. # else
  359.                 (void) chmod(tt_name, tt_stat.st_mode);
  360. # endif
  361.             }
  362.             biff_state = BS_UNEXAMINED;    /* it's out of our hands */
  363.         }
  364. #        undef BS_UNEXAMINED
  365. #        undef BS_DISABLED
  366. #        undef BS_UNCHANGED
  367.     }
  368.  
  369. #endif /* BIFF */
  370.     prev_n = n;
  371. }
  372.  
  373. /* Determine the number of characters to buffer at each baud rate.  The
  374.    lower the number, the quicker the response when new input arrives.  Of
  375.    course the lower the number, the more prone the program is to stop in
  376.    output.  Decide what matters most to you. This sets ScrBufSize to the right
  377.    number or chars, and initializes `jstdout'.  */
  378.  
  379. void
  380. settout()
  381. {
  382.     int    speed_chars;
  383.  
  384.     static const struct {
  385.         unsigned int bsize;
  386.         unsigned int brate;
  387.     } speeds[] = {
  388.  
  389. #ifdef B0
  390.         { 1, B0 },
  391. #endif
  392. #ifdef B50
  393.         { 1, B50 },
  394. #endif
  395. #ifdef B75
  396.         { 1, B75 },
  397. #endif
  398. #ifdef B110
  399.         { 1, B110 },
  400. #endif
  401. #ifdef B134
  402.         { 1, B134 },
  403. #endif
  404. #ifdef B150
  405.         { 1, B150 },
  406. #endif
  407. #ifdef B200
  408.         { 1, B200 },
  409. #endif
  410. #ifdef B300
  411.         { 2, B300 },
  412. #endif
  413. #ifdef B600
  414.         { 4, B600 },
  415. #endif
  416. #ifdef B900
  417.         { 6, B900 },
  418. #endif
  419. #ifdef B1200
  420.         { 8, B1200 },
  421. #endif
  422. #ifdef B1800
  423.         { 16, B1800 },
  424. #endif
  425. #ifdef B2400
  426.         { 32, B2400 },
  427. #endif
  428. #ifdef B3600
  429.         { 64, B3600 },
  430. #endif
  431. #ifdef B4800
  432.         { 128, B4800 },
  433. #endif
  434. #ifdef B7200
  435.         { 256, B7200 },
  436. #endif
  437. #ifdef B9600
  438.         { 256, B9600 },
  439. #endif
  440. #ifdef EXTA
  441.         { 512, EXTA },
  442. #endif
  443. #ifdef B19200
  444.         { 512, B19200 },
  445. #endif
  446. #ifdef EXTB
  447.         { 1024, EXTB },
  448. #endif
  449. #ifdef B38400
  450.         { 1024, B38400 },
  451. #endif
  452. #ifdef EXT
  453.         { 1024, EXT }
  454. #endif
  455. };
  456.     int i;
  457.     for (i = 0; ; i++) {
  458.         if (i == elemsof(speeds)) {
  459.             speed_chars = 512;
  460.             ospeed = B9600;    /* XXX */
  461.             break;
  462.         }
  463.         if (speeds[i].brate == (unsigned short) ospeed) {
  464.             speed_chars = speeds[i].bsize;
  465.             break;
  466.         }
  467.     }
  468.  
  469.     flushscreen();        /* flush the one character buffer */
  470.     ScrBufSize = min(MAXTTYBUF, speed_chars * max(LI / 24, 1));
  471. #ifndef NO_JSTDOUT
  472.     jstdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, (char *)NULL, ScrBufSize);
  473. #endif
  474. }
  475.  
  476. void
  477. ttsize()
  478. {
  479.     /* ??? We really ought to wait until the screen is big enough:
  480.      * at least three lines high (one line each for buffer, mode,
  481.      * and message) and at least twelve columns wide (eight for
  482.      * line number, one for content, two for overflow indicators,
  483.      * and one blank at end).
  484.      */
  485. #ifdef TIOCGWINSZ
  486.     struct winsize win;
  487.  
  488.     if (ioctl(0, TIOCGWINSZ, (UnivPtr) &win) == 0
  489.     && win.ws_col >= 12
  490.     && win.ws_row >= 3)
  491.     {
  492.         CO = min(win.ws_col, MAXCOLS);
  493.         LI = win.ws_row;
  494.     }
  495. #else /* !TIOCGWINSZ */
  496. # ifdef BTL_BLIT
  497.     struct jwinsize jwin;
  498.  
  499.     if (ioctl(0, JWINSIZE, (UnivPtr) &jwin) == 0
  500.     && jwin.bytesx >= 12
  501.     && jwin.bytesy >= 3)
  502.     {
  503.         CO = min(jwin.bytesx, MAXCOLS);
  504.         LI = jwin.bytesy;
  505.     }
  506. # endif /* BTL_BLIT */
  507. #endif /* !TIOCGWINSZ */
  508.     ILI = LI - 1;
  509. }
  510.  
  511. #endif /* UNIX */
  512.