This is term.c in view mode; [Download] [Up]
#ifndef lint static char Rcs_Id[] = "$Id: term.c,v 1.46 1994/01/25 07:12:11 geoff Exp $"; #endif /* * term.c - deal with termcap, and unix terminal mode settings * * Pace Willisson, 1983 * * Copyright 1987, 1988, 1989, 1992, 1993, Geoff Kuenning, Granada Hills, CA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All modifications to the source code must be clearly marked as * such. Binary redistributions based on modified source code * must be clearly marked as modified versions in the documentation * and/or other materials provided with the distribution. * 4. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * This product includes software developed by Geoff Kuenning and * other unpaid contributors. * 5. The name of Geoff Kuenning may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Log: term.c,v $ * Revision 1.46 1994/01/25 07:12:11 geoff * Get rid of all old RCS log lines in preparation for the 3.1 release. * */ #include "config.h" #include "ispell.h" #include "proto.h" #include "msgs.h" #ifdef USG #include <termio.h> #else #include <sgtty.h> #endif #include <signal.h> void erase P ((void)); void move P ((int row, int col)); void inverse P ((void)); void normal P ((void)); void backup P ((void)); static int putch P ((int c)); void terminit P ((void)); SIGNAL_TYPE done P ((int signo)); #ifdef SIGTSTP static SIGNAL_TYPE onstop P ((int signo)); #endif /* SIGTSTP */ void stop P ((void)); int shellescape P ((char * buf)); #ifdef USESH void shescape P ((char * buf)); #endif /* USESH */ void 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); } } void move (row, col) int row; int col; { tputs (tgoto (cm, col, row), 100, putch); } void inverse () { tputs (so, 10, putch); } void normal () { tputs (se, 10, putch); } void backup () { if (BC) tputs (BC, 1, putch); else (void) putchar ('\b'); } static int putch (c) int c; { return putchar (c); } #ifdef USG static struct termio sbuf; static struct termio osbuf; #else static struct sgttyb sbuf; static struct sgttyb osbuf; #ifdef TIOCSLTC static struct ltchars ltc; static 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 void terminit () { #ifdef TIOCPGRP int tpgrp; #else #ifdef TIOCGPGRP int tpgrp; #endif #endif #ifdef TIOCGWINSZ struct winsize wsize; #endif /* TIOCGWINSZ */ tgetent (termcap, getenv ("TERM")); 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, (char *) &wsize) >= 0) { if (wsize.ws_col != 0) co = wsize.ws_col; if (wsize.ws_row != 0) li = wsize.ws_row; } #endif /* TIOCGWINSZ */ /* * 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, (char *) &osbuf); termchanged = 1; sbuf = osbuf; sbuf.c_lflag &= ~(ECHO | ECHOK | ECHONL | ICANON); sbuf.c_oflag &= ~(OPOST); sbuf.c_iflag &= ~(INLCR | IGNCR | ICRNL); sbuf.c_cc[VMIN] = 1; sbuf.c_cc[VTIME] = 1; (void) ioctl (0, TCSETAW, (char *) &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, (char *) &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, (char *) &osbuf); #ifdef TIOCGLTC (void) ioctl (0, TIOCGLTC, (char *) &oltc); #endif termchanged = 1; sbuf = osbuf; sbuf.sg_flags &= ~ECHO; sbuf.sg_flags |= TERM_MODE; (void) ioctl (0, TIOCSETP, (char *) &sbuf); erasechar = sbuf.sg_erase; killchar = sbuf.sg_kill; #ifdef TIOCSLTC ltc = oltc; ltc.t_suspc = -1; (void) ioctl (0, TIOCSLTC, (char *) <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); } /* ARGSUSED */ SIGNAL_TYPE done (signo) int signo; { if (tempfile[0] != '\0') (void) unlink (tempfile); if (termchanged) { if (te) tputs (te, 1, putch); #ifdef USG (void) ioctl (0, TCSETAW, (char *) &osbuf); #else (void) ioctl (0, TIOCSETP, (char *) &osbuf); #ifdef TIOCSLTC (void) ioctl (0, TIOCSLTC, (char *) &oltc); #endif #endif } exit (0); } #ifdef SIGTSTP static SIGNAL_TYPE onstop (signo) int signo; { #ifdef USG (void) ioctl (0, TCSETAW, (char *) &osbuf); #else (void) ioctl (0, TIOCSETP, (char *) &osbuf); #ifdef TIOCSLTC (void) ioctl (0, TIOCSLTC, (char *) &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, (char *) &sbuf); #else (void) ioctl (0, TIOCSETP, (char *) &sbuf); #ifdef TIOCSLTC (void) ioctl (0, TIOCSLTC, (char *) <c); #endif #endif } #endif void 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. */ #ifndef USESH #define NEED_SHELLESCAPE #endif /* USESH */ #ifndef REGEX_LOOKUP #define NEED_SHELLESCAPE #endif /* REGEX_LOOKUP */ #ifdef NEED_SHELLESCAPE 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, (char *) &osbuf); #else (void) ioctl (0, TIOCSETP, (char *) &osbuf); (void) ioctl (0, TIOCSLTC, (char *) &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 if ((i = fork ()) == 0) { (void) execvp (argv[0], (char **) 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 */ } 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, (char *) &sbuf); #else (void) ioctl (0, TIOCSETP, (char *) &sbuf); (void) ioctl (0, TIOCSLTC, (char *) <c); #endif if (termstat) { (void) printf (TERM_C_TYPE_SPACE); (void) fflush (stdout); #ifdef COMMANDFORSPACE i = GETKEYSTROKE (); if (i != ' ' && i != '\n' && i != '\r') (void) ungetc (i, stdin); #else while (GETKEYSTROKE () != ' ') ; #endif } return (termstat); } #endif /* NEED_SHELLESCAPE */ #ifdef USESH void shescape (buf) char * buf; { #ifdef COMMANDFORSPACE int ch; #endif #ifdef USG (void) ioctl (0, TCSETAW, (char *) &osbuf); #else (void) ioctl (0, TIOCSETP, (char *) &osbuf); #ifdef TIOCSLTC (void) ioctl (0, TIOCSLTC, (char *) &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, (char *) &sbuf); #else (void) ioctl (0, TIOCSETP, (char *) &sbuf); #ifdef TIOCSLTC (void) ioctl (0, TIOCSLTC, (char *) <c); #endif #endif (void) printf (TERM_C_TYPE_SPACE); (void) fflush (stdout); #ifdef COMMANDFORSPACE ch = GETKEYSTROKE (); if (ch != ' ' && ch != '\n' && ch != '\r') (void) ungetc (ch, stdin); #else while (GETKEYSTROKE () != ' ') ; #endif } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.