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

📄 tty.c

📁 Magic C++!的源代码
💻 C
字号:
/* tty.c -- Magic C++ tty property setup   (Mostly) portable public-domain implementation   -- Copyright(C) 2003 Magicunix Infomation Technology Limited    This file is part of magicd.   magicd is free software; you can redistribute it and/or   modify it under the terms of the GNU General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.	    For details, see the Magic C++ World-Wide-Web page,    `http://www.magicunix.com',   or send a mail to the Magic C++ developers <support@magicunix.com>. */#include <stdio.h>#include <stdlib.h>#include <string.h> #include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>#include "tools.h"extern void d_zero(), d_copy();#ifdef HAVE_TERMIO_H#include <termio.h>#else#include <sys/ioctl.h>#endif  /* HAVE_TERMIO_H */#ifdef HAVE_BSDTTY_H#include <sys/bsdtty.h>#ifndef TIOCNOTTY#define TIOCNOTTY	_IO('t', 113)	/* HP-UX void tty definition */#endif#endif /* HAVE_BSDTTY_H */#ifdef HAVE_SYS_IOCTL_COMPAT_H#include	<sys/ioctl_compat.h>#endif /* NEED_COMPAT_H *//* * Pseudo-terminal routines for Unix System V Release 3.2 and BSD4.2-3 * I actually have three sets of routines, for three different methods * of obtaining a pseudo-tty.  The first is for IRIX System V UNIX,  * which uses _getpty() to obtain a pty.  The second is for Solaris * 2.x which uses a clone open with some funky streams stuff to get * a pseudo-tty.  The last is the brute-force method that works on * every thing else I have come across, including Sun/OS 4.x, AIX, * HP-UX, BSD 4.2-3, ULTRIX, and AT&T System V.3 */extern int errno; /*from magicd.c*/extern int debug; /*from magicd.c*/int master_fd;char tty_name[18];char pty_name[12];#ifdef IRIX	/* IRIX System V for SGI machines */extern char *_getpty();int get_pty_master(){	char 	*ttyptr;	if ( (ttyptr=_getpty(&master_fd, O_RDWR, 0600, 0)) == 0 )		return(-1);	else		strcpy(tty_name, ttyptr);	return(master_fd);}/* * Open the slave half of a pseudo-terminal. */int get_pty_slave(){	int	slave_fd;	char	*slavename;	slavename=tty_name;	if (slavename == NULL) {		close(master_fd);		return(-1);	}	if ( (slave_fd=open(slavename, O_RDWR, 0666)) < 0 )	/* open the slave */	{		close(master_fd);		return(-1);	}	return(slave_fd);}#else  /* not IRIX */#ifdef SOLARIS		/* Solaris 2.1 (UNIX System V r4)  */#include <stropts.h>#define DEV_CLONE	"/dev/ptmx"extern char *ptsname();int get_pty_master(){	char 	*ttyptr;	if(debug)		util_log("open master!\n");	if ( (master_fd=open(DEV_CLONE, O_RDWR, 0666)) < 0 )	{		util_err_log("get_pty_master() failed on open!\n",__FILE__,__LINE__,errno );		return(-1);	}	if ( grantpt(master_fd) < 0 )	/* grant access to slave */	{		util_err_log("get_pty_master() failed on grantpt!\n",__FILE__,__LINE__,errno );				close(master_fd);		return(-1);	}	if ( unlockpt(master_fd) < 0 )	/* clear slave's lock flag */	{		util_err_log("get_pty_master() failed on unlockpt!\n",__FILE__,__LINE__,errno );		close(master_fd);		return(-1);	}	if ( (ttyptr=ptsname(master_fd)) == NULL )	{		util_err_log("get_pty_master() failed on ptsname!\n",__FILE__,__LINE__,errno );				close(master_fd);		return(-1);	}	else		strcpy(tty_name, ttyptr);	return(master_fd);}/* * Open the slave half of a pseudo-terminal. */int get_pty_slave(){	int	slave_fd;	char	*slavename;	slavename=tty_name;	if ( (slave_fd=open(slavename, O_RDWR, 0666)) < 0 )	/* open the slave */	{		close(master_fd);		return(-1);	}	if ( ioctl(slave_fd, I_PUSH, "ptem") < 0 )	{		close(master_fd);		close(slave_fd);		return(-1);	}	if ( ioctl(slave_fd, I_PUSH, "ldterm") < 0 )	{		close(master_fd);		close(slave_fd);		return(-1);	}	if ( ioctl(slave_fd, I_PUSH, "ttcompat") < 0 )	{		close(master_fd);		close(slave_fd);		return(-1);	}	return(slave_fd);}#else	/* BSD, Sun/OS, AIX, ULTRIX, HP-UX, AT&T SYSV */#include	<setjmp.h>#ifndef X_OK#define	R_OK	4	/* Test for Read permission */#define	W_OK	2	/* Test for Write permission */#define	X_OK	1	/* Test for eXecute permission */#endif#define PTY_OWNER 	0	/* the uid of the owner of pty's.				   usually bin or root */#define BIN_UID		2	/* Secondary pty owner */jmp_buf next;void trynext(){	longjmp(next, 2);}int get_pty_master(){	int i, master_fd;	char *ptr;	struct stat statbuff;	static char ptychar[]="pqrst";  /* X */ 	static char hexdigit[]="0123456789abcdef";  /* Y */	for (ptr=ptychar; *ptr != 0; ptr++)	{		strcpy(pty_name, "/dev/ptyXY");		pty_name[8]=(*ptr);  /* X */		pty_name[9]='0';   /* Y */		if ( stat(pty_name, &statbuff) < 0 )			break;#ifdef OLDDEBUG		fprintf(stderr, "statted.\n");#endif		i=(-1);		/* Initialize i */		/*timeout checking*/		/* Set a time limit for the open */		/*if it's timeout ,back here*/		if ( setjmp(next) == -1 )			return(-1);		signal(SIGALRM, trynext);		for ( ++i; hexdigit[i]; ++i)		{			pty_name[5]='p';			pty_name[9]=hexdigit[i];			/*set timeout*/			alarm(2);	/* Set an open timeout */			if ( (master_fd=open(pty_name, O_RDWR, 0666)) >= 0 )			{				alarm(0); 	/* Reset the alarm */				pty_name[5]='t';				sprintf(tty_name, "%s", pty_name);				if ( access(tty_name, R_OK|W_OK) == 0 ) 				{					signal(SIGALRM, SIG_DFL);					return (master_fd);				} else {					pty_name[5]='p';					(void) close(master_fd);				}			}			/* reset the alarm */			alarm(0);		}	}	util_err_log("Get master pty failed!\n",__FILE__,__LINE__,errno);		return(-1);}/* Open the slave half of a pseudo-terminal. */int get_pty_slave(){	int slave_fd;	if ( (slave_fd=open(tty_name, O_RDWR, 0666)) < 0 )	{		util_err_log("Get slave pty failed!\n",__FILE__,__LINE__,errno);		close(master_fd);		return(-1);	}	return(slave_fd);}#endif  /* is SOLARIS? */#endif /* is IRIX? */ /* The end of the Pseudo-tty routines *//* These are the terminal manipulation routines. :)  Fun!  */#ifdef SIGWINCH		 /* Starting window structure *//* I am using struct winsize here, but redefining it, because   Each system seems to define it in a different place, or not   at all.  The actual structure never seems to change though. :) */struct winstats {	unsigned short	ws_row;		/* rows, in characters */	unsigned short	ws_col;		/* columns, in characters */	unsigned short	ws_xpixel;	/* horizontal size, pixels - not used */	unsigned short	ws_ypixel;	/* vertical size, pixels - not used */	} tty_win;#ifdef NEED_UPDATEWIN			/* Not used *//* The window size has changed, let the pty know.  Used as a signal handler */void updatewin(){#ifdef TIOCGWINSZ    	(void) ioctl(ttyfd, TIOCGWINSZ, &tty_win);    	(void) ioctl(masterfd, TIOCSWINSZ, &tty_win);#endif /* TIOCGWINSZ */	   /* An interesting note...		I had code here to send a SIGWINCH to the pty		process, but it turns out the kernel does when		the pty recieves the TIOCSWINSZ ioctl.  */}#endif /* NEED_UPDATEWIN */#endif /* SIGWINCH */	/* Code to disassociate from my tty. Yay! :) */void dropctty(){	int fd; #ifdef _POSIX_SOURCE	setsid();		/* The POSIX solution is simple. :) */#else#ifdef TIOCNOTTY  /* We want to get HP-UX, BSD, and Sun/OS here */	/*setpgrp(0, 0);*/	/*there are no args in sun and linux*/#ifdef FREEBSD	setpgrp(0,0);#else	setpgrp();#endif#if !defined( CIBAUD)  && !defined(FREEBSD)/* Sun/OS doesn't need to do TIOCNOTTY.  */	if ( (fd=open("/dev/tty", O_RDWR)) > (-1) ) 	{		if (ioctl(fd, TIOCNOTTY, 0) < 0)		{			util_log("ioctl TIOCNOTTY error\n");			fprintf(stderr, "\r");		}		close(fd);	}#endif /* CIBAUD */#else /*  SYSV 	*/	setpgrp();#endif /* TIOCNOTTY */#endif /* _POSIX_SOURCE */}/* Just fork, and exit, leaving the child running as a daemon */void daemonize(){	switch (fork()) {		case -1:	perror("fork() failed");				exit(3);				break;		case 0:		dropctty();				return;		default:	exit(0);	}}#ifdef HAVE_TERMIO_H/* Get the modes of the contorlling tty and save them.  Saves   ttymodes in tty_mode and returns -1 if ioctl fails. */struct termio tty_mode;  /* Save tty mode here */int tty_init=0;int tty_getmode(fd)int fd;{	/* If not a tty, don't set tty_init, but return ok */	if ( !isatty(fd) ) 		return(0);	d_zero((char *)&tty_mode, sizeof(struct termio));	if (ioctl(fd, TCGETA, (char *) &tty_mode) < 0)		return(-1);  	tty_init=1;	/* Flag: we have initialized the tty_mode struct */#if defined(SIGWINCH) && defined(TIOCGWINSZ)	d_zero((char *)&tty_win, sizeof(struct winstats));   	(void) ioctl(fd, TIOCGWINSZ, &tty_win);#endif /* SIGWINCH */	return(0);}/* Restore terminal's mode to whatever it was on the most   recent call to the tty_getmode() function. */int tty_reset(fd)int fd;{	if ( ! tty_init )		return(-1);	if ( ! isatty(fd) )		return(0);	if (ioctl(fd, TCSETA, (char *) &tty_mode) < 0)		return(-1);#if defined(SIGWINCH) && defined(TIOCSWINSZ)	(void) ioctl(fd, TIOCSWINSZ, &tty_win);#endif /* SIGWINCH */	return(0);}/* Set a tty to a sane mode */int tty_sane(fd)int fd;{#ifdef TIOCGWINSZ	struct winstats temp_win;#endif	struct termio temp_mode;	if ( ! isatty(fd) )		return(0);	if( debug )		fprintf(stderr, "tty_init: %d\r\n", tty_init);	temp_mode.c_lflag=(ISIG|ICANON|ECHO|ECHOE);	temp_mode.c_iflag=(BRKINT|IGNPAR|ISTRIP|ICRNL|IXON);	temp_mode.c_oflag=(OPOST|ONLCR);	temp_mode.c_cflag=(CS8|PARENB|CREAD);	temp_mode.c_cc[VERASE]=('H'^64);	temp_mode.c_cc[VKILL]=('U'^64);	temp_mode.c_cc[VQUIT]=('\\'^64);	temp_mode.c_cc[VINTR]=('C'^64);	temp_mode.c_cc[VEOF]=('D'^64);	temp_mode.c_cc[VMIN]=1;	temp_mode.c_cc[VTIME]=0;		if (ioctl(fd, TCSETA, (char *) &temp_mode) < 0)		return(-1);#if defined(SIGWINCH) && defined(TIOCSWINSZ)	d_zero((char *)&temp_win, sizeof(struct winstats));	temp_win.ws_row=24;	temp_win.ws_col=80;	(void) ioctl(fd, TIOCSWINSZ, &temp_win);#endif	return(0);}/* Set a terminal in raw mode */int tty_raw(fd)int fd;     	/* file descriptor of tty device */{	struct termio temp_mode;	if ( ! isatty(fd) )		return(0);	if ( ioctl(fd, TCGETA, (char *)&temp_mode) < 0 )		return(-1);	temp_mode.c_iflag=(IGNBRK | ISTRIP);   /* turn off all input control */	temp_mode.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONLRET);					/* disable output post-processing */	temp_mode.c_lflag = 0;	temp_mode.c_cc[VMIN]=1;		/* 1 or more chars satisfy read */	temp_mode.c_cc[VTIME]=0;	/* 10'ths of seconds between chars */	if (ioctl(fd, TCSETA, (char *) &temp_mode) < 0)		return(-1);	return(0);}/* Function to set a tty echo or no echo */int tty_echo(fd, echo)int fd;int echo;{	struct termio temp_mode;	if ( ! isatty(fd) )		return(0);	if ( ioctl(fd, TCGETA, &temp_mode) < 0 )		return(-1);	if ( echo )		temp_mode.c_lflag|=ECHO;	else		temp_mode.c_lflag&=(~ECHO);	util_log("set echo!\n");	if ( ioctl(fd, TCSETA, &temp_mode) < 0 )		return(-1);	return(0);}#else  /* no /usr/include/termio.h *//* Get the modes of the controlling tty and save them.  Saves   ttymodes in tty_mode and returns 1 if ioctl fails. */static struct sgttyb	tty_mode;	/* save tty mode here */int tty_init=0;int tty_getmode(fd)int fd;{	if ( ! isatty(fd) )		return(0);	tty_init=1;	/* Flag: we have initialized the tty_mode struct */	if (ioctl(fd, TIOCGETP, (char *) &tty_mode) < 0)		return(-1);#ifdef SIGWINCH	if ( ioctl(fd, TIOCGWINSZ, &tty_win) < 0 )		perror("ioctl TIOCGWINSZ error");#endif /* SIGWINCH */	return(0);}/* * Restore a terminal's mode to whatever it was on the most * recent call to the tty_getmode() function above. */int tty_reset(fd)int	fd;		/* of terminal device */{	if ( ! tty_init )	/* Have we been initialized? */		return(-1);	if ( ! isatty(fd) )		return(0);	if (ioctl(fd, TIOCSETP, (char *) &tty_mode) < 0)		return(-1);#ifdef SIGWINCH    	(void) ioctl(fd, TIOCSWINSZ, &tty_win);#endif /* SIGWINCH */	return(0);}/* Set a tty to a sane mode */int tty_sane(fd)int fd;{	struct sgttyb temp_mode;	if ( ! isatty(fd) )		return(0);	if (ioctl(fd, TIOCGETP, (char *) &temp_mode) < 0)		return(-1);	temp_mode.sg_flags &= ~RAW;	/* turn RAW mode off */	temp_mode.sg_flags |= ECHO;	/* turn ECHO on */		if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0)		return(-1);	return(0);}/* * Put a terminal device into RAW mode with ECHO off. */int tty_raw(fd)int	fd;		/* of terminal device */{	struct sgttyb	temp_mode;	if ( ! isatty(fd) )		return(0);	if (ioctl(fd, TIOCGETP, (char *) &temp_mode) < 0)		return(-1);	temp_mode.sg_flags |= RAW;	/* turn RAW mode on */	temp_mode.sg_flags &= ~ECHO;	/* turn ECHO off */	if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0)		return(-1);	return(0);}/* Set a terminal echo or no echo, as requested.  */int tty_echo(fd, echo)int fd;int echo;{	struct sgttyb temp_mode;	if ( ! isatty(fd) )		return(0);	if (ioctl(fd, TIOCGETP, (char *) &temp_mode) < 0)		return(-1);	if ( echo )		temp_mode.sg_flags |= ECHO;	/* turn ECHO on */	else		temp_mode.sg_flags &= ~ECHO;	/* turn ECHO off */		if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0)		return(-1);	return(0);}#endif /* HAVE_TERMIO_H *//* * Write "n" bytes to a descriptor. * Use in place of write() when fd is a stream socket. */int writen(fd, ptr, nbytes)register int	fd;register char	*ptr;register int	nbytes;{	int	nleft, nwritten;	nleft = nbytes;	while (nleft > 0) {		nwritten = write(fd, ptr, nleft);		if (nwritten <= 0)			return(nwritten);		/* error */		nleft -= nwritten;		ptr   += nwritten;	}	return(nbytes - nleft);}       /* Replacement for bzero(), which isn't always available.  */void d_zero(data, size)char *data;int   size;{	int i;	for ( i=0; (i < size); ++i, ++data )		*data='\0';}/* Replacement for bcopy(), which isn't always available.  */void d_copy(frombuf, tobuf, size)char *frombuf;char *tobuf;int   size;{	int i;	for ( i=0; (i < size); ++i, ++frombuf, ++tobuf )		*tobuf=(*frombuf);}

⌨️ 快捷键说明

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