⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty.c

📁 举世闻名的joe记事本源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	UNIX Tty and Process interface *	Copyright *		(C) 1992 Joseph H. Allen * *	This file is part of JOE (Joe's Own Editor) */#include "types.h"#ifdef GWINSZ_IN_SYS_IOCTL#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#endif#ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifdef HAVE_OPENPTY#ifdef HAVE_PTY_H#include <pty.h>#endif#ifdef HAVE_LIBUTIL_H#include <libutil.h>#endif#endif#ifdef HAVE_LOGIN_TTY#ifdef HAVE_UTMP_H#include <utmp.h>#endif#endifint idleout = 1;#ifdef __amigaos#undef SIGTSTP#endif/* We use the defines in sys/ioctl to determine what type * tty interface the system uses and what type of system * we actually have. */#ifdef HAVE_POSIX_TERMIOS#  include <termios.h>#else#  ifdef HAVE_SYSV_TERMIO#    include <termio.h>#    include <sys/termio.h>#  else#    include <sgtty.h>#  endif#endif#ifdef HAVE_SETITIMER#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#endif/* I'm not sure if SCO_UNIX and ISC have __svr4__ defined, but I think   they might */#ifdef M_SYS5#ifndef M_XENIX#include <sys/stream.h>#include <sys/ptem.h>#ifndef __svr4__#define __svr4__ 1#endif#endif#endif#ifdef ISC#ifndef __svr4__#define __svr4__ 1#endif#endif#ifdef __svr4__#include <stropts.h>#endif/** Aliased defines **//* O_NDELAY, O_NONBLOCK, and FNDELAY are all synonyms for placing a descriptor * in non-blocking mode; we make whichever one we have look like O_NDELAY */#ifndef O_NDELAY#ifdef O_NONBLOCK#define O_NDELAY O_NONBLOCK#endif#ifdef FNDELAY#define O_NDELAY FNDELAY#endif#endif/* Some systems define this, some don't */#ifndef sigmask#define sigmask(x) (1<<((x)-1))#endif/* Some BSDs don't have TILDE */#ifndef TILDE#define TILDE 0#endif/* Global configuration variables */int noxon = 0;			/* Set if ^S/^Q processing should be disabled */int Baud = 0;			/* Baud rate from joerc, cmd line or environment *//* The terminal */FILE *termin = NULL;FILE *termout = NULL;/* Original state of tty */#ifdef HAVE_POSIX_TERMIOSstruct termios oldterm;#else /* HAVE_POSIX_TERMIOS */#ifdef HAVE_SYSV_TERMIOstatic struct termio oldterm;#else /* HAVE_SYSV_TERMIO */static struct sgttyb oarg;static struct tchars otarg;static struct ltchars oltarg;#endif /* HAVE_SYSV_TERMIO */#endif /* HAVE_POSIX_TERMIOS *//* Output buffer, index and size */unsigned char *obuf = NULL;int obufp = 0;int obufsiz;/* The baud rate */unsigned baud;			/* Bits per second */unsigned long upc;		/* Microseconds per character *//* TTY Speed code to baud-rate conversion table (this is dumb- is it really * too much to ask for them to just use an integer for the baud-rate?) */static int speeds[] = {	B50, 50, B75, 75, B110, 110, B134, 134, B150, 150, B200, 200, B300,	300, B600, 600,	B1200, 1200, B1800, 1800, B2400, 2400, B4800, 4800, B9600, 9600#ifdef EXTA	    , EXTA, 19200#endif#ifdef EXTB	    , EXTB, 38400#endif#ifdef B19200	    , B19200, 19200#endif#ifdef B38400	    , B38400, 38400#endif};/* Input buffer */int have = 0;			/* Set if we have pending input */static unsigned char havec;	/* Character read in during pending input check */int leave = 0;			/* When set, typeahead checking is disabled *//* TTY mode flag.  1 for open, 0 for closed */static int ttymode = 0;/* Signal state flag.  1 for joe, 0 for normal */static int ttysig = 0;/* Stuff for shell windows */static pid_t kbdpid;		/* PID of kbd client */static int ackkbd = -1;		/* Editor acks keyboard client to this */static int mpxfd;		/* Editor reads packets from this fd */static int mpxsfd;		/* Clients send packets to this fd */static int nmpx = 0;static int accept = NO_MORE_DATA;	/* =-1 if we have last packet */struct packet {	MPX *who;	int size;	int ch;	unsigned char data[1024];} pack;MPX asyncs[NPROC];/* Set signals for JOE */void sigjoe(void){	if (ttysig)		return;	ttysig = 1;	joe_set_signal(SIGHUP, ttsig);	joe_set_signal(SIGTERM, ttsig);	joe_set_signal(SIGABRT, ttsig);	joe_set_signal(SIGINT, SIG_IGN);	joe_set_signal(SIGPIPE, SIG_IGN);}/* Restore signals for exiting */void signrm(void){	if (!ttysig)		return;	ttysig = 0;	joe_set_signal(SIGABRT, SIG_DFL);	joe_set_signal(SIGHUP, SIG_DFL);	joe_set_signal(SIGTERM, SIG_DFL);	joe_set_signal(SIGINT, SIG_DFL);	joe_set_signal(SIGPIPE, SIG_DFL);}/* Open terminal and set signals */void ttopen(void){	sigjoe();	ttopnn();}/* Close terminal and restore signals */void ttclose(void){	ttclsn();	signrm();}static int winched = 0;#ifdef SIGWINCH/* Window size interrupt handler */static RETSIGTYPE winchd(int unused){	++winched;	REINSTALL_SIGHANDLER(SIGWINCH, winchd);}#endif/* Second ticker */int ticked = 0;static RETSIGTYPE dotick(int unused){	ticked = 1;}void tickoff(void){#ifdef HAVE_SETITIMER	struct itimerval val;	val.it_value.tv_sec = 0;	val.it_value.tv_usec = 0;	val.it_interval.tv_sec = 0;	val.it_interval.tv_usec = 0;	setitimer(ITIMER_REAL,&val,NULL);#else	alarm(0);#endif}void tickon(void){#ifdef HAVE_SETITIMER	struct itimerval val;	val.it_interval.tv_sec = 0;	val.it_interval.tv_usec = 0;	if (auto_scroll) {		int tim = auto_trig_time - mnow();		if (tim < 0)			tim = 1;		tim *= 1000;		val.it_value.tv_sec = 0;		val.it_value.tv_usec = tim;	} else {		val.it_value.tv_sec = 1;		val.it_value.tv_usec = 0;	}	ticked = 0;	joe_set_signal(SIGALRM, dotick);	setitimer(ITIMER_REAL,&val,NULL);#else	ticked = 0;	joe_set_signal(SIGALRM, dotick);	alarm(1);#endif}/* Open terminal */void ttopnn(void){	int x, bbaud;#ifdef HAVE_POSIX_TERMIOS	struct termios newterm;#else#ifdef HAVE_SYSV_TERMIO	struct termio newterm;#else	struct sgttyb arg;	struct tchars targ;	struct ltchars ltarg;#endif#endif	if (!termin) {		if (idleout ? (!(termin = stdin) || !(termout = stdout)) : (!(termin = fopen("/dev/tty", "r")) || !(termout = fopen("/dev/tty", "w")))) {			fprintf(stderr, (char *)joe_gettext(_("Couldn\'t open /dev/tty\n")));			exit(1);		} else {#ifdef SIGWINCH			joe_set_signal(SIGWINCH, winchd);#endif		}	}	if (ttymode)		return;	ttymode = 1;	fflush(termout);#ifdef HAVE_POSIX_TERMIOS	tcgetattr(fileno(termin), &oldterm);	newterm = oldterm;	newterm.c_lflag = 0;	if (noxon)		newterm.c_iflag &= ~(ICRNL | IGNCR | INLCR | IXON | IXOFF);	else		newterm.c_iflag &= ~(ICRNL | IGNCR | INLCR);	newterm.c_oflag = 0;	newterm.c_cc[VMIN] = 1;	newterm.c_cc[VTIME] = 0;	tcsetattr(fileno(termin), TCSADRAIN, &newterm);	bbaud = cfgetospeed(&newterm);#else#ifdef HAVE_SYSV_TERMIO	ioctl(fileno(termin), TCGETA, &oldterm);	newterm = oldterm;	newterm.c_lflag = 0;	if (noxon)		newterm.c_iflag &= ~(ICRNL | IGNCR | INLCR | IXON | IXOFF);	else		newterm.c_iflag &= ~(ICRNL | IGNCR | INLCR);	newterm.c_oflag = 0;	newterm.c_cc[VMIN] = 1;	newterm.c_cc[VTIME] = 0;	ioctl(fileno(termin), TCSETAW, &newterm);	bbaud = (newterm.c_cflag & CBAUD);#else	ioctl(fileno(termin), TIOCGETP, &arg);	ioctl(fileno(termin), TIOCGETC, &targ);	ioctl(fileno(termin), TIOCGLTC, &ltarg);	oarg = arg;	otarg = targ;	oltarg = ltarg;	arg.sg_flags = ((arg.sg_flags & ~(ECHO | CRMOD | XTABS | ALLDELAY | TILDE)) | CBREAK);	if (noxon) {		targ.t_startc = -1;		targ.t_stopc = -1;	}	targ.t_intrc = -1;	targ.t_quitc = -1;	targ.t_eofc = -1;	targ.t_brkc = -1;	ltarg.t_suspc = -1;	ltarg.t_dsuspc = -1;	ltarg.t_rprntc = -1;	ltarg.t_flushc = -1;	ltarg.t_werasc = -1;	ltarg.t_lnextc = -1;	ioctl(fileno(termin), TIOCSETN, &arg);	ioctl(fileno(termin), TIOCSETC, &targ);	ioctl(fileno(termin), TIOCSLTC, &ltarg);	bbaud = arg.sg_ospeed;#endif#endif	baud = 9600;	upc = 0;	for (x = 0; x != 30; x += 2)		if (bbaud == speeds[x]) {			baud = speeds[x + 1];			break;		}	if (Baud)		baud = Baud;	upc = DIVIDEND / baud;	if (obuf)		joe_free(obuf);	if (!(TIMES * upc))		obufsiz = 4096;	else {		obufsiz = 1000000 / (TIMES * upc);		if (obufsiz > 4096)			obufsiz = 4096;	}	if (!obufsiz)		obufsiz = 1;	obuf = (unsigned char *) joe_malloc(obufsiz);}/* Close terminal */void ttclsn(void){	int oleave;	if (ttymode)		ttymode = 0;	else		return;	oleave = leave;	leave = 1;	ttflsh();#ifdef HAVE_POSIX_TERMIOS	tcsetattr(fileno(termin), TCSADRAIN, &oldterm);#else#ifdef HAVE_SYSV_TERMIO	ioctl(fileno(termin), TCSETAW, &oldterm);#else	ioctl(fileno(termin), TIOCSETN, &oarg);	ioctl(fileno(termin), TIOCSETC, &otarg);	ioctl(fileno(termin), TIOCSLTC, &oltarg);#endif#endif	leave = oleave;}/* Timer interrupt handler */static int yep;static RETSIGTYPE dosig(int unused){	yep = 1;}/* FLush output and check for typeahead */#ifdef HAVE_SETITIMER#ifdef SIG_SETMASKstatic void maskit(void){	sigset_t set;	sigemptyset(&set);	sigaddset(&set, SIGALRM);	sigprocmask(SIG_SETMASK, &set, NULL);}static void unmaskit(void){	sigset_t set;	sigemptyset(&set);	sigprocmask(SIG_SETMASK, &set, NULL);}static void pauseit(void){	sigset_t set;	sigemptyset(&set);	sigsuspend(&set);}#elsestatic void maskit(void){	sigsetmask(sigmask(SIGALRM));}static void unmaskit(void){	sigsetmask(0);}static void pauseit(void){	sigpause(0);}#endif#endifint ttflsh(void){	/* Flush output */	if (obufp) {		unsigned long usec = obufp * upc;	/* No. usecs this write should take */#ifdef HAVE_SETITIMER		if (usec >= 50000 && baud < 9600) {			struct itimerval a, b;			a.it_value.tv_sec = usec / 1000000;			a.it_value.tv_usec = usec % 1000000;			a.it_interval.tv_usec = 0;			a.it_interval.tv_sec = 0;			alarm(0);			joe_set_signal(SIGALRM, dosig);			yep = 0;			maskit();			setitimer(ITIMER_REAL, &a, &b);			joe_write(fileno(termout), obuf, obufp);			while (!yep)				pauseit();			unmaskit();		} else			joe_write(fileno(termout), obuf, obufp);#else		joe_write(fileno(termout), obuf, obufp);#ifdef FIORDCHK		if (baud < 9600 && usec / 1000)			nap(usec / 1000);#endif#endif		obufp = 0;	}	/* Ack previous packet */	if (ackkbd != -1 && accept != NO_MORE_DATA && !have) {		unsigned char c = 0;		if (pack.who && pack.who->func)			joe_write(pack.who->ackfd, &c, 1);		else			joe_write(ackkbd, &c, 1);		accept = NO_MORE_DATA;	}	/* Check for typeahead or next packet */	if (!have && !leave) {		if (ackkbd != -1) {			fcntl(mpxfd, F_SETFL, O_NDELAY);			if (read(mpxfd, &pack, sizeof(struct packet) - 1024) > 0) {				fcntl(mpxfd, F_SETFL, 0);				joe_read(mpxfd, pack.data, pack.size);				have = 1;				accept = pack.ch;			} else				fcntl(mpxfd, F_SETFL, 0);		} else {			/* Set terminal input to non-blocking */			fcntl(fileno(termin), F_SETFL, O_NDELAY);			/* Try to read */			if (read(fileno(termin), &havec, 1) == 1)				have = 1;			/* Set terminal back to blocking */			fcntl(fileno(termin), F_SETFL, 0);		}	}	return 0;}/* Read next character from input */void mpxdied(MPX *m);long last_time;int ttgetc(void){	int stat;	long new_time;	int flg;	tickon();      loop:      	flg = 0;      	/* Status line clock */	new_time = time(NULL);	if (new_time != last_time) {		last_time = new_time;		dostaupd = 1;		ticked = 1;	}	/* Autoscroller */	if (auto_scroll && mnow() >= auto_trig_time) {		do_auto_scroll();		ticked = 1;		flg = 1;	}	ttflsh();	while (winched) {		winched = 0;		edupd(1);		ttflsh();	}	if (ticked) {		edupd(flg);		ttflsh();		tickon();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -