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

📄 tty.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 4 页
字号:
		tp->tty_outrepcode = REVIVE;	}  }  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);}/*===========================================================================* *				do_ioctl				     * *===========================================================================*/PRIVATE void do_ioctl(tp, m_ptr)register tty_t *tp;message *m_ptr;			/* pointer to message sent to task */{/* Perform an IOCTL on this terminal. Posix termios calls are handled * by the IOCTL system call */  int r;  union {	int i;#if ENABLE_SRCCOMPAT	struct sgttyb sg;	struct tchars tc;#endif  } param;  size_t size;  /* Size of the ioctl parameter. */  switch (m_ptr->TTY_REQUEST) {    case TCGETS:        /* Posix tcgetattr function */    case TCSETS:        /* Posix tcsetattr function, TCSANOW option */     case TCSETSW:       /* Posix tcsetattr function, TCSADRAIN option */    case TCSETSF:	/* Posix tcsetattr function, TCSAFLUSH option */        size = sizeof(struct termios);        break;    case TCSBRK:        /* Posix tcsendbreak function */    case TCFLOW:        /* Posix tcflow function */    case TCFLSH:        /* Posix tcflush function */    case TIOCGPGRP:     /* Posix tcgetpgrp function */    case TIOCSPGRP:	/* Posix tcsetpgrp function */        size = sizeof(int);        break;    case TIOCGWINSZ:    /* get window size (not Posix) */    case TIOCSWINSZ:	/* set window size (not Posix) */        size = sizeof(struct winsize);        break;#if ENABLE_SRCCOMPAT    case TIOCGETP:      /* BSD-style get terminal properties */    case TIOCSETP:	/* BSD-style set terminal properties */	size = sizeof(struct sgttyb);	break;    case TIOCGETC:      /* BSD-style get terminal special characters */     case TIOCSETC:	/* BSD-style get terminal special characters */ 	size = sizeof(struct tchars);	break;#endif#if (MACHINE == IBM_PC)    case KIOCSMAP:	/* load keymap (Minix extension) */        size = sizeof(keymap_t);        break;    case TIOCSFON:	/* load font (Minix extension) */        size = sizeof(u8_t [8192]);        break;#endif    case TCDRAIN:	/* Posix tcdrain function -- no parameter */    default:		size = 0;  }  r = OK;  switch (m_ptr->TTY_REQUEST) {    case TCGETS:	/* Get the termios attributes. */	r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_termios,		m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS, 		(vir_bytes) size);	break;    case TCSETSW:    case TCSETSF:    case TCDRAIN:	if (tp->tty_outleft > 0) {		/* Wait for all ongoing output processing to finish. */		tp->tty_iocaller = m_ptr->m_source;		tp->tty_ioproc = m_ptr->PROC_NR;		tp->tty_ioreq = m_ptr->REQUEST;		tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;		r = SUSPEND;		break;	}	if (m_ptr->TTY_REQUEST == TCDRAIN) break;	if (m_ptr->TTY_REQUEST == TCSETSF) tty_icancel(tp);	/*FALL THROUGH*/    case TCSETS:	/* Set the termios attributes. */	r = sys_vircopy( m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		SELF, D, (vir_bytes) &tp->tty_termios, (vir_bytes) size);	if (r != OK) break;	setattr(tp);	break;    case TCFLSH:	r = sys_vircopy( m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		SELF, D, (vir_bytes) &param.i, (vir_bytes) size);	if (r != OK) break;	switch (param.i) {	    case TCIFLUSH:	tty_icancel(tp);		 	    break;	    case TCOFLUSH:	(*tp->tty_ocancel)(tp, 0);		    break;	    case TCIOFLUSH:	tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break;	    default:		r = EINVAL;	}	break;    case TCFLOW:	r = sys_vircopy( m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		SELF, D, (vir_bytes) &param.i, (vir_bytes) size);	if (r != OK) break;	switch (param.i) {	    case TCOOFF:	    case TCOON:		tp->tty_inhibited = (param.i == TCOOFF);		tp->tty_events = 1;		break;	    case TCIOFF:		(*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTOP]);		break;	    case TCION:		(*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTART]);		break;	    default:		r = EINVAL;	}	break;    case TCSBRK:	if (tp->tty_break != NULL) (*tp->tty_break)(tp,0);	break;    case TIOCGWINSZ:	r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_winsize,		m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS, 		(vir_bytes) size);	break;    case TIOCSWINSZ:	r = sys_vircopy( m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		SELF, D, (vir_bytes) &tp->tty_winsize, (vir_bytes) size);	sigchar(tp, SIGWINCH);	break;#if ENABLE_SRCCOMPAT    case TIOCGETP:	compat_getp(tp, &param.sg);	r = sys_vircopy(SELF, D, (vir_bytes) &param.sg,		m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		(vir_bytes) size);	break;    case TIOCSETP:	r = sys_vircopy( m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		SELF, D, (vir_bytes) &param.sg, (vir_bytes) size);	if (r != OK) break;	compat_setp(tp, &param.sg);	break;    case TIOCGETC:	compat_getc(tp, &param.tc);	r = sys_vircopy(SELF, D, (vir_bytes) &param.tc,		m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS, 		(vir_bytes) size);	break;    case TIOCSETC:	r = sys_vircopy( m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS,		SELF, D, (vir_bytes) &param.tc, (vir_bytes) size);	if (r != OK) break;	compat_setc(tp, &param.tc);	break;#endif#if (MACHINE == IBM_PC)    case KIOCSMAP:	/* Load a new keymap (only /dev/console). */	if (isconsole(tp)) r = kbd_loadmap(m_ptr);	break;    case TIOCSFON:	/* Load a font into an EGA or VGA card (hs@hck.hr) */	if (isconsole(tp)) r = con_loadfont(m_ptr);	break;#endif#if (MACHINE == ATARI)    case VDU_LOADFONT:	r = vdu_loadfont(m_ptr);	break;#endif/* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is  * not defined. */    case TIOCGPGRP:         case TIOCSPGRP:	    default:#if ENABLE_BINCOMPAT	do_ioctl_compat(tp, m_ptr);	return;#else	r = ENOTTY;#endif  }  /* Send the reply. */  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);}/*===========================================================================* *				do_open					     * *===========================================================================*/PRIVATE void do_open(tp, m_ptr)register tty_t *tp;message *m_ptr;			/* pointer to message sent to task */{/* A tty line has been opened.  Make it the callers controlling tty if * O_NOCTTY is *not* set and it is not the log device.  1 is returned if * the tty is made the controlling tty, otherwise OK or an error code. */  int r = OK;  if (m_ptr->TTY_LINE == LOG_MINOR) {	/* The log device is a write-only diagnostics device. */	if (m_ptr->COUNT & R_BIT) r = EACCES;  } else {	if (!(m_ptr->COUNT & O_NOCTTY)) {		tp->tty_pgrp = m_ptr->PROC_NR;		r = 1;	}	tp->tty_openct++;  }  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);}/*===========================================================================* *				do_close				     * *===========================================================================*/PRIVATE void do_close(tp, m_ptr)register tty_t *tp;message *m_ptr;			/* pointer to message sent to task */{/* A tty line has been closed.  Clean up the line if it is the last close. */  if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {	tp->tty_pgrp = 0;	tty_icancel(tp);	(*tp->tty_ocancel)(tp, 0);	(*tp->tty_close)(tp, 0);	tp->tty_termios = termios_defaults;	tp->tty_winsize = winsize_defaults;	setattr(tp);  }  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, OK);}/*===========================================================================* *				do_cancel				     * *===========================================================================*/PRIVATE void do_cancel(tp, m_ptr)register tty_t *tp;message *m_ptr;			/* pointer to message sent to task */{/* A signal has been sent to a process that is hanging trying to read or write. * The pending read or write must be finished off immediately. */  int proc_nr;  int mode;  /* Check the parameters carefully, to avoid cancelling twice. */  proc_nr = m_ptr->PROC_NR;  mode = m_ptr->COUNT;  if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {	/* Process was reading when killed.  Clean up input. */	tty_icancel(tp);	tp->tty_inleft = tp->tty_incum = 0;  }  if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {	/* Process was writing when killed.  Clean up output. */	(*tp->tty_ocancel)(tp, 0);	tp->tty_outleft = tp->tty_outcum = 0;  }  if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {	/* Process was waiting for output to drain. */	tp->tty_ioreq = 0;  }  tp->tty_events = 1;  tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);}PUBLIC int select_try(struct tty *tp, int ops){	int ready_ops = 0;	/* Special case. If line is hung up, no operations will block.	 * (and it can be seen as an exceptional condition.)	 */	if (tp->tty_termios.c_ospeed == B0) {		ready_ops |= ops;	}	if (ops & SEL_RD) {		/* will i/o not block on read? */		if (tp->tty_inleft > 0) {			ready_ops |= SEL_RD;	/* EIO - no blocking */		} else if (tp->tty_incount > 0) {			/* Is a regular read possible? tty_incount			 * says there is data. But a read will only succeed			 * in canonical mode if a newline has been seen.			 */			if (!(tp->tty_termios.c_lflag & ICANON) ||				tp->tty_eotct > 0) {				ready_ops |= SEL_RD;			}		}	}	if (ops & SEL_WR)  {  		if (tp->tty_outleft > 0)  ready_ops |= SEL_WR;		else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= SEL_WR;	}	return ready_ops;}PUBLIC int select_retry(struct tty *tp){	if (select_try(tp, tp->tty_select_ops))		notify(tp->tty_select_proc);	return OK;}/*===========================================================================* *				handle_events				     * *===========================================================================*/PUBLIC void handle_events(tp)tty_t *tp;			/* TTY to check for events. */{/* Handle any events pending on a TTY.  These events are usually device * interrupts. * * Two kinds of events are prominent: *	- a character has been received from the console or an RS232 line. *	- an RS232 line has completed a write request (on behalf of a user). * The interrupt handler may delay the interrupt message at its discretion * to avoid swamping the TTY task.  Messages may be overwritten when the * lines are fast or when there are races between different lines, input * and output, because MINIX only provides single buffering for interrupt * messages (in proc.c).  This is handled by explicitly checking each line * for fresh input and completed output on each interrupt. */  char *buf;  unsigned count;  int status;  do {	tp->tty_events = 0;	/* Read input and perform input processing. */	(*tp->tty_devread)(tp, 0);	/* Perform output processing and write output. */	(*tp->tty_devwrite)(tp, 0);	/* Ioctl waiting for some event? */	if (tp->tty_ioreq != 0) dev_ioctl(tp);  } while (tp->tty_events);  /* Transfer characters from the input queue to a waiting process. */  in_transfer(tp);  /* Reply if enough bytes are available. */  if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {	if (tp->tty_inrepcode == REVIVE) {		notify(tp->tty_incaller);		tp->tty_inrevived = 1;	} else {		tty_reply(tp->tty_inrepcode, tp->tty_incaller, 			tp->tty_inproc, tp->tty_incum);		tp->tty_inleft = tp->tty_incum = 0;	}  }  if (tp->tty_select_ops)  	select_retry(tp);#if NR_PTYS > 0  if (ispty(tp))  	select_retry_pty(tp);#endif}/*===========================================================================* *				in_transfer				     * *===========================================================================*/PRIVATE void in_transfer(tp)register tty_t *tp;		/* pointer to terminal to read from */{/* Transfer bytes from the input queue to a process reading from a terminal. */  int ch;  int count;  char buf[64], *bp;  /* Force read to succeed if the line is hung up, looks like EOF to reader. */  if (tp->tty_termios.c_ospeed == B0) tp->tty_min = 0;  /* Anything to do? */  if (tp->tty_inleft == 0 || tp->tty_eotct < tp->tty_min) return;  bp = buf;  while (tp->tty_inleft > 0 && tp->tty_eotct > 0) {	ch = *tp->tty_intail;	if (!(ch & IN_EOF)) {		/* One character to be delivered to the user. */		*bp = ch & IN_CHAR;		tp->tty_inleft--;		if (++bp == bufend(buf)) {			/* Temp buffer full, copy to user space. */			sys_vircopy(SELF, D, (vir_bytes) buf, 				tp->tty_inproc, D, tp->tty_in_vir,				(vir_bytes) buflen(buf));			tp->tty_in_vir += buflen(buf);			tp->tty_incum += buflen(buf);			bp = buf;		}	}	/* Remove the character from the input queue. */	if (++tp->tty_intail == bufend(tp->tty_inbuf))		tp->tty_intail = tp->tty_inbuf;	tp->tty_incount--;	if (ch & IN_EOT) {		tp->tty_eotct--;		/* Don't read past a line break in canonical mode. */		if (tp->tty_termios.c_lflag & ICANON) tp->tty_inleft = 0;	}  }  if (bp > buf) {	/* Leftover characters in the buffer. */	count = bp - buf;	sys_vircopy(SELF, D, (vir_bytes) buf, 		tp->tty_inproc, D, tp->tty_in_vir, (vir_bytes) count);	tp->tty_in_vir += count;	tp->tty_incum += count;  }  /* Usually reply to the reader, possibly even if incum == 0 (EOF). */  if (tp->tty_inleft == 0) {	if (tp->tty_inrepcode == REVIVE) {		notify(tp->tty_incaller);		tp->tty_inrevived = 1;	} else {		tty_reply(tp->tty_inrepcode, tp->tty_incaller, 			tp->tty_inproc, tp->tty_incum);		tp->tty_inleft = tp->tty_incum = 0;	}  }}/*===========================================================================* *				in_process				     * *===========================================================================*/PUBLIC int in_process(tp, buf, count)register tty_t *tp;		/* terminal on which character has arrived */char *buf;			/* buffer with input characters */int count;			/* number of input characters */{/* Characters have just been typed in.  Process, save, and echo them.  Return * the number of characters processed. */  int ch, sig, ct;  int timeset = FALSE;  static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };  for (ct = 0; ct < count; ct++) {	/* Take one character. */	ch = *buf++ & BYTE;	/* Strip to seven bits? */	if (tp->tty_termios.c_iflag & ISTRIP) ch &= 0x7F;	/* Input extensions? */	if (tp->tty_termios.c_lflag & IEXTEN) {

⌨️ 快捷键说明

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