home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode:Text -*- */
- #ifndef lint
- static char Rcs_Id[] =
- "$Id: term.c,v 1.37 1991/12/09 00:40:48 geoff Exp $";
- #endif
-
- /*
- * term.c - deal with termcap, and unix terminal mode settings
- *
- * Pace Willisson, 1983
- *
- * Copyright 1987, 1988, 1989, by Geoff Kuenning, Manhattan Beach, CA
- * Permission for non-profit use is hereby granted.
- * All other rights reserved.
- * See "version.h" for a more complete copyright notice.
- */
-
- /*
- * $Log: term.c,v $
- * Revision 1.37 1991/12/09 00:40:48 geoff
- * Don't unlink the tempfile on exit if it has a null name.
- *
- * Revision 1.36 91/09/04 18:00:57 geoff
- * Move the include of config.h. Since it now contains the definition of
- * USG, it must precede any use of that option.
- *
- * Revision 1.35 91/07/27 20:48:37 geoff
- * Don't obey the screen size from TIOCGWINSZ if it's zero or negative.
- *
- * Revision 1.34 91/07/11 19:52:24 geoff
- * Remove the include of stdio.h, since ispell.h now does this. Change
- * the termination code to put out the te sequence, rather than ti.
- *
- * Revision 1.33 91/07/05 19:51:55 geoff
- * Fix some lint complaints, including getting rid of a couple of unused
- * variables.
- *
- * Revision 1.32 91/07/03 18:21:09 geoff
- * Add code to support the "ti" and "te" termcap sequences, since the Sun
- * cmdtool (or is it shelltool) needs it to function properly with ispell.
- *
- * Revision 1.31 90/12/31 00:59:29 geoff
- * Reformat to follow a consistent convention throughout ispell
- *
- * Revision 1.30 90/04/26 22:44:25 geoff
- * If it is available, use the TIOCGWINSZ ioctl to determine the dimensions
- * of the terminal. The enviroment variables LINES and COLUMNS can still
- * be used to override this ioctl.
- *
- * Revision 1.29 90/04/17 15:35:07 geoff
- * Declare the signal-handling routines to be SIGNAL_TYPE
- *
- * Revision 1.28 89/12/27 03:18:43 geoff
- * Move all messages to msgs.h so they can be reconfigured
- *
- * Revision 1.27 89/12/26 23:26:32 geoff
- * Change the signal type to be definable (Israel Pinkas).
- *
- * Revision 1.26 89/04/28 01:17:17 geoff
- * Change Header to Id; nobody cares about my pathnames.
- *
- * Revision 1.25 89/04/03 01:58:34 geoff
- * Fix a bunch of lint complaints. Add code to let LINES and COLUMNS
- * override the screen size given by the termcap entry. Rearrange some
- * code so that signal-catching and terminal setting is done only after
- * we are sure the termcap entry is ok.
- *
- * Revision 1.24 89/02/27 02:23:48 geoff
- * Fix the interpretation of CONTEXTROUNDUP (it was inverted from what
- * the comments in config.X said).
- *
- * Revision 1.23 89/02/22 23:16:43 geoff
- * Add support for calculating "contextsize" based on the terminal size.
- *
- * Revision 1.22 89/01/06 00:14:47 geoff
- * Add support for MAX_SCREEN_SIZE (Keith Cantrell).
- *
- * Revision 1.21 88/12/26 02:32:39 geoff
- * Add a copyright notice.
- *
- * Revision 1.20 88/11/16 02:20:35 geoff
- * Make sure "tpgrp" is defined if TIOCGPGRP is defined but not TIOCPGRP
- * (a Locus-ism).
- *
- * Revision 1.19 88/10/20 20:53:09 geoff
- * If a shell escape fails, don't flush stdio buffers on exit from the child.
- * (Ole Bjoern Hessen).
- *
- * Revision 1.18 88/04/30 22:15:45 geoff
- * Fix some lint complaints, and get rid of some unused variables found
- * by lint.
- *
- * Revision 1.17 88/03/27 01:05:19 geoff
- * Fix the #ifdefs to handle USG-like systems that nevertheless have job
- * control.
- *
- * Revision 1.16 87/09/03 23:17:42 geoff
- * Integrate George Sipe's latest changes: make ^Z spawn a shell on USG.
- * Add the shellescape() routine to handle simple shell commands faster.
- * Also clean up signal handling a bit.
- *
- * Revision 1.15 87/09/03 17:32:29 geoff
- * Add ifdefs to make it compile on V7
- *
- * Revision 1.14 87/09/03 17:09:09 geoff
- * Catch signals on USG systems, too (imt3b2!imtsft)
- *
- * Revision 1.13 87/06/27 12:20:54 geoff
- * Get the sg termcap value for braindamaged terminals (Michael Wester).
- *
- * Revision 1.12 87/06/07 14:31:12 geoff
- * Integrate Joel Shprentz's changes into the main branch
- *
- * Revision 1.11 87/05/25 21:24:34 geoff
- * Integrate Mark Davies' changes, and improve some signal catching code.
- *
- * Revision 1.10 87/04/21 23:29:20 geoff
- * Only catch signals if they aren't ignored; this makes background stuff
- * work properly.
- *
- * Revision 1.9 87/04/19 22:53:44 geoff
- * Swap the includes of ispell.h and config.h so config.h can affect ispell.h.
- *
- * Revision 1.8 87/04/02 12:26:10 geoff
- * Make stdout buffered.
- *
- * Revision 1.7 87/04/01 15:22:58 geoff
- * Integrate Joe Orost's V7/register changes into the main branch
- *
- * Revision 1.6 87/03/22 23:21:44 geoff
- * Integrate Perry Smith's changes into the main branch
- *
- * Revision 1.5 87/02/26 00:22:48 geoff
- * Integrate McQueer's and McMahon's enhancements into the main branch
- *
- * Revision 1.4 87/01/19 00:25:19 geoff
- * Prohibit non-interactive use on USG systems too
- *
- * Revision 1.3 87/01/19 00:07:00 geoff
- * Modify to work on USG systems.
- *
- * Revision 1.2 87/01/17 13:12:11 geoff
- * Add RCS ID keywords
- *
- */
-
- #include "config.h"
- #ifdef USG
- #include <termio.h>
- #else
- #include <sgtty.h>
- #endif
- #include <signal.h>
- #include <stdio.h>
- #include "ispell.h"
- #include "msgs.h"
-
- extern char * tgoto ();
-
- extern void exit ();
- extern void _exit ();
- extern char * getenv ();
-
- int putch();
-
- erase ()
- {
-
- if (cl)
- tputs (cl, li, putch);
- else
- {
- if (ho)
- tputs (ho, 100, putch);
- else if (cm)
- tputs (tgoto (cm, 0, 0), 100, putch);
- tputs (cd, li, putch);
- }
- }
-
- move (row, col)
- {
- tputs (tgoto (cm, col, row), 100, putch);
- }
-
- inverse ()
- {
- tputs (so, 10, putch);
- }
-
- normal ()
- {
- tputs (se, 10, putch);
- }
-
- backup ()
- {
- if (BC)
- tputs (BC, 1, putch);
- else
- (void) putchar ('\b');
- }
-
- putch (c)
- {
- (void) putchar (c);
- }
-
- #ifdef USG
- struct termio sbuf;
- struct termio osbuf;
- #else
- struct sgttyb sbuf;
- struct sgttyb osbuf;
- #ifdef TIOCSLTC
- struct ltchars ltc;
- struct ltchars oltc;
- #endif
- #endif
- static int termchanged = 0;
- static SIGNAL_TYPE (*oldint) ();
- static SIGNAL_TYPE (*oldterm) ();
- #ifdef SIGTSTP
- static SIGNAL_TYPE (*oldttin) ();
- static SIGNAL_TYPE (*oldttou) ();
- static SIGNAL_TYPE (*oldtstp) ();
- #endif
-
- terminit ()
- {
- #ifdef OS2
- int dst[2];
- int tgstat;
- #endif /* OS2 */
- #ifdef TIOCPGRP
- int tpgrp;
- #else
- #ifdef TIOCGPGRP
- int tpgrp;
- #endif
- #endif
- #ifdef SIGTSTP
- SIGNAL_TYPE onstop ();
- #endif
- #ifdef TIOCGWINSZ
- struct winsize wsize;
- #endif /* TIOCGWINSZ */
-
- #ifdef OS2 /* check if termcap.dat is found and TERM is valid */
- if ( (tgstat = tgetent (termcap, getenv ("TERM") ) ) == -1 )
- {
- (void) fprintf (stderr, TERM_C_NO_TERMCAP);
- exit();
- }
- else if (tgstat == 0)
- {
- (void) fprintf (stderr, TERM_C_INVALID_TERM, getenv ("TERM"));
- exit();
- }
- #else
- tgetent (termcap, getenv ("TERM"));
- #endif /* OS2 */
- termptr = termstr;
- BC = tgetstr ("bc", &termptr);
- cd = tgetstr ("cd", &termptr);
- cl = tgetstr ("cl", &termptr);
- cm = tgetstr ("cm", &termptr);
- ho = tgetstr ("ho", &termptr);
- nd = tgetstr ("nd", &termptr);
- so = tgetstr ("so", &termptr); /* inverse video on */
- se = tgetstr ("se", &termptr); /* inverse video off */
- if ((sg = tgetnum ("sg")) < 0) /* space taken by so/se */
- sg = 0;
- ti = tgetstr ("ti", &termptr); /* terminal initialization */
- te = tgetstr ("te", &termptr); /* terminal termination */
- co = tgetnum ("co");
- li = tgetnum ("li");
- #ifdef TIOCGWINSZ
- if (ioctl (0, TIOCGWINSZ, &wsize) >= 0)
- {
- if (wsize.ws_col > 0)
- co = wsize.ws_col;
- if (wsize.ws_row > 0)
- li = wsize.ws_row;
- }
- #endif /* TIOCGWINSZ */
-
- #ifdef OS2 /* get the OS/2 window size */
- _scrsize(dst);
- co = dst[0];
- li = dst[1];
- #endif /* OS2 */
-
-
- /*
- * Let the variables "LINES" and "COLUMNS" override the termcap
- * entry. Technically, this is a terminfo-ism, but I think the
- * vast majority of users will find it pretty handy.
- */
- if (getenv ("COLUMNS") != NULL)
- co = atoi (getenv ("COLUMNS"));
- if (getenv ("LINES") != NULL)
- li = atoi (getenv ("LINES"));
- #if MAX_SCREEN_SIZE > 0
- if (li > MAX_SCREEN_SIZE)
- li = MAX_SCREEN_SIZE;
- #endif /* MAX_SCREEN_SIZE > 0 */
- #if MAXCONTEXT == MINCONTEXT
- contextsize = MINCONTEXT;
- #else /* MAXCONTEXT == MINCONTEXT */
- if (contextsize == 0)
- #ifdef CONTEXTROUNDUP
- contextsize = (li * CONTEXTPCT + 99) / 100;
- #else /* CONTEXTROUNDUP */
- contextsize = (li * CONTEXTPCT) / 100;
- #endif /* CONTEXTROUNDUP */
- if (contextsize > MAXCONTEXT)
- contextsize = MAXCONTEXT;
- else if (contextsize < MINCONTEXT)
- contextsize = MINCONTEXT;
- #endif /* MAX_CONTEXT == MIN_CONTEXT */
- /*
- * Insist on 2 lines for the screen header, 2 for blank lines
- * separating areas of the screen, 2 for word choices, and 2 for
- * the minimenu, plus however many are needed for context. If
- * possible, make the context smaller to fit on the screen.
- */
- if (li < contextsize + 8 && contextsize > MINCONTEXT)
- {
- contextsize = li - 8;
- if (contextsize < MINCONTEXT)
- contextsize = MINCONTEXT;
- }
- if (li < MINCONTEXT + 8)
- (void) fprintf (stderr, TERM_C_SMALL_SCREEN, MINCONTEXT + 8);
-
- #ifdef SIGTSTP
- #ifdef TIOCPGRP
- retry:
- #endif /* SIGTSTP */
- #endif /* TIOCPGRP */
-
- #ifdef USG
- if (!isatty (0))
- {
- (void) fprintf (stderr, TERM_C_NO_BATCH);
- exit (1);
- }
- (void) ioctl (0, TCGETA, &osbuf);
- termchanged = 1;
-
- sbuf = osbuf;
- #ifdef OS2 /* IDEFAULT added for os/2 -- jbh 8/15/92 */
- sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON | IDEFAULT);
- #else
- sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON);
- #endif /* OS2 */
-
- sbuf.c_oflag &= ~(OPOST);
- sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL);
- sbuf.c_cc[VMIN] = 1;
- sbuf.c_cc[VTIME] = 1;
- (void) ioctl (0, TCSETAW, &sbuf);
-
- erasechar = osbuf.c_cc[VERASE];
- killchar = osbuf.c_cc[VKILL];
-
- #endif
-
- #ifdef SIGTSTP
- #ifndef USG
- (void) sigsetmask (1<<(SIGTSTP-1) | 1<<(SIGTTIN-1) | 1<<(SIGTTOU-1));
- #endif
- #endif
- #ifdef TIOCGPGRP
- if (ioctl (0, TIOCGPGRP, &tpgrp) != 0)
- {
- (void) fprintf (stderr, TERM_C_NO_BATCH);
- exit (1);
- }
- #endif
- #ifdef SIGTSTP
- #ifdef TIOCPGRP
- if (tpgrp != getpgrp(0)) /* not in foreground */
- {
- #ifndef USG
- (void) sigsetmask (1 << (SIGTSTP - 1) | 1 << (SIGTTIN - 1));
- #endif
- (void) signal (SIGTTOU, SIG_DFL);
- (void) kill (0, SIGTTOU);
- /* job stops here waiting for SIGCONT */
- goto retry;
- }
- #endif
- #endif
-
- #ifndef USG
- (void) ioctl (0, TIOCGETP, &osbuf);
- #ifdef TIOCGLTC
- (void) ioctl (0, TIOCGLTC, &oltc);
- #endif
- termchanged = 1;
-
- sbuf = osbuf;
- sbuf.sg_flags &= ~ECHO;
- sbuf.sg_flags |= TERM_MODE;
- (void) ioctl (0, TIOCSETP, &sbuf);
-
- erasechar = sbuf.sg_erase;
- killchar = sbuf.sg_kill;
-
- #ifdef TIOCSLTC
- ltc = oltc;
- ltc.t_suspc = -1;
- (void) ioctl (0, TIOCSLTC, <c);
- #endif
-
- #endif /* USG */
-
- if ((oldint = signal (SIGINT, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGINT, done);
- if ((oldterm = signal (SIGTERM, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTERM, done);
-
- #ifdef SIGTSTP
- #ifndef USG
- (void) sigsetmask (0);
- #endif
- if ((oldttin = signal (SIGTTIN, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTTIN, onstop);
- if ((oldttou = signal (SIGTTOU, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTTOU, onstop);
- if ((oldtstp = signal (SIGTSTP, SIG_IGN)) != SIG_IGN)
- (void) signal (SIGTSTP, onstop);
- #endif
- if (ti)
- tputs (ti, 1, putch);
- }
-
- SIGNAL_TYPE done ()
- {
- if (tempfile[0] != '\0')
- #ifdef OS2
- {
- fcloseall(); /* OS/2 won't unlink an open file */
- (void) unlink (tempfile);
- }
- #else /* OS2 */
- (void) unlink (tempfile);
- #endif /* OS2 */
-
- if (termchanged)
- {
- if (te)
- tputs (te, 1, putch);
- #ifdef USG
- (void) ioctl (0, TCSETAW, &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, &oltc);
- #endif
- #endif
- }
- #ifdef OS2 /* returns screen to the original color */
- erase ();
- #endif /* OS2 */
- exit (0);
- }
-
- #ifdef SIGTSTP
- SIGNAL_TYPE onstop (signo)
- int signo;
- {
- #ifdef USG
- (void) ioctl (0, TCSETAW, &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, &oltc);
- #endif
- #endif
- (void) signal (signo, SIG_DFL);
- #ifndef USG
- (void) sigsetmask (sigblock (0) & ~(1 << (signo - 1)));
- #endif
- (void) kill (0, signo);
- /* stop here until continued */
- (void) signal (signo, onstop);
- #ifdef USG
- (void) ioctl (0, TCSETAW, &sbuf);
- #else
- (void) ioctl (0, TIOCSETP, &sbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, <c);
- #endif
- #endif
- }
- #endif
-
- stop ()
- {
- #ifdef SIGTSTP
- onstop (SIGTSTP);
- #else
- /* for System V */
- move (li - 1, 0);
- (void) fflush (stdout);
- if (getenv ("SHELL"))
- (void) shellescape (getenv ("SHELL"));
- else
- (void) shellescape ("sh");
- #endif
- }
-
- /* Fork and exec a process. Returns NZ if command found, regardless of
- ** command's return status. Returns zero if command was not found.
- ** Doesn't use a shell.
- */
- int shellescape (buf)
- char * buf;
- {
- char * argv[100];
- char * cp = buf;
- int i = 0;
- int termstat;
-
- /* parse buf to args (destroying it in the process) */
- while (*cp != '\0')
- {
- while (*cp == ' ' || *cp == '\t')
- ++cp;
- if (*cp == '\0')
- break;
- argv[i++] = cp;
- while (*cp != ' ' && *cp != '\t' && *cp != '\0')
- ++cp;
- if (*cp != '\0')
- *cp++ = '\0';
- }
- argv[i] = NULL;
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, &osbuf);
- (void) ioctl (0, TIOCSLTC, &oltc);
- #endif
- (void) signal (SIGINT, oldint);
- (void) signal (SIGTERM, oldterm);
- #ifdef SIGTSTP
- (void) signal (SIGTTIN, oldttin);
- (void) signal (SIGTTOU, oldttou);
- (void) signal (SIGTSTP, oldtstp);
- #endif
-
- /* ifdef OS2 no fork available under OS/2 - needs to be rewritted */
- /* (void) printf(TERM_C_NO_FORK); */
- /* else */
- if ((i = fork ()) == 0)
- {
- (void) execvp (argv[0], argv);
- _exit (123); /* Command not found */
- }
- else if (i > 0)
- {
- while (wait (&termstat) != i)
- ;
- termstat = (termstat == (123 << 8)) ? 0 : -1;
- }
- else
- {
- (void) printf (TERM_C_CANT_FORK);
- termstat = -1; /* Couldn't fork */
- }
-
- /* endif OS2 */
-
-
- if (oldint != SIG_IGN)
- (void) signal (SIGINT, done);
- if (oldterm != SIG_IGN)
- (void) signal (SIGTERM, done);
-
- #ifdef SIGTSTP
- if (oldttin != SIG_IGN)
- (void) signal (SIGTTIN, onstop);
- if (oldttou != SIG_IGN)
- (void) signal (SIGTTOU, onstop);
- if (oldtstp != SIG_IGN)
- (void) signal (SIGTSTP, onstop);
- #endif
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, &sbuf);
- #else
- (void) ioctl (0, TIOCSETP, &sbuf);
- (void) ioctl (0, TIOCSLTC, <c);
- #endif
- if (termstat)
- {
- (void) printf (TERM_C_TYPE_SPACE);
- (void) fflush (stdout);
- #ifdef COMMANDFORSPACE
- i = getchar ();
- if (i != ' ' && i != '\n' && i != '\r')
- ungetc (i, stdin);
- #else
- while (getchar () != ' ')
- ;
- #endif
- }
- return (termstat);
- }
-
- #ifdef USESH
- shescape (buf)
- char * buf;
- {
- #ifdef COMMANDFORSPACE
- int ch;
- #endif
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, &osbuf);
- #else
- (void) ioctl (0, TIOCSETP, &osbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, &oltc);
- #endif
- #endif
- (void) signal (SIGINT, oldint);
- (void) signal (SIGTERM, oldterm);
- #ifdef SIGTSTP
- (void) signal (SIGTTIN, oldttin);
- (void) signal (SIGTTOU, oldttou);
- (void) signal (SIGTSTP, oldtstp);
- #endif
-
- (void) system (buf);
-
- if (oldint != SIG_IGN)
- (void) signal (SIGINT, done);
- if (oldterm != SIG_IGN)
- (void) signal (SIGTERM, done);
-
- #ifdef SIGTSTP
- if (oldttin != SIG_IGN)
- (void) signal (SIGTTIN, onstop);
- if (oldttou != SIG_IGN)
- (void) signal (SIGTTOU, onstop);
- if (oldtstp != SIG_IGN)
- (void) signal (SIGTSTP, onstop);
- #endif
-
- #ifdef USG
- (void) ioctl (0, TCSETAW, &sbuf);
- #else
- (void) ioctl (0, TIOCSETP, &sbuf);
- #ifdef TIOCSLTC
- (void) ioctl (0, TIOCSLTC, <c);
- #endif
- #endif
- (void) printf (TERM_C_TYPE_SPACE);
- (void) fflush (stdout);
- #ifdef COMMANDFORSPACE
- ch = getchar ();
- if (ch != ' ' && ch != '\n' && ch != '\r')
- ungetc (ch, stdin);
- #else
- while (getchar () != ' ')
- ;
- #endif
- }
- #endif
-