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

📄 tty_io.c

📁 unix/linux 编程实践一书的所有源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (retval)				return retval;			ch = get_user((char *) arg);			tty->ldisc.receive_buf(tty, &ch, &mbz, 1);			return 0;		case TIOCGWINSZ:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (struct winsize));			if (retval)				return retval;			memcpy_tofs((struct winsize *) arg, &tty->winsize,				    sizeof (struct winsize));			return 0;		case TIOCSWINSZ:			retval = verify_area(VERIFY_READ, (void *) arg,					     sizeof (struct winsize));			if (retval)				return retval;						memcpy_fromfs(&tmp_ws, (struct winsize *) arg,				      sizeof (struct winsize));			if (memcmp(&tmp_ws, &tty->winsize,				   sizeof(struct winsize))) {				if (tty->pgrp > 0)					kill_pg(tty->pgrp, SIGWINCH, 1);				if ((real_tty->pgrp != tty->pgrp) &&				    (real_tty->pgrp > 0))					kill_pg(real_tty->pgrp, SIGWINCH, 1);			}			tty->winsize = tmp_ws;			real_tty->winsize = tmp_ws;			return 0;		case TIOCCONS:			if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE) {				if (!suser())					return -EPERM;				redirect = NULL;				return 0;			}			if (redirect)				return -EBUSY;			redirect = real_tty;			return 0;		case FIONBIO:			retval = verify_area(VERIFY_READ, (void *) arg, sizeof(int));			if (retval)				return retval;			arg = get_user((unsigned int *) arg);			if (arg)				file->f_flags |= O_NONBLOCK;			else				file->f_flags &= ~O_NONBLOCK;			return 0;		case TIOCEXCL:			set_bit(TTY_EXCLUSIVE, &tty->flags);			return 0;		case TIOCNXCL:			clear_bit(TTY_EXCLUSIVE, &tty->flags);			return 0;		case TIOCNOTTY:			if (current->tty != tty)				return -ENOTTY;			if (current->leader)				disassociate_ctty(0);			current->tty = NULL;			return 0;		case TIOCSCTTY:			if (current->leader &&			    (current->session == tty->session))				return 0;			/*			 * The process must be a session leader and			 * not have a controlling tty already.			 */			if (!current->leader || current->tty)				return -EPERM;			if (tty->session > 0) {				/*				 * This tty is already the controlling				 * tty for another session group!				 */				if ((arg == 1) && suser()) {					/*					 * Steal it away					 */					struct task_struct *p;					for_each_task(p)						if (p->tty == tty)							p->tty = NULL;				} else					return -EPERM;			}			current->tty = tty;			current->tty_old_pgrp = 0;			tty->session = current->session;			tty->pgrp = current->pgrp;			return 0;		case TIOCGPGRP:			/*			 * (tty == real_tty) is a cheap way of			 * testing if the tty is NOT a master pty.			 */			if (tty == real_tty && current->tty != real_tty)				return -ENOTTY;			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (pid_t));			if (retval)				return retval;			put_user(real_tty->pgrp, (pid_t *) arg);			return 0;		case TIOCSPGRP:			retval = tty_check_change(real_tty);			if (retval == -EIO)				return -ENOTTY;			if (retval)				return retval;			if (!current->tty ||			    (current->tty != real_tty) ||			    (real_tty->session != current->session))				return -ENOTTY;			pgrp = get_user((pid_t *) arg);			if (pgrp < 0)				return -EINVAL;			if (session_of_pgrp(pgrp) != current->session)				return -EPERM;			real_tty->pgrp = pgrp;			return 0;		case TIOCGETD:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (int));			if (retval)				return retval;			put_user(tty->ldisc.num, (int *) arg);			return 0;		case TIOCSETD:			retval = tty_check_change(tty);			if (retval)				return retval;			retval = verify_area(VERIFY_READ, (void *) arg,					     sizeof (int));			if (retval)				return retval;			arg = get_user((int *) arg);			return tty_set_ldisc(tty, arg);		case TIOCLINUX:			if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)				return -EINVAL;			if (current->tty != tty && !suser())				return -EPERM;			retval = verify_area(VERIFY_READ, (void *) arg, 1);			if (retval)				return retval;			switch (retval = get_user((char *)arg))			{				case 0:				case 8:				case 9:					printk("TIOCLINUX (0/8/9) ioctl is gone - use /dev/vcs\n");					return -EINVAL;#if 0				case 1:					printk("Deprecated TIOCLINUX (1) ioctl\n");					return do_get_ps_info(arg);#endif				case 2:					return set_selection(arg, tty, 1);				case 3:					return paste_selection(tty);				case 4:					do_unblank_screen();					return 0;				case 5:					return sel_loadlut(arg);				case 6:			/*			 * Make it possible to react to Shift+Mousebutton.			 * Note that 'shift_state' is an undocumented			 * kernel-internal variable; programs not closely			 * related to the kernel should not use this.			 */					retval = verify_area(VERIFY_WRITE, (void *) arg, 1);					if (retval)						return retval;					put_user(shift_state,(char *) arg);					return 0;				case 7:					retval = verify_area(VERIFY_WRITE, (void *) arg, 1);					if (retval)						return retval;					put_user(mouse_reporting(),(char *) arg);					return 0;				case 10:					set_vesa_blanking(arg);					return 0;				case 11:	/* set kmsg redirect */					if (!suser())						return -EPERM;					retval = verify_area(VERIFY_READ,						(void *) arg+1, 1);					if (retval)						return retval;					kmsg_redirect = get_user((char *)arg+1);					return 0;				case 12:	/* get fg_console */					return fg_console;				default: 					return -EINVAL;			}		case TIOCTTYGSTRUCT:			retval = verify_area(VERIFY_WRITE, (void *) arg,						sizeof(struct tty_struct));			if (retval)				return retval;			memcpy_tofs((struct tty_struct *) arg,				    tty, sizeof(struct tty_struct));			return 0;		default:			if (tty->driver.ioctl) {				retval = (tty->driver.ioctl)(tty, file,							     cmd, arg);				if (retval != -ENOIOCTLCMD)					return retval;			}			if (tty->ldisc.ioctl) {				retval = (tty->ldisc.ioctl)(tty, file,							    cmd, arg);				if (retval != -ENOIOCTLCMD)					return retval;			}			return -EINVAL;		}}/* * This implements the "Secure Attention Key" ---  the idea is to * prevent trojan horses by killing all processes associated with this * tty when the user hits the "Secure Attention Key".  Required for * super-paranoid applications --- see the Orange Book for more details. *  * This code could be nicer; ideally it should send a HUP, wait a few * seconds, then send a INT, and then a KILL signal.  But you then * have to coordinate with the init process, since all processes associated * with the current tty must be dead before the new getty is allowed * to spawn. */void do_SAK( struct tty_struct *tty){#ifdef TTY_SOFT_SAK	tty_hangup(tty);#else	struct task_struct **p;	int session;	int		i;	struct file	*filp;		if (!tty)		return;	session  = tty->session;	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer(tty);	if (tty->driver.flush_buffer)		tty->driver.flush_buffer(tty); 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {		if (!(*p))			continue;		if (((*p)->tty == tty) ||		    ((session > 0) && ((*p)->session == session)))			send_sig(SIGKILL, *p, 1);		else if ((*p)->files) {			for (i=0; i < NR_OPEN; i++) {				filp = (*p)->files->fd[i];				if (filp && (filp->f_op == &tty_fops) &&				    (filp->private_data == tty)) {					send_sig(SIGKILL, *p, 1);					break;				}			}		}	}#endif}/* * This routine is called out of the software interrupt to flush data * from the flip buffer to the line discipline. */static void flush_to_ldisc(void *private_){	struct tty_struct *tty = (struct tty_struct *) private_;	unsigned char	*cp;	char		*fp;	int		count;	if (tty->flip.buf_num) {		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;		tty->flip.buf_num = 0;		cli();		tty->flip.char_buf_ptr = tty->flip.char_buf;		tty->flip.flag_buf_ptr = tty->flip.flag_buf;	} else {		cp = tty->flip.char_buf;		fp = tty->flip.flag_buf;		tty->flip.buf_num = 1;		cli();		tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;		tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;	}	count = tty->flip.count;	tty->flip.count = 0;	sti();	#if 0	if (count > tty->max_flip_cnt)		tty->max_flip_cnt = count;#endif	tty->ldisc.receive_buf(tty, cp, fp, count);}/* * This subroutine initializes a tty structure. */static void initialize_tty_struct(struct tty_struct *tty){	memset(tty, 0, sizeof(struct tty_struct));	tty->magic = TTY_MAGIC;	tty->ldisc = ldiscs[N_TTY];	tty->pgrp = -1;	tty->flip.char_buf_ptr = tty->flip.char_buf;	tty->flip.flag_buf_ptr = tty->flip.flag_buf;	tty->flip.tqueue.routine = flush_to_ldisc;	tty->flip.tqueue.data = tty;}/* * The default put_char routine if the driver did not define one. */void tty_default_put_char(struct tty_struct *tty, unsigned char ch){	tty->driver.write(tty, 0, &ch, 1);}/* * Called by a tty driver to register itself. */int tty_register_driver(struct tty_driver *driver){	int error;	if (driver->flags & TTY_DRIVER_INSTALLED)		return 0;	error = register_chrdev(driver->major, driver->name, &tty_fops);	if (error < 0)		return error;	else if(driver->major == 0)		driver->major = error;	if (!driver->put_char)		driver->put_char = tty_default_put_char;		driver->prev = 0;	driver->next = tty_drivers;	if (tty_drivers) tty_drivers->prev = driver;	tty_drivers = driver;	return error;}/* * Called by a tty driver to unregister itself. */int tty_unregister_driver(struct tty_driver *driver){	int	retval;	struct tty_driver *p;	int	found = 0;	const char *othername = NULL;		if (*driver->refcount)		return -EBUSY;	for (p = tty_drivers; p; p = p->next) {		if (p == driver)			found++;		else if (p->major == driver->major)			othername = p->name;	}		if (!found)		return -ENOENT;	if (othername == NULL) {		retval = unregister_chrdev(driver->major, driver->name);		if (retval)			return retval;	} else		register_chrdev(driver->major, othername, &tty_fops);	if (driver->prev)		driver->prev->next = driver->next;	else		tty_drivers = driver->next;		if (driver->next)		driver->next->prev = driver->prev;	return 0;}/* * Initialize the console device. This is called *early*, so * we can't necessarily depend on lots of kernel help here. * Just do some early initializations, and do the complex setup * later. */long console_init(long kmem_start, long kmem_end){	/* Setup the default TTY line discipline. */	memset(ldiscs, 0, sizeof(ldiscs));	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);	/*	 * Set up the standard termios.  Individual tty drivers may 	 * deviate from this; this is used as a template.	 */	memset(&tty_std_termios, 0, sizeof(struct termios));	memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);	tty_std_termios.c_iflag = ICRNL | IXON;	tty_std_termios.c_oflag = OPOST | ONLCR;	tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;	tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |		ECHOCTL | ECHOKE | IEXTEN;	/*	 * set up the console device so that later boot sequences can 	 * inform about problems etc..	 */	return con_init(kmem_start);}static struct tty_driver dev_tty_driver, dev_console_driver;/* * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */int tty_init(void){	if (sizeof(struct tty_struct) > PAGE_SIZE)		panic("size of tty structure > PAGE_SIZE!");	/*	 * dev_tty_driver and dev_console_driver are actually magic	 * devices which get redirected at open time.  Nevertheless,	 * we register them so that register_chrdev is called	 * appropriately.	 */	memset(&dev_tty_driver, 0, sizeof(struct tty_driver));	dev_tty_driver.magic = TTY_DRIVER_MAGIC;	dev_tty_driver.name = "tty";	dev_tty_driver.name_base = 0;	dev_tty_driver.major = TTY_MAJOR;	dev_tty_driver.minor_start = 0;	dev_tty_driver.num = 1;		if (tty_register_driver(&dev_tty_driver))		panic("Couldn't register /dev/tty driver\n");	dev_console_driver = dev_tty_driver;	dev_console_driver.name = "console";	dev_console_driver.major = TTYAUX_MAJOR;	if (tty_register_driver(&dev_console_driver))		panic("Couldn't register /dev/console driver\n");		kbd_init();#ifdef CONFIG_SERIAL	rs_init();#endif#ifdef CONFIG_SCC	scc_init();#endif#ifdef CONFIG_CYCLADES	cy_init();#endif#ifdef CONFIG_STALLION	stl_init();#endif#ifdef CONFIG_ISTALLION	stli_init();#endif#ifdef CONFIG_DIGI	pcxe_init();#endif#ifdef CONFIG_RISCOM8	riscom8_init();#endif#ifdef CONFIG_BAYCOM	baycom_init();#endif#ifdef CONFIG_SPECIALIX	specialix_init();#endif	pty_init();	vcs_init();	return 0;}

⌨️ 快捷键说明

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