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

📄 tty_ioctl.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 2 页
字号:
int tty_ioctl(struct inode * inode, struct file * file,	unsigned int cmd, unsigned long arg){	struct tty_struct * tty;	struct tty_struct * other_tty;	struct tty_struct * termios_tty;	pid_t pgrp;	int dev;	int termios_dev;	int retval;	if (MAJOR(file->f_rdev) != TTY_MAJOR) {		printk("tty_ioctl: tty pseudo-major != TTY_MAJOR\n");		return -EINVAL;	}	dev = MINOR(file->f_rdev);	tty = TTY_TABLE(dev);	if (!tty)		return -EINVAL;	if (IS_A_PTY(dev))		other_tty = tty_table[PTY_OTHER(dev)];	else		other_tty = NULL;	if (IS_A_PTY_MASTER(dev)) {		termios_tty = other_tty;		termios_dev = PTY_OTHER(dev);	} else {		termios_tty = tty;		termios_dev = dev;	}	switch (cmd) {		case TCGETS:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (struct termios));			if (retval)				return retval;			memcpy_tofs((struct termios *) arg,				    termios_tty->termios,				    sizeof (struct termios));			return 0;		case TCSETSF:		case TCSETSW:		case TCSETS:			retval = check_change(termios_tty, termios_dev);			if (retval)				return retval;			if (cmd == TCSETSF || cmd == TCSETSW) {				if (cmd == TCSETSF)					flush_input(termios_tty);				wait_until_sent(termios_tty, 0);			}			return set_termios(termios_tty, (struct termios *) arg,					   termios_dev);		case TCGETA:			return get_termio(termios_tty,(struct termio *) arg);		case TCSETAF:		case TCSETAW:		case TCSETA:			retval = check_change(termios_tty, termios_dev);			if (retval)				return retval;			if (cmd == TCSETAF || cmd == TCSETAW) {				if (cmd == TCSETAF)					flush_input(termios_tty);				wait_until_sent(termios_tty, 0);			}			return set_termio(termios_tty, (struct termio *) arg,					  termios_dev);		case TCXONC:			retval = check_change(tty, dev);			if (retval)				return retval;			switch (arg) {			case TCOOFF:				stop_tty(tty);				break;			case TCOON:				start_tty(tty);				break;			case TCIOFF:				if (STOP_CHAR(tty) != __DISABLED_CHAR)					put_tty_queue(STOP_CHAR(tty),						      &tty->write_q);				break;			case TCION:				if (START_CHAR(tty) != __DISABLED_CHAR)					put_tty_queue(START_CHAR(tty),						      &tty->write_q);				break;			default:				return -EINVAL;			}			return 0;		case TCFLSH:			retval = check_change(tty, dev);			if (retval)				return retval;			switch (arg) {			case TCIFLUSH:				flush_input(tty);				break;			case TCIOFLUSH:				flush_input(tty);				/* fall through */			case TCOFLUSH:				flush_output(tty);				break;			default:				return -EINVAL;			}			return 0;		case TIOCEXCL:			set_bit(TTY_EXCLUSIVE, &tty->flags);			return 0;		case TIOCNXCL:			clear_bit(TTY_EXCLUSIVE, &tty->flags);			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 >= 0))				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 == dev)							p->tty = -1;				} else					return -EPERM;			}			current->tty = dev;			tty->session = current->session;			tty->pgrp = current->pgrp;			return 0;		case TIOCGPGRP:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (pid_t));			if (retval)				return retval;			if (current->tty != termios_dev)				return -ENOTTY;			put_fs_long(termios_tty->pgrp, (pid_t *) arg);			return 0;		case TIOCSPGRP:			retval = check_change(termios_tty, termios_dev);			if (retval)				return retval;			if ((current->tty < 0) ||			    (current->tty != termios_dev) ||			    (termios_tty->session != current->session))				return -ENOTTY;			pgrp = get_fs_long((pid_t *) arg);			if (pgrp < 0)				return -EINVAL;			if (session_of_pgrp(pgrp) != current->session)				return -EPERM;			termios_tty->pgrp = pgrp;			return 0;		case TIOCOUTQ:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (unsigned long));			if (retval)				return retval;			put_fs_long(CHARS(&tty->write_q),				    (unsigned long *) arg);			return 0;		case TIOCINQ:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (unsigned long));			if (retval)				return retval;			if (L_ICANON(tty))				put_fs_long(inq_canon(tty),					(unsigned long *) arg);			else				put_fs_long(CHARS(&tty->secondary),					(unsigned long *) arg);			return 0;		case TIOCSTI:			if ((current->tty != dev) && !suser())				return -EPERM;			retval = verify_area(VERIFY_READ, (void *) arg, 1);			if (retval)				return retval;			put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);			TTY_READ_FLUSH(tty);			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:			if (IS_A_PTY_MASTER(dev))				set_window_size(other_tty,(struct winsize *) arg);			return set_window_size(tty,(struct winsize *) arg);		case TIOCLINUX:			switch (get_fs_byte((char *)arg))			{				case 0: 					return do_screendump(arg);				case 1: 					return do_get_ps_info(arg);#ifdef CONFIG_SELECTION				case 2:					return set_selection(arg);				case 3:					return paste_selection(tty);				case 4:					unblank_screen();					return 0;#endif /* CONFIG_SELECTION */				default: 					return -EINVAL;			}		case TIOCCONS:			if (IS_A_CONSOLE(dev)) {				if (!suser())					return -EPERM;				redirect = NULL;				return 0;			}			if (redirect)				return -EBUSY;			if (!suser())				return -EPERM;			if (IS_A_PTY_MASTER(dev))				redirect = other_tty;			else if (IS_A_PTY_SLAVE(dev))				redirect = tty;			else				return -ENOTTY;			return 0;		case FIONBIO:			arg = get_fs_long((unsigned long *) arg);			if (arg)				file->f_flags |= O_NONBLOCK;			else				file->f_flags &= ~O_NONBLOCK;			return 0;		case TIOCNOTTY:			if (current->tty != dev)				return -ENOTTY;			if (current->leader)				disassociate_ctty(0);			current->tty = -1;			return 0;		case TIOCGETD:			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (unsigned long));			if (retval)				return retval;			put_fs_long(tty->disc, (unsigned long *) arg);			return 0;		case TIOCSETD:			retval = check_change(tty, dev);			if (retval)				return retval;			arg = get_fs_long((unsigned long *) arg);			return tty_set_ldisc(tty, arg);		case TIOCGLCKTRMIOS:			arg = get_fs_long((unsigned long *) arg);			retval = verify_area(VERIFY_WRITE, (void *) arg,					     sizeof (struct termios));			if (retval)				return retval;			memcpy_tofs((struct termios *) arg,				    &termios_locked[termios_dev],				    sizeof (struct termios));			return 0;		case TIOCSLCKTRMIOS:			if (!suser())				return -EPERM;			arg = get_fs_long((unsigned long *) arg);			memcpy_fromfs(&termios_locked[termios_dev],				      (struct termios *) arg,				      sizeof (struct termios));			return 0;		case TIOCPKT:			if (!IS_A_PTY_MASTER(dev))				return -ENOTTY;			retval = verify_area(VERIFY_READ, (void *) arg,					     sizeof (unsigned long));			if (retval)				return retval;			if (get_fs_long(arg)) {				if (!tty->packet) {					tty->packet = 1;					tty->link->ctrl_status = 0;				}			} else				tty->packet = 0;			return 0;		case TCSBRK: case TCSBRKP:			retval = check_change(tty, dev);			if (retval)				return retval;			wait_until_sent(tty, 0);			if (!tty->ioctl)				return 0;			tty->ioctl(tty, file, cmd, arg);			return 0;		default:			if (tty->ioctl) {				retval = (tty->ioctl)(tty, file, cmd, arg);				if (retval != -EINVAL)					return retval;			}			if (ldiscs[tty->disc].ioctl) {				retval = (ldiscs[tty->disc].ioctl)					(tty, file, cmd, arg);				return retval;			}			return -EINVAL;	}}

⌨️ 快捷键说明

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