ia64/xen-unstable

changeset 2083:f04ec9f1af56

bitkeeper revision 1.1148 (411131f0ZrZwSSvmzkGHMRh1xnTq_Q)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xeno.bk-26dom0
into freefall.cl.cam.ac.uk:/local/scratch/cl349/xeno.bk-26dom0
author cl349@freefall.cl.cam.ac.uk
date Wed Aug 04 18:58:56 2004 +0000 (2004-08-04)
parents 41708c9ea59d 126bcd4c8898
children 81aca503df11
files .rootkeys linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c linux-2.6.7-xen-sparse/drivers/char/tty_io.c linux-2.6.7-xen-sparse/drivers/xen/console/console.c
line diff
     1.1 --- a/.rootkeys	Wed Aug 04 17:10:01 2004 +0000
     1.2 +++ b/.rootkeys	Wed Aug 04 18:58:56 2004 +0000
     1.3 @@ -170,6 +170,7 @@ 40f56239sFcjHiIRmnObRIDF-zaeKQ linux-2.6
     1.4  40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.7-xen-sparse/arch/xen/kernel/reboot.c
     1.5  3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.7-xen-sparse/arch/xen/kernel/xen_proc.c
     1.6  4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.7-xen-sparse/drivers/char/mem.c
     1.7 +4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.7-xen-sparse/drivers/char/tty_io.c
     1.8  40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.7-xen-sparse/drivers/xen/Makefile
     1.9  410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.7-xen-sparse/drivers/xen/blkback/Makefile
    1.10  4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.7-xen-sparse/drivers/xen/blkback/blkback.c
     2.1 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c	Wed Aug 04 17:10:01 2004 +0000
     2.2 +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/kernel/setup.c	Wed Aug 04 18:58:56 2004 +0000
     2.3 @@ -1243,12 +1243,15 @@ void __init setup_arch(char **cmdline_p)
     2.4  #endif
     2.5  #endif
     2.6  	} else {
     2.7 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
     2.8 +		extern const struct consw xennull_con;
     2.9 +		extern int console_use_vt;
    2.10  #if defined(CONFIG_VGA_CONSOLE)
    2.11  		/* disable VGA driver */
    2.12  		ORIG_VIDEO_ISVGA = VIDEO_TYPE_VLFB;
    2.13  #endif
    2.14 -#if defined(CONFIG_DUMMY_CONSOLE)
    2.15 -		conswitchp = &dummy_con;
    2.16 +		conswitchp = &xennull_con;
    2.17 +		console_use_vt = 0;
    2.18  #endif
    2.19  	}
    2.20  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/linux-2.6.7-xen-sparse/drivers/char/tty_io.c	Wed Aug 04 18:58:56 2004 +0000
     3.3 @@ -0,0 +1,2447 @@
     3.4 +/*
     3.5 + *  linux/drivers/char/tty_io.c
     3.6 + *
     3.7 + *  Copyright (C) 1991, 1992  Linus Torvalds
     3.8 + */
     3.9 +
    3.10 +/*
    3.11 + * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
    3.12 + * or rs-channels. It also implements echoing, cooked mode etc.
    3.13 + *
    3.14 + * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
    3.15 + *
    3.16 + * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
    3.17 + * tty_struct and tty_queue structures.  Previously there was an array
    3.18 + * of 256 tty_struct's which was statically allocated, and the
    3.19 + * tty_queue structures were allocated at boot time.  Both are now
    3.20 + * dynamically allocated only when the tty is open.
    3.21 + *
    3.22 + * Also restructured routines so that there is more of a separation
    3.23 + * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
    3.24 + * the low-level tty routines (serial.c, pty.c, console.c).  This
    3.25 + * makes for cleaner and more compact code.  -TYT, 9/17/92 
    3.26 + *
    3.27 + * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
    3.28 + * which can be dynamically activated and de-activated by the line
    3.29 + * discipline handling modules (like SLIP).
    3.30 + *
    3.31 + * NOTE: pay no attention to the line discipline code (yet); its
    3.32 + * interface is still subject to change in this version...
    3.33 + * -- TYT, 1/31/92
    3.34 + *
    3.35 + * Added functionality to the OPOST tty handling.  No delays, but all
    3.36 + * other bits should be there.
    3.37 + *	-- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
    3.38 + *
    3.39 + * Rewrote canonical mode and added more termios flags.
    3.40 + * 	-- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94
    3.41 + *
    3.42 + * Reorganized FASYNC support so mouse code can share it.
    3.43 + *	-- ctm@ardi.com, 9Sep95
    3.44 + *
    3.45 + * New TIOCLINUX variants added.
    3.46 + *	-- mj@k332.feld.cvut.cz, 19-Nov-95
    3.47 + * 
    3.48 + * Restrict vt switching via ioctl()
    3.49 + *      -- grif@cs.ucr.edu, 5-Dec-95
    3.50 + *
    3.51 + * Move console and virtual terminal code to more appropriate files,
    3.52 + * implement CONFIG_VT and generalize console device interface.
    3.53 + *	-- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
    3.54 + *
    3.55 + * Rewrote init_dev and release_dev to eliminate races.
    3.56 + *	-- Bill Hawes <whawes@star.net>, June 97
    3.57 + *
    3.58 + * Added devfs support.
    3.59 + *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 13-Jan-1998
    3.60 + *
    3.61 + * Added support for a Unix98-style ptmx device.
    3.62 + *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
    3.63 + *
    3.64 + * Reduced memory usage for older ARM systems
    3.65 + *      -- Russell King <rmk@arm.linux.org.uk>
    3.66 + *
    3.67 + * Move do_SAK() into process context.  Less stack use in devfs functions.
    3.68 + * alloc_tty_struct() always uses kmalloc() -- Andrew Morton <andrewm@uow.edu.eu> 17Mar01
    3.69 + */
    3.70 +
    3.71 +#include <linux/config.h>
    3.72 +#include <linux/types.h>
    3.73 +#include <linux/major.h>
    3.74 +#include <linux/errno.h>
    3.75 +#include <linux/signal.h>
    3.76 +#include <linux/fcntl.h>
    3.77 +#include <linux/sched.h>
    3.78 +#include <linux/interrupt.h>
    3.79 +#include <linux/tty.h>
    3.80 +#include <linux/tty_driver.h>
    3.81 +#include <linux/tty_flip.h>
    3.82 +#include <linux/devpts_fs.h>
    3.83 +#include <linux/file.h>
    3.84 +#include <linux/console.h>
    3.85 +#include <linux/timer.h>
    3.86 +#include <linux/ctype.h>
    3.87 +#include <linux/kd.h>
    3.88 +#include <linux/mm.h>
    3.89 +#include <linux/string.h>
    3.90 +#include <linux/slab.h>
    3.91 +#include <linux/poll.h>
    3.92 +#include <linux/proc_fs.h>
    3.93 +#include <linux/init.h>
    3.94 +#include <linux/module.h>
    3.95 +#include <linux/smp_lock.h>
    3.96 +#include <linux/device.h>
    3.97 +
    3.98 +#include <asm/uaccess.h>
    3.99 +#include <asm/system.h>
   3.100 +#include <asm/bitops.h>
   3.101 +
   3.102 +#include <linux/kbd_kern.h>
   3.103 +#include <linux/vt_kern.h>
   3.104 +#include <linux/selection.h>
   3.105 +#include <linux/devfs_fs_kernel.h>
   3.106 +
   3.107 +#include <linux/kmod.h>
   3.108 +
   3.109 +#undef TTY_DEBUG_HANGUP
   3.110 +
   3.111 +#define TTY_PARANOIA_CHECK 1
   3.112 +#define CHECK_TTY_COUNT 1
   3.113 +
   3.114 +struct termios tty_std_termios = {	/* for the benefit of tty drivers  */
   3.115 +	.c_iflag = ICRNL | IXON,
   3.116 +	.c_oflag = OPOST | ONLCR,
   3.117 +	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
   3.118 +	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
   3.119 +		   ECHOCTL | ECHOKE | IEXTEN,
   3.120 +	.c_cc = INIT_C_CC
   3.121 +};
   3.122 +
   3.123 +EXPORT_SYMBOL(tty_std_termios);
   3.124 +
   3.125 +LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
   3.126 +struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
   3.127 +
   3.128 +/* Semaphore to protect creating and releasing a tty */
   3.129 +DECLARE_MUTEX(tty_sem);
   3.130 +
   3.131 +#ifdef CONFIG_VT
   3.132 +int console_use_vt = 1;
   3.133 +#endif
   3.134 +#ifdef CONFIG_UNIX98_PTYS
   3.135 +extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
   3.136 +extern int pty_limit;		/* Config limit on Unix98 ptys */
   3.137 +#endif
   3.138 +
   3.139 +extern void disable_early_printk(void);
   3.140 +
   3.141 +static void initialize_tty_struct(struct tty_struct *tty);
   3.142 +
   3.143 +static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
   3.144 +static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
   3.145 +ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *);
   3.146 +static unsigned int tty_poll(struct file *, poll_table *);
   3.147 +static int tty_open(struct inode *, struct file *);
   3.148 +static int tty_release(struct inode *, struct file *);
   3.149 +int tty_ioctl(struct inode * inode, struct file * file,
   3.150 +	      unsigned int cmd, unsigned long arg);
   3.151 +static int tty_fasync(int fd, struct file * filp, int on);
   3.152 +extern void rs_360_init(void);
   3.153 +static void release_mem(struct tty_struct *tty, int idx);
   3.154 +
   3.155 +
   3.156 +static struct tty_struct *alloc_tty_struct(void)
   3.157 +{
   3.158 +	struct tty_struct *tty;
   3.159 +
   3.160 +	tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
   3.161 +	if (tty)
   3.162 +		memset(tty, 0, sizeof(struct tty_struct));
   3.163 +	return tty;
   3.164 +}
   3.165 +
   3.166 +static inline void free_tty_struct(struct tty_struct *tty)
   3.167 +{
   3.168 +	kfree(tty);
   3.169 +}
   3.170 +
   3.171 +#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
   3.172 +
   3.173 +char *tty_name(struct tty_struct *tty, char *buf)
   3.174 +{
   3.175 +	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
   3.176 +		strcpy(buf, "NULL tty");
   3.177 +	else
   3.178 +		strcpy(buf, tty->name);
   3.179 +	return buf;
   3.180 +}
   3.181 +
   3.182 +EXPORT_SYMBOL(tty_name);
   3.183 +
   3.184 +inline int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
   3.185 +			      const char *routine)
   3.186 +{
   3.187 +#ifdef TTY_PARANOIA_CHECK
   3.188 +	if (!tty) {
   3.189 +		printk(KERN_WARNING
   3.190 +			"null TTY for (%d:%d) in %s\n",
   3.191 +			imajor(inode), iminor(inode), routine);
   3.192 +		return 1;
   3.193 +	}
   3.194 +	if (tty->magic != TTY_MAGIC) {
   3.195 +		printk(KERN_WARNING
   3.196 +			"bad magic number for tty struct (%d:%d) in %s\n",
   3.197 +			imajor(inode), iminor(inode), routine);
   3.198 +		return 1;
   3.199 +	}
   3.200 +#endif
   3.201 +	return 0;
   3.202 +}
   3.203 +
   3.204 +static int check_tty_count(struct tty_struct *tty, const char *routine)
   3.205 +{
   3.206 +#ifdef CHECK_TTY_COUNT
   3.207 +	struct list_head *p;
   3.208 +	int count = 0;
   3.209 +	
   3.210 +	file_list_lock();
   3.211 +	list_for_each(p, &tty->tty_files) {
   3.212 +		count++;
   3.213 +	}
   3.214 +	file_list_unlock();
   3.215 +	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
   3.216 +	    tty->driver->subtype == PTY_TYPE_SLAVE &&
   3.217 +	    tty->link && tty->link->count)
   3.218 +		count++;
   3.219 +	if (tty->count != count) {
   3.220 +		printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) "
   3.221 +				    "!= #fd's(%d) in %s\n",
   3.222 +		       tty->name, tty->count, count, routine);
   3.223 +		return count;
   3.224 +       }	
   3.225 +#endif
   3.226 +	return 0;
   3.227 +}
   3.228 +
   3.229 +int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
   3.230 +{
   3.231 +	if (disc < N_TTY || disc >= NR_LDISCS)
   3.232 +		return -EINVAL;
   3.233 +	
   3.234 +	if (new_ldisc) {
   3.235 +		ldiscs[disc] = *new_ldisc;
   3.236 +		ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
   3.237 +		ldiscs[disc].num = disc;
   3.238 +	} else
   3.239 +		memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
   3.240 +	
   3.241 +	return 0;
   3.242 +}
   3.243 +
   3.244 +EXPORT_SYMBOL(tty_register_ldisc);
   3.245 +
   3.246 +/* Set the discipline of a tty line. */
   3.247 +static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
   3.248 +{
   3.249 +	int	retval = 0;
   3.250 +	struct	tty_ldisc o_ldisc;
   3.251 +	char buf[64];
   3.252 +
   3.253 +	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
   3.254 +		return -EINVAL;
   3.255 +	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
   3.256 +	/* Cyrus Durgin <cider@speakeasy.org> */
   3.257 +	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
   3.258 +		request_module("tty-ldisc-%d", ldisc);
   3.259 +	}
   3.260 +	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
   3.261 +		return -EINVAL;
   3.262 +
   3.263 +	if (tty->ldisc.num == ldisc)
   3.264 +		return 0;	/* We are already in the desired discipline */
   3.265 +
   3.266 +	if (!try_module_get(ldiscs[ldisc].owner))
   3.267 +	       	return -EINVAL;
   3.268 +	
   3.269 +	o_ldisc = tty->ldisc;
   3.270 +
   3.271 +	tty_wait_until_sent(tty, 0);
   3.272 +	
   3.273 +	/* Shutdown the current discipline. */
   3.274 +	if (tty->ldisc.close)
   3.275 +		(tty->ldisc.close)(tty);
   3.276 +
   3.277 +	/* Now set up the new line discipline. */
   3.278 +	tty->ldisc = ldiscs[ldisc];
   3.279 +	tty->termios->c_line = ldisc;
   3.280 +	if (tty->ldisc.open)
   3.281 +		retval = (tty->ldisc.open)(tty);
   3.282 +	if (retval < 0) {
   3.283 +		tty->ldisc = o_ldisc;
   3.284 +		tty->termios->c_line = tty->ldisc.num;
   3.285 +		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
   3.286 +			tty->ldisc = ldiscs[N_TTY];
   3.287 +			tty->termios->c_line = N_TTY;
   3.288 +			if (tty->ldisc.open) {
   3.289 +				int r = tty->ldisc.open(tty);
   3.290 +
   3.291 +				if (r < 0)
   3.292 +					panic("Couldn't open N_TTY ldisc for "
   3.293 +					      "%s --- error %d.",
   3.294 +					      tty_name(tty, buf), r);
   3.295 +			}
   3.296 +		}
   3.297 +	} else {
   3.298 +		module_put(o_ldisc.owner);
   3.299 +	}
   3.300 +	
   3.301 +	if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
   3.302 +		tty->driver->set_ldisc(tty);
   3.303 +	return retval;
   3.304 +}
   3.305 +
   3.306 +/*
   3.307 + * This routine returns a tty driver structure, given a device number
   3.308 + */
   3.309 +struct tty_driver *get_tty_driver(dev_t device, int *index)
   3.310 +{
   3.311 +	struct tty_driver *p;
   3.312 +
   3.313 +	list_for_each_entry(p, &tty_drivers, tty_drivers) {
   3.314 +		dev_t base = MKDEV(p->major, p->minor_start);
   3.315 +		if (device < base || device >= base + p->num)
   3.316 +			continue;
   3.317 +		*index = device - base;
   3.318 +		return p;
   3.319 +	}
   3.320 +	return NULL;
   3.321 +}
   3.322 +
   3.323 +/*
   3.324 + * If we try to write to, or set the state of, a terminal and we're
   3.325 + * not in the foreground, send a SIGTTOU.  If the signal is blocked or
   3.326 + * ignored, go ahead and perform the operation.  (POSIX 7.2)
   3.327 + */
   3.328 +int tty_check_change(struct tty_struct * tty)
   3.329 +{
   3.330 +	if (current->signal->tty != tty)
   3.331 +		return 0;
   3.332 +	if (tty->pgrp <= 0) {
   3.333 +		printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
   3.334 +		return 0;
   3.335 +	}
   3.336 +	if (process_group(current) == tty->pgrp)
   3.337 +		return 0;
   3.338 +	if (is_ignored(SIGTTOU))
   3.339 +		return 0;
   3.340 +	if (is_orphaned_pgrp(process_group(current)))
   3.341 +		return -EIO;
   3.342 +	(void) kill_pg(process_group(current), SIGTTOU, 1);
   3.343 +	return -ERESTARTSYS;
   3.344 +}
   3.345 +
   3.346 +EXPORT_SYMBOL(tty_check_change);
   3.347 +
   3.348 +static ssize_t hung_up_tty_read(struct file * file, char __user * buf,
   3.349 +				size_t count, loff_t *ppos)
   3.350 +{
   3.351 +	/* Can't seek (pread) on ttys.  */
   3.352 +	if (ppos != &file->f_pos)
   3.353 +		return -ESPIPE;
   3.354 +	return 0;
   3.355 +}
   3.356 +
   3.357 +static ssize_t hung_up_tty_write(struct file * file, const char __user * buf,
   3.358 +				 size_t count, loff_t *ppos)
   3.359 +{
   3.360 +	/* Can't seek (pwrite) on ttys.  */
   3.361 +	if (ppos != &file->f_pos)
   3.362 +		return -ESPIPE;
   3.363 +	return -EIO;
   3.364 +}
   3.365 +
   3.366 +/* No kernel lock held - none needed ;) */
   3.367 +static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait)
   3.368 +{
   3.369 +	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
   3.370 +}
   3.371 +
   3.372 +static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
   3.373 +			     unsigned int cmd, unsigned long arg)
   3.374 +{
   3.375 +	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
   3.376 +}
   3.377 +
   3.378 +static struct file_operations tty_fops = {
   3.379 +	.llseek		= no_llseek,
   3.380 +	.read		= tty_read,
   3.381 +	.write		= tty_write,
   3.382 +	.poll		= tty_poll,
   3.383 +	.ioctl		= tty_ioctl,
   3.384 +	.open		= tty_open,
   3.385 +	.release	= tty_release,
   3.386 +	.fasync		= tty_fasync,
   3.387 +};
   3.388 +
   3.389 +static struct file_operations console_fops = {
   3.390 +	.llseek		= no_llseek,
   3.391 +	.read		= tty_read,
   3.392 +	.write		= redirected_tty_write,
   3.393 +	.poll		= tty_poll,
   3.394 +	.ioctl		= tty_ioctl,
   3.395 +	.open		= tty_open,
   3.396 +	.release	= tty_release,
   3.397 +	.fasync		= tty_fasync,
   3.398 +};
   3.399 +
   3.400 +static struct file_operations hung_up_tty_fops = {
   3.401 +	.llseek		= no_llseek,
   3.402 +	.read		= hung_up_tty_read,
   3.403 +	.write		= hung_up_tty_write,
   3.404 +	.poll		= hung_up_tty_poll,
   3.405 +	.ioctl		= hung_up_tty_ioctl,
   3.406 +	.release	= tty_release,
   3.407 +};
   3.408 +
   3.409 +static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED;
   3.410 +static struct file *redirect;
   3.411 +/*
   3.412 + * This can be called by the "eventd" kernel thread.  That is process synchronous,
   3.413 + * but doesn't hold any locks, so we need to make sure we have the appropriate
   3.414 + * locks for what we're doing..
   3.415 + */
   3.416 +void do_tty_hangup(void *data)
   3.417 +{
   3.418 +	struct tty_struct *tty = (struct tty_struct *) data;
   3.419 +	struct file * cons_filp = NULL;
   3.420 +	struct file *filp, *f = NULL;
   3.421 +	struct task_struct *p;
   3.422 +	struct pid *pid;
   3.423 +	int    closecount = 0, n;
   3.424 +
   3.425 +	if (!tty)
   3.426 +		return;
   3.427 +
   3.428 +	/* inuse_filps is protected by the single kernel lock */
   3.429 +	lock_kernel();
   3.430 +
   3.431 +	spin_lock(&redirect_lock);
   3.432 +	if (redirect && redirect->private_data == tty) {
   3.433 +		f = redirect;
   3.434 +		redirect = NULL;
   3.435 +	}
   3.436 +	spin_unlock(&redirect_lock);
   3.437 +	
   3.438 +	check_tty_count(tty, "do_tty_hangup");
   3.439 +	file_list_lock();
   3.440 +	list_for_each_entry(filp, &tty->tty_files, f_list) {
   3.441 +		if (filp->f_op->write == redirected_tty_write)
   3.442 +			cons_filp = filp;
   3.443 +		if (filp->f_op->write != tty_write)
   3.444 +			continue;
   3.445 +		closecount++;
   3.446 +		tty_fasync(-1, filp, 0);	/* can't block */
   3.447 +		filp->f_op = &hung_up_tty_fops;
   3.448 +	}
   3.449 +	file_list_unlock();
   3.450 +	
   3.451 +	/* FIXME! What are the locking issues here? This may me overdoing things..
   3.452 +	* this question is especially important now that we've removed the irqlock. */
   3.453 +	{
   3.454 +		unsigned long flags;
   3.455 +
   3.456 +		local_irq_save(flags); // FIXME: is this safe?
   3.457 +		if (tty->ldisc.flush_buffer)
   3.458 +			tty->ldisc.flush_buffer(tty);
   3.459 +		if (tty->driver->flush_buffer)
   3.460 +			tty->driver->flush_buffer(tty);
   3.461 +		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
   3.462 +		    tty->ldisc.write_wakeup)
   3.463 +			(tty->ldisc.write_wakeup)(tty);
   3.464 +		local_irq_restore(flags); // FIXME: is this safe?
   3.465 +	}
   3.466 +
   3.467 +	wake_up_interruptible(&tty->write_wait);
   3.468 +	wake_up_interruptible(&tty->read_wait);
   3.469 +
   3.470 +	/*
   3.471 +	 * Shutdown the current line discipline, and reset it to
   3.472 +	 * N_TTY.
   3.473 +	 */
   3.474 +	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
   3.475 +		*tty->termios = tty->driver->init_termios;
   3.476 +	if (tty->ldisc.num != ldiscs[N_TTY].num) {
   3.477 +		if (tty->ldisc.close)
   3.478 +			(tty->ldisc.close)(tty);
   3.479 +		module_put(tty->ldisc.owner);
   3.480 +		
   3.481 +		tty->ldisc = ldiscs[N_TTY];
   3.482 +		tty->termios->c_line = N_TTY;
   3.483 +		if (tty->ldisc.open) {
   3.484 +			int i = (tty->ldisc.open)(tty);
   3.485 +			if (i < 0)
   3.486 +				printk(KERN_ERR "do_tty_hangup: N_TTY open: "
   3.487 +						"error %d\n", -i);
   3.488 +		}
   3.489 +	}
   3.490 +	
   3.491 +	read_lock(&tasklist_lock);
   3.492 +	if (tty->session > 0) {
   3.493 +		struct list_head *l;
   3.494 +		for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) {
   3.495 +			if (p->signal->tty == tty)
   3.496 +				p->signal->tty = NULL;
   3.497 +			if (!p->signal->leader)
   3.498 +				continue;
   3.499 +			send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p);
   3.500 +			send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
   3.501 +			if (tty->pgrp > 0)
   3.502 +				p->signal->tty_old_pgrp = tty->pgrp;
   3.503 +		}
   3.504 +	}
   3.505 +	read_unlock(&tasklist_lock);
   3.506 +
   3.507 +	tty->flags = 0;
   3.508 +	tty->session = 0;
   3.509 +	tty->pgrp = -1;
   3.510 +	tty->ctrl_status = 0;
   3.511 +	/*
   3.512 +	 *	If one of the devices matches a console pointer, we
   3.513 +	 *	cannot just call hangup() because that will cause
   3.514 +	 *	tty->count and state->count to go out of sync.
   3.515 +	 *	So we just call close() the right number of times.
   3.516 +	 */
   3.517 +	if (cons_filp) {
   3.518 +		if (tty->driver->close)
   3.519 +			for (n = 0; n < closecount; n++)
   3.520 +				tty->driver->close(tty, cons_filp);
   3.521 +	} else if (tty->driver->hangup)
   3.522 +		(tty->driver->hangup)(tty);
   3.523 +	unlock_kernel();
   3.524 +	if (f)
   3.525 +		fput(f);
   3.526 +}
   3.527 +
   3.528 +void tty_hangup(struct tty_struct * tty)
   3.529 +{
   3.530 +#ifdef TTY_DEBUG_HANGUP
   3.531 +	char	buf[64];
   3.532 +	
   3.533 +	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
   3.534 +#endif
   3.535 +	schedule_work(&tty->hangup_work);
   3.536 +}
   3.537 +
   3.538 +EXPORT_SYMBOL(tty_hangup);
   3.539 +
   3.540 +void tty_vhangup(struct tty_struct * tty)
   3.541 +{
   3.542 +#ifdef TTY_DEBUG_HANGUP
   3.543 +	char	buf[64];
   3.544 +
   3.545 +	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
   3.546 +#endif
   3.547 +	do_tty_hangup((void *) tty);
   3.548 +}
   3.549 +EXPORT_SYMBOL(tty_vhangup);
   3.550 +
   3.551 +int tty_hung_up_p(struct file * filp)
   3.552 +{
   3.553 +	return (filp->f_op == &hung_up_tty_fops);
   3.554 +}
   3.555 +
   3.556 +EXPORT_SYMBOL(tty_hung_up_p);
   3.557 +
   3.558 +/*
   3.559 + * This function is typically called only by the session leader, when
   3.560 + * it wants to disassociate itself from its controlling tty.
   3.561 + *
   3.562 + * It performs the following functions:
   3.563 + * 	(1)  Sends a SIGHUP and SIGCONT to the foreground process group
   3.564 + * 	(2)  Clears the tty from being controlling the session
   3.565 + * 	(3)  Clears the controlling tty for all processes in the
   3.566 + * 		session group.
   3.567 + *
   3.568 + * The argument on_exit is set to 1 if called when a process is
   3.569 + * exiting; it is 0 if called by the ioctl TIOCNOTTY.
   3.570 + */
   3.571 +void disassociate_ctty(int on_exit)
   3.572 +{
   3.573 +	struct tty_struct *tty;
   3.574 +	struct task_struct *p;
   3.575 +	struct list_head *l;
   3.576 +	struct pid *pid;
   3.577 +	int tty_pgrp = -1;
   3.578 +
   3.579 +	lock_kernel();
   3.580 +
   3.581 +	tty = current->signal->tty;
   3.582 +	if (tty) {
   3.583 +		tty_pgrp = tty->pgrp;
   3.584 +		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
   3.585 +			tty_vhangup(tty);
   3.586 +	} else {
   3.587 +		if (current->signal->tty_old_pgrp) {
   3.588 +			kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
   3.589 +			kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
   3.590 +		}
   3.591 +		unlock_kernel();	
   3.592 +		return;
   3.593 +	}
   3.594 +	if (tty_pgrp > 0) {
   3.595 +		kill_pg(tty_pgrp, SIGHUP, on_exit);
   3.596 +		if (!on_exit)
   3.597 +			kill_pg(tty_pgrp, SIGCONT, on_exit);
   3.598 +	}
   3.599 +
   3.600 +	current->signal->tty_old_pgrp = 0;
   3.601 +	tty->session = 0;
   3.602 +	tty->pgrp = -1;
   3.603 +
   3.604 +	read_lock(&tasklist_lock);
   3.605 +	for_each_task_pid(current->signal->session, PIDTYPE_SID, p, l, pid)
   3.606 +		p->signal->tty = NULL;
   3.607 +	read_unlock(&tasklist_lock);
   3.608 +	unlock_kernel();
   3.609 +}
   3.610 +
   3.611 +void stop_tty(struct tty_struct *tty)
   3.612 +{
   3.613 +	if (tty->stopped)
   3.614 +		return;
   3.615 +	tty->stopped = 1;
   3.616 +	if (tty->link && tty->link->packet) {
   3.617 +		tty->ctrl_status &= ~TIOCPKT_START;
   3.618 +		tty->ctrl_status |= TIOCPKT_STOP;
   3.619 +		wake_up_interruptible(&tty->link->read_wait);
   3.620 +	}
   3.621 +	if (tty->driver->stop)
   3.622 +		(tty->driver->stop)(tty);
   3.623 +}
   3.624 +
   3.625 +EXPORT_SYMBOL(stop_tty);
   3.626 +
   3.627 +void start_tty(struct tty_struct *tty)
   3.628 +{
   3.629 +	if (!tty->stopped || tty->flow_stopped)
   3.630 +		return;
   3.631 +	tty->stopped = 0;
   3.632 +	if (tty->link && tty->link->packet) {
   3.633 +		tty->ctrl_status &= ~TIOCPKT_STOP;
   3.634 +		tty->ctrl_status |= TIOCPKT_START;
   3.635 +		wake_up_interruptible(&tty->link->read_wait);
   3.636 +	}
   3.637 +	if (tty->driver->start)
   3.638 +		(tty->driver->start)(tty);
   3.639 +	if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
   3.640 +	    tty->ldisc.write_wakeup)
   3.641 +		(tty->ldisc.write_wakeup)(tty);
   3.642 +	wake_up_interruptible(&tty->write_wait);
   3.643 +}
   3.644 +
   3.645 +EXPORT_SYMBOL(start_tty);
   3.646 +
   3.647 +static ssize_t tty_read(struct file * file, char __user * buf, size_t count, 
   3.648 +			loff_t *ppos)
   3.649 +{
   3.650 +	int i;
   3.651 +	struct tty_struct * tty;
   3.652 +	struct inode *inode;
   3.653 +
   3.654 +	/* Can't seek (pread) on ttys.  */
   3.655 +	if (ppos != &file->f_pos)
   3.656 +		return -ESPIPE;
   3.657 +
   3.658 +	tty = (struct tty_struct *)file->private_data;
   3.659 +	inode = file->f_dentry->d_inode;
   3.660 +	if (tty_paranoia_check(tty, inode, "tty_read"))
   3.661 +		return -EIO;
   3.662 +	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
   3.663 +		return -EIO;
   3.664 +
   3.665 +	lock_kernel();
   3.666 +	if (tty->ldisc.read)
   3.667 +		i = (tty->ldisc.read)(tty,file,buf,count);
   3.668 +	else
   3.669 +		i = -EIO;
   3.670 +	unlock_kernel();
   3.671 +	if (i > 0)
   3.672 +		inode->i_atime = CURRENT_TIME;
   3.673 +	return i;
   3.674 +}
   3.675 +
   3.676 +/*
   3.677 + * Split writes up in sane blocksizes to avoid
   3.678 + * denial-of-service type attacks
   3.679 + */
   3.680 +static inline ssize_t do_tty_write(
   3.681 +	ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char __user *, size_t),
   3.682 +	struct tty_struct *tty,
   3.683 +	struct file *file,
   3.684 +	const unsigned char __user *buf,
   3.685 +	size_t count)
   3.686 +{
   3.687 +	ssize_t ret = 0, written = 0;
   3.688 +	
   3.689 +	if (down_interruptible(&tty->atomic_write)) {
   3.690 +		return -ERESTARTSYS;
   3.691 +	}
   3.692 +	if ( test_bit(TTY_NO_WRITE_SPLIT, &tty->flags) ) {
   3.693 +		lock_kernel();
   3.694 +		written = write(tty, file, buf, count);
   3.695 +		unlock_kernel();
   3.696 +	} else {
   3.697 +		for (;;) {
   3.698 +			unsigned long size = max((unsigned long)PAGE_SIZE*2, 16384UL);
   3.699 +			if (size > count)
   3.700 +				size = count;
   3.701 +			lock_kernel();
   3.702 +			ret = write(tty, file, buf, size);
   3.703 +			unlock_kernel();
   3.704 +			if (ret <= 0)
   3.705 +				break;
   3.706 +			written += ret;
   3.707 +			buf += ret;
   3.708 +			count -= ret;
   3.709 +			if (!count)
   3.710 +				break;
   3.711 +			ret = -ERESTARTSYS;
   3.712 +			if (signal_pending(current))
   3.713 +				break;
   3.714 +			cond_resched();
   3.715 +		}
   3.716 +	}
   3.717 +	if (written) {
   3.718 +		file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
   3.719 +		ret = written;
   3.720 +	}
   3.721 +	up(&tty->atomic_write);
   3.722 +	return ret;
   3.723 +}
   3.724 +
   3.725 +
   3.726 +static ssize_t tty_write(struct file * file, const char __user * buf, size_t count,
   3.727 +			 loff_t *ppos)
   3.728 +{
   3.729 +	struct tty_struct * tty;
   3.730 +	struct inode *inode = file->f_dentry->d_inode;
   3.731 +
   3.732 +	/* Can't seek (pwrite) on ttys.  */
   3.733 +	if (ppos != &file->f_pos)
   3.734 +		return -ESPIPE;
   3.735 +
   3.736 +	tty = (struct tty_struct *)file->private_data;
   3.737 +	if (tty_paranoia_check(tty, inode, "tty_write"))
   3.738 +		return -EIO;
   3.739 +	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
   3.740 +		return -EIO;
   3.741 +	if (!tty->ldisc.write)
   3.742 +		return -EIO;
   3.743 +	return do_tty_write(tty->ldisc.write, tty, file,
   3.744 +			    (const unsigned char __user *)buf, count);
   3.745 +}
   3.746 +
   3.747 +ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count,
   3.748 +			 loff_t *ppos)
   3.749 +{
   3.750 +	struct file *p = NULL;
   3.751 +
   3.752 +	spin_lock(&redirect_lock);
   3.753 +	if (redirect) {
   3.754 +		get_file(redirect);
   3.755 +		p = redirect;
   3.756 +	}
   3.757 +	spin_unlock(&redirect_lock);
   3.758 +
   3.759 +	if (p) {
   3.760 +		ssize_t res;
   3.761 +		/* Can't seek (pwrite) on ttys.  */
   3.762 +		if (ppos != &file->f_pos)
   3.763 +			return -ESPIPE;
   3.764 +		res = vfs_write(p, buf, count, &p->f_pos);
   3.765 +		fput(p);
   3.766 +		return res;
   3.767 +	}
   3.768 +
   3.769 +	return tty_write(file, buf, count, ppos);
   3.770 +}
   3.771 +
   3.772 +static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
   3.773 +{
   3.774 +	sprintf(p, "%s%d", driver->name, index + driver->name_base);
   3.775 +}
   3.776 +
   3.777 +/*
   3.778 + * WSH 06/09/97: Rewritten to remove races and properly clean up after a
   3.779 + * failed open.  The new code protects the open with a semaphore, so it's
   3.780 + * really quite straightforward.  The semaphore locking can probably be
   3.781 + * relaxed for the (most common) case of reopening a tty.
   3.782 + */
   3.783 +static int init_dev(struct tty_driver *driver, int idx,
   3.784 +	struct tty_struct **ret_tty)
   3.785 +{
   3.786 +	struct tty_struct *tty, *o_tty;
   3.787 +	struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
   3.788 +	struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
   3.789 +	int retval=0;
   3.790 +
   3.791 +	/* 
   3.792 +	 * Check whether we need to acquire the tty semaphore to avoid
   3.793 +	 * race conditions.  For now, play it safe.
   3.794 +	 */
   3.795 +	down(&tty_sem);
   3.796 +
   3.797 +	/* check whether we're reopening an existing tty */
   3.798 +	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
   3.799 +		tty = devpts_get_tty(idx);
   3.800 +		if (tty && driver->subtype == PTY_TYPE_MASTER)
   3.801 +			tty = tty->link;
   3.802 +	} else {
   3.803 +		tty = driver->ttys[idx];
   3.804 +	}
   3.805 +	if (tty) goto fast_track;
   3.806 +
   3.807 +	/*
   3.808 +	 * First time open is complex, especially for PTY devices.
   3.809 +	 * This code guarantees that either everything succeeds and the
   3.810 +	 * TTY is ready for operation, or else the table slots are vacated
   3.811 +	 * and the allocated memory released.  (Except that the termios 
   3.812 +	 * and locked termios may be retained.)
   3.813 +	 */
   3.814 +
   3.815 +	if (!try_module_get(driver->owner)) {
   3.816 +		retval = -ENODEV;
   3.817 +		goto end_init;
   3.818 +	}
   3.819 +
   3.820 +	o_tty = NULL;
   3.821 +	tp = o_tp = NULL;
   3.822 +	ltp = o_ltp = NULL;
   3.823 +
   3.824 +	tty = alloc_tty_struct();
   3.825 +	if(!tty)
   3.826 +		goto fail_no_mem;
   3.827 +	initialize_tty_struct(tty);
   3.828 +	tty->driver = driver;
   3.829 +	tty->index = idx;
   3.830 +	tty_line_name(driver, idx, tty->name);
   3.831 +
   3.832 +	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
   3.833 +		tp_loc = &tty->termios;
   3.834 +		ltp_loc = &tty->termios_locked;
   3.835 +	} else {
   3.836 +		tp_loc = &driver->termios[idx];
   3.837 +		ltp_loc = &driver->termios_locked[idx];
   3.838 +	}
   3.839 +
   3.840 +	if (!*tp_loc) {
   3.841 +		tp = (struct termios *) kmalloc(sizeof(struct termios),
   3.842 +						GFP_KERNEL);
   3.843 +		if (!tp)
   3.844 +			goto free_mem_out;
   3.845 +		*tp = driver->init_termios;
   3.846 +	}
   3.847 +
   3.848 +	if (!*ltp_loc) {
   3.849 +		ltp = (struct termios *) kmalloc(sizeof(struct termios),
   3.850 +						 GFP_KERNEL);
   3.851 +		if (!ltp)
   3.852 +			goto free_mem_out;
   3.853 +		memset(ltp, 0, sizeof(struct termios));
   3.854 +	}
   3.855 +
   3.856 +	if (driver->type == TTY_DRIVER_TYPE_PTY) {
   3.857 +		o_tty = alloc_tty_struct();
   3.858 +		if (!o_tty)
   3.859 +			goto free_mem_out;
   3.860 +		initialize_tty_struct(o_tty);
   3.861 +		o_tty->driver = driver->other;
   3.862 +		o_tty->index = idx;
   3.863 +		tty_line_name(driver->other, idx, o_tty->name);
   3.864 +
   3.865 +		if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
   3.866 +			o_tp_loc = &o_tty->termios;
   3.867 +			o_ltp_loc = &o_tty->termios_locked;
   3.868 +		} else {
   3.869 +			o_tp_loc = &driver->other->termios[idx];
   3.870 +			o_ltp_loc = &driver->other->termios_locked[idx];
   3.871 +		}
   3.872 +
   3.873 +		if (!*o_tp_loc) {
   3.874 +			o_tp = (struct termios *)
   3.875 +				kmalloc(sizeof(struct termios), GFP_KERNEL);
   3.876 +			if (!o_tp)
   3.877 +				goto free_mem_out;
   3.878 +			*o_tp = driver->other->init_termios;
   3.879 +		}
   3.880 +
   3.881 +		if (!*o_ltp_loc) {
   3.882 +			o_ltp = (struct termios *)
   3.883 +				kmalloc(sizeof(struct termios), GFP_KERNEL);
   3.884 +			if (!o_ltp)
   3.885 +				goto free_mem_out;
   3.886 +			memset(o_ltp, 0, sizeof(struct termios));
   3.887 +		}
   3.888 +
   3.889 +		/*
   3.890 +		 * Everything allocated ... set up the o_tty structure.
   3.891 +		 */
   3.892 +		if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) {
   3.893 +			driver->other->ttys[idx] = o_tty;
   3.894 +		}
   3.895 +		if (!*o_tp_loc)
   3.896 +			*o_tp_loc = o_tp;
   3.897 +		if (!*o_ltp_loc)
   3.898 +			*o_ltp_loc = o_ltp;
   3.899 +		o_tty->termios = *o_tp_loc;
   3.900 +		o_tty->termios_locked = *o_ltp_loc;
   3.901 +		driver->other->refcount++;
   3.902 +		if (driver->subtype == PTY_TYPE_MASTER)
   3.903 +			o_tty->count++;
   3.904 +
   3.905 +		/* Establish the links in both directions */
   3.906 +		tty->link   = o_tty;
   3.907 +		o_tty->link = tty;
   3.908 +	}
   3.909 +
   3.910 +	/* 
   3.911 +	 * All structures have been allocated, so now we install them.
   3.912 +	 * Failures after this point use release_mem to clean up, so 
   3.913 +	 * there's no need to null out the local pointers.
   3.914 +	 */
   3.915 +	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
   3.916 +		driver->ttys[idx] = tty;
   3.917 +	}
   3.918 +	
   3.919 +	if (!*tp_loc)
   3.920 +		*tp_loc = tp;
   3.921 +	if (!*ltp_loc)
   3.922 +		*ltp_loc = ltp;
   3.923 +	tty->termios = *tp_loc;
   3.924 +	tty->termios_locked = *ltp_loc;
   3.925 +	driver->refcount++;
   3.926 +	tty->count++;
   3.927 +
   3.928 +	/* 
   3.929 +	 * Structures all installed ... call the ldisc open routines.
   3.930 +	 * If we fail here just call release_mem to clean up.  No need
   3.931 +	 * to decrement the use counts, as release_mem doesn't care.
   3.932 +	 */
   3.933 +	if (tty->ldisc.open) {
   3.934 +		retval = (tty->ldisc.open)(tty);
   3.935 +		if (retval)
   3.936 +			goto release_mem_out;
   3.937 +	}
   3.938 +	if (o_tty && o_tty->ldisc.open) {
   3.939 +		retval = (o_tty->ldisc.open)(o_tty);
   3.940 +		if (retval) {
   3.941 +			if (tty->ldisc.close)
   3.942 +				(tty->ldisc.close)(tty);
   3.943 +			goto release_mem_out;
   3.944 +		}
   3.945 +	}
   3.946 +	goto success;
   3.947 +
   3.948 +	/*
   3.949 +	 * This fast open can be used if the tty is already open.
   3.950 +	 * No memory is allocated, and the only failures are from
   3.951 +	 * attempting to open a closing tty or attempting multiple
   3.952 +	 * opens on a pty master.
   3.953 +	 */
   3.954 +fast_track:
   3.955 +	if (test_bit(TTY_CLOSING, &tty->flags)) {
   3.956 +		retval = -EIO;
   3.957 +		goto end_init;
   3.958 +	}
   3.959 +	if (driver->type == TTY_DRIVER_TYPE_PTY &&
   3.960 +	    driver->subtype == PTY_TYPE_MASTER) {
   3.961 +		/*
   3.962 +		 * special case for PTY masters: only one open permitted, 
   3.963 +		 * and the slave side open count is incremented as well.
   3.964 +		 */
   3.965 +		if (tty->count) {
   3.966 +			retval = -EIO;
   3.967 +			goto end_init;
   3.968 +		}
   3.969 +		tty->link->count++;
   3.970 +	}
   3.971 +	tty->count++;
   3.972 +	tty->driver = driver; /* N.B. why do this every time?? */
   3.973 +
   3.974 +success:
   3.975 +	*ret_tty = tty;
   3.976 +	
   3.977 +	/* All paths come through here to release the semaphore */
   3.978 +end_init:
   3.979 +	up(&tty_sem);
   3.980 +	return retval;
   3.981 +
   3.982 +	/* Release locally allocated memory ... nothing placed in slots */
   3.983 +free_mem_out:
   3.984 +	if (o_tp)
   3.985 +		kfree(o_tp);
   3.986 +	if (o_tty)
   3.987 +		free_tty_struct(o_tty);
   3.988 +	if (ltp)
   3.989 +		kfree(ltp);
   3.990 +	if (tp)
   3.991 +		kfree(tp);
   3.992 +	free_tty_struct(tty);
   3.993 +
   3.994 +fail_no_mem:
   3.995 +	module_put(driver->owner);
   3.996 +	retval = -ENOMEM;
   3.997 +	goto end_init;
   3.998 +
   3.999 +	/* call the tty release_mem routine to clean out this slot */
  3.1000 +release_mem_out:
  3.1001 +	printk(KERN_INFO "init_dev: ldisc open failed, "
  3.1002 +			 "clearing slot %d\n", idx);
  3.1003 +	release_mem(tty, idx);
  3.1004 +	goto end_init;
  3.1005 +}
  3.1006 +
  3.1007 +/*
  3.1008 + * Releases memory associated with a tty structure, and clears out the
  3.1009 + * driver table slots.
  3.1010 + */
  3.1011 +static void release_mem(struct tty_struct *tty, int idx)
  3.1012 +{
  3.1013 +	struct tty_struct *o_tty;
  3.1014 +	struct termios *tp;
  3.1015 +	int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
  3.1016 +
  3.1017 +	if ((o_tty = tty->link) != NULL) {
  3.1018 +		if (!devpts)
  3.1019 +			o_tty->driver->ttys[idx] = NULL;
  3.1020 +		if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
  3.1021 +			tp = o_tty->termios;
  3.1022 +			if (!devpts)
  3.1023 +				o_tty->driver->termios[idx] = NULL;
  3.1024 +			kfree(tp);
  3.1025 +
  3.1026 +			tp = o_tty->termios_locked;
  3.1027 +			if (!devpts)
  3.1028 +				o_tty->driver->termios_locked[idx] = NULL;
  3.1029 +			kfree(tp);
  3.1030 +		}
  3.1031 +		o_tty->magic = 0;
  3.1032 +		o_tty->driver->refcount--;
  3.1033 +		file_list_lock();
  3.1034 +		list_del_init(&o_tty->tty_files);
  3.1035 +		file_list_unlock();
  3.1036 +		free_tty_struct(o_tty);
  3.1037 +	}
  3.1038 +
  3.1039 +	if (!devpts)
  3.1040 +		tty->driver->ttys[idx] = NULL;
  3.1041 +	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
  3.1042 +		tp = tty->termios;
  3.1043 +		if (!devpts)
  3.1044 +			tty->driver->termios[idx] = NULL;
  3.1045 +		kfree(tp);
  3.1046 +
  3.1047 +		tp = tty->termios_locked;
  3.1048 +		if (!devpts)
  3.1049 +			tty->driver->termios_locked[idx] = NULL;
  3.1050 +		kfree(tp);
  3.1051 +	}
  3.1052 +
  3.1053 +	tty->magic = 0;
  3.1054 +	tty->driver->refcount--;
  3.1055 +	file_list_lock();
  3.1056 +	list_del_init(&tty->tty_files);
  3.1057 +	file_list_unlock();
  3.1058 +	module_put(tty->driver->owner);
  3.1059 +	free_tty_struct(tty);
  3.1060 +}
  3.1061 +
  3.1062 +/*
  3.1063 + * Even releasing the tty structures is a tricky business.. We have
  3.1064 + * to be very careful that the structures are all released at the
  3.1065 + * same time, as interrupts might otherwise get the wrong pointers.
  3.1066 + *
  3.1067 + * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
  3.1068 + * lead to double frees or releasing memory still in use.
  3.1069 + */
  3.1070 +static void release_dev(struct file * filp)
  3.1071 +{
  3.1072 +	struct tty_struct *tty, *o_tty;
  3.1073 +	int	pty_master, tty_closing, o_tty_closing, do_sleep;
  3.1074 +	int	idx;
  3.1075 +	char	buf[64];
  3.1076 +	
  3.1077 +	tty = (struct tty_struct *)filp->private_data;
  3.1078 +	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
  3.1079 +		return;
  3.1080 +
  3.1081 +	check_tty_count(tty, "release_dev");
  3.1082 +
  3.1083 +	tty_fasync(-1, filp, 0);
  3.1084 +
  3.1085 +	idx = tty->index;
  3.1086 +	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
  3.1087 +		      tty->driver->subtype == PTY_TYPE_MASTER);
  3.1088 +	o_tty = tty->link;
  3.1089 +
  3.1090 +#ifdef TTY_PARANOIA_CHECK
  3.1091 +	if (idx < 0 || idx >= tty->driver->num) {
  3.1092 +		printk(KERN_DEBUG "release_dev: bad idx when trying to "
  3.1093 +				  "free (%s)\n", tty->name);
  3.1094 +		return;
  3.1095 +	}
  3.1096 +	if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  3.1097 +		if (tty != tty->driver->ttys[idx]) {
  3.1098 +			printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
  3.1099 +			       "for (%s)\n", idx, tty->name);
  3.1100 +			return;
  3.1101 +		}
  3.1102 +		if (tty->termios != tty->driver->termios[idx]) {
  3.1103 +			printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
  3.1104 +			       "for (%s)\n",
  3.1105 +			       idx, tty->name);
  3.1106 +			return;
  3.1107 +		}
  3.1108 +		if (tty->termios_locked != tty->driver->termios_locked[idx]) {
  3.1109 +			printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
  3.1110 +			       "termios_locked for (%s)\n",
  3.1111 +			       idx, tty->name);
  3.1112 +			return;
  3.1113 +		}
  3.1114 +	}
  3.1115 +#endif
  3.1116 +
  3.1117 +#ifdef TTY_DEBUG_HANGUP
  3.1118 +	printk(KERN_DEBUG "release_dev of %s (tty count=%d)...",
  3.1119 +	       tty_name(tty, buf), tty->count);
  3.1120 +#endif
  3.1121 +
  3.1122 +#ifdef TTY_PARANOIA_CHECK
  3.1123 +	if (tty->driver->other &&
  3.1124 +	     !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  3.1125 +		if (o_tty != tty->driver->other->ttys[idx]) {
  3.1126 +			printk(KERN_DEBUG "release_dev: other->table[%d] "
  3.1127 +					  "not o_tty for (%s)\n",
  3.1128 +			       idx, tty->name);
  3.1129 +			return;
  3.1130 +		}
  3.1131 +		if (o_tty->termios != tty->driver->other->termios[idx]) {
  3.1132 +			printk(KERN_DEBUG "release_dev: other->termios[%d] "
  3.1133 +					  "not o_termios for (%s)\n",
  3.1134 +			       idx, tty->name);
  3.1135 +			return;
  3.1136 +		}
  3.1137 +		if (o_tty->termios_locked != 
  3.1138 +		      tty->driver->other->termios_locked[idx]) {
  3.1139 +			printk(KERN_DEBUG "release_dev: other->termios_locked["
  3.1140 +					  "%d] not o_termios_locked for (%s)\n",
  3.1141 +			       idx, tty->name);
  3.1142 +			return;
  3.1143 +		}
  3.1144 +		if (o_tty->link != tty) {
  3.1145 +			printk(KERN_DEBUG "release_dev: bad pty pointers\n");
  3.1146 +			return;
  3.1147 +		}
  3.1148 +	}
  3.1149 +#endif
  3.1150 +
  3.1151 +	if (tty->driver->close)
  3.1152 +		tty->driver->close(tty, filp);
  3.1153 +
  3.1154 +	/*
  3.1155 +	 * Sanity check: if tty->count is going to zero, there shouldn't be
  3.1156 +	 * any waiters on tty->read_wait or tty->write_wait.  We test the
  3.1157 +	 * wait queues and kick everyone out _before_ actually starting to
  3.1158 +	 * close.  This ensures that we won't block while releasing the tty
  3.1159 +	 * structure.
  3.1160 +	 *
  3.1161 +	 * The test for the o_tty closing is necessary, since the master and
  3.1162 +	 * slave sides may close in any order.  If the slave side closes out
  3.1163 +	 * first, its count will be one, since the master side holds an open.
  3.1164 +	 * Thus this test wouldn't be triggered at the time the slave closes,
  3.1165 +	 * so we do it now.
  3.1166 +	 *
  3.1167 +	 * Note that it's possible for the tty to be opened again while we're
  3.1168 +	 * flushing out waiters.  By recalculating the closing flags before
  3.1169 +	 * each iteration we avoid any problems.
  3.1170 +	 */
  3.1171 +	while (1) {
  3.1172 +		tty_closing = tty->count <= 1;
  3.1173 +		o_tty_closing = o_tty &&
  3.1174 +			(o_tty->count <= (pty_master ? 1 : 0));
  3.1175 +		do_sleep = 0;
  3.1176 +
  3.1177 +		if (tty_closing) {
  3.1178 +			if (waitqueue_active(&tty->read_wait)) {
  3.1179 +				wake_up(&tty->read_wait);
  3.1180 +				do_sleep++;
  3.1181 +			}
  3.1182 +			if (waitqueue_active(&tty->write_wait)) {
  3.1183 +				wake_up(&tty->write_wait);
  3.1184 +				do_sleep++;
  3.1185 +			}
  3.1186 +		}
  3.1187 +		if (o_tty_closing) {
  3.1188 +			if (waitqueue_active(&o_tty->read_wait)) {
  3.1189 +				wake_up(&o_tty->read_wait);
  3.1190 +				do_sleep++;
  3.1191 +			}
  3.1192 +			if (waitqueue_active(&o_tty->write_wait)) {
  3.1193 +				wake_up(&o_tty->write_wait);
  3.1194 +				do_sleep++;
  3.1195 +			}
  3.1196 +		}
  3.1197 +		if (!do_sleep)
  3.1198 +			break;
  3.1199 +
  3.1200 +		printk(KERN_WARNING "release_dev: %s: read/write wait queue "
  3.1201 +				    "active!\n", tty_name(tty, buf));
  3.1202 +		schedule();
  3.1203 +	}	
  3.1204 +
  3.1205 +	/*
  3.1206 +	 * The closing flags are now consistent with the open counts on 
  3.1207 +	 * both sides, and we've completed the last operation that could 
  3.1208 +	 * block, so it's safe to proceed with closing.
  3.1209 +	 */
  3.1210 +	if (pty_master) {
  3.1211 +		if (--o_tty->count < 0) {
  3.1212 +			printk(KERN_WARNING "release_dev: bad pty slave count "
  3.1213 +					    "(%d) for %s\n",
  3.1214 +			       o_tty->count, tty_name(o_tty, buf));
  3.1215 +			o_tty->count = 0;
  3.1216 +		}
  3.1217 +	}
  3.1218 +	if (--tty->count < 0) {
  3.1219 +		printk(KERN_WARNING "release_dev: bad tty->count (%d) for %s\n",
  3.1220 +		       tty->count, tty_name(tty, buf));
  3.1221 +		tty->count = 0;
  3.1222 +	}
  3.1223 +
  3.1224 +	/*
  3.1225 +	 * We've decremented tty->count, so we need to remove this file
  3.1226 +	 * descriptor off the tty->tty_files list; this serves two
  3.1227 +	 * purposes:
  3.1228 +	 *  - check_tty_count sees the correct number of file descriptors
  3.1229 +	 *    associated with this tty.
  3.1230 +	 *  - do_tty_hangup no longer sees this file descriptor as
  3.1231 +	 *    something that needs to be handled for hangups.
  3.1232 +	 */
  3.1233 +	file_kill(filp);
  3.1234 +	filp->private_data = NULL;
  3.1235 +
  3.1236 +	/*
  3.1237 +	 * Perform some housekeeping before deciding whether to return.
  3.1238 +	 *
  3.1239 +	 * Set the TTY_CLOSING flag if this was the last open.  In the
  3.1240 +	 * case of a pty we may have to wait around for the other side
  3.1241 +	 * to close, and TTY_CLOSING makes sure we can't be reopened.
  3.1242 +	 */
  3.1243 +	if(tty_closing)
  3.1244 +		set_bit(TTY_CLOSING, &tty->flags);
  3.1245 +	if(o_tty_closing)
  3.1246 +		set_bit(TTY_CLOSING, &o_tty->flags);
  3.1247 +
  3.1248 +	/*
  3.1249 +	 * If _either_ side is closing, make sure there aren't any
  3.1250 +	 * processes that still think tty or o_tty is their controlling
  3.1251 +	 * tty.
  3.1252 +	 */
  3.1253 +	if (tty_closing || o_tty_closing) {
  3.1254 +		struct task_struct *p;
  3.1255 +		struct list_head *l;
  3.1256 +		struct pid *pid;
  3.1257 +
  3.1258 +		read_lock(&tasklist_lock);
  3.1259 +		for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
  3.1260 +			p->signal->tty = NULL;
  3.1261 +		if (o_tty)
  3.1262 +			for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid)
  3.1263 +				p->signal->tty = NULL;
  3.1264 +		read_unlock(&tasklist_lock);
  3.1265 +	}
  3.1266 +
  3.1267 +	/* check whether both sides are closing ... */
  3.1268 +	if (!tty_closing || (o_tty && !o_tty_closing))
  3.1269 +		return;
  3.1270 +	
  3.1271 +#ifdef TTY_DEBUG_HANGUP
  3.1272 +	printk(KERN_DEBUG "freeing tty structure...");
  3.1273 +#endif
  3.1274 +
  3.1275 +	/*
  3.1276 +	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
  3.1277 +	 * kill any delayed work.
  3.1278 +	 */
  3.1279 +	clear_bit(TTY_DONT_FLIP, &tty->flags);
  3.1280 +	cancel_delayed_work(&tty->flip.work);
  3.1281 +
  3.1282 +	/*
  3.1283 +	 * Wait for ->hangup_work and ->flip.work handlers to terminate
  3.1284 +	 */
  3.1285 +	flush_scheduled_work();
  3.1286 +
  3.1287 +	/*
  3.1288 +	 * Shutdown the current line discipline, and reset it to N_TTY.
  3.1289 +	 * N.B. why reset ldisc when we're releasing the memory??
  3.1290 +	 */
  3.1291 +	if (tty->ldisc.close)
  3.1292 +		(tty->ldisc.close)(tty);
  3.1293 +	module_put(tty->ldisc.owner);
  3.1294 +	
  3.1295 +	tty->ldisc = ldiscs[N_TTY];
  3.1296 +	tty->termios->c_line = N_TTY;
  3.1297 +	if (o_tty) {
  3.1298 +		if (o_tty->ldisc.close)
  3.1299 +			(o_tty->ldisc.close)(o_tty);
  3.1300 +		module_put(o_tty->ldisc.owner);
  3.1301 +		o_tty->ldisc = ldiscs[N_TTY];
  3.1302 +	}
  3.1303 +
  3.1304 +	/* 
  3.1305 +	 * The release_mem function takes care of the details of clearing
  3.1306 +	 * the slots and preserving the termios structure.
  3.1307 +	 */
  3.1308 +	release_mem(tty, idx);
  3.1309 +}
  3.1310 +
  3.1311 +/*
  3.1312 + * tty_open and tty_release keep up the tty count that contains the
  3.1313 + * number of opens done on a tty. We cannot use the inode-count, as
  3.1314 + * different inodes might point to the same tty.
  3.1315 + *
  3.1316 + * Open-counting is needed for pty masters, as well as for keeping
  3.1317 + * track of serial lines: DTR is dropped when the last close happens.
  3.1318 + * (This is not done solely through tty->count, now.  - Ted 1/27/92)
  3.1319 + *
  3.1320 + * The termios state of a pty is reset on first open so that
  3.1321 + * settings don't persist across reuse.
  3.1322 + */
  3.1323 +static int tty_open(struct inode * inode, struct file * filp)
  3.1324 +{
  3.1325 +	struct tty_struct *tty;
  3.1326 +	int noctty, retval;
  3.1327 +	struct tty_driver *driver;
  3.1328 +	int index;
  3.1329 +	dev_t device = inode->i_rdev;
  3.1330 +	unsigned short saved_flags = filp->f_flags;
  3.1331 +retry_open:
  3.1332 +	noctty = filp->f_flags & O_NOCTTY;
  3.1333 +	if (device == MKDEV(TTYAUX_MAJOR,0)) {
  3.1334 +		if (!current->signal->tty)
  3.1335 +			return -ENXIO;
  3.1336 +		driver = current->signal->tty->driver;
  3.1337 +		index = current->signal->tty->index;
  3.1338 +		filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
  3.1339 +		/* noctty = 1; */
  3.1340 +		goto got_driver;
  3.1341 +	}
  3.1342 +#ifdef CONFIG_VT
  3.1343 +	if (console_use_vt && device == MKDEV(TTY_MAJOR,0)) {
  3.1344 +		extern int fg_console;
  3.1345 +		extern struct tty_driver *console_driver;
  3.1346 +		driver = console_driver;
  3.1347 +		index = fg_console;
  3.1348 +		noctty = 1;
  3.1349 +		goto got_driver;
  3.1350 +	}
  3.1351 +#endif
  3.1352 +	if (device == MKDEV(TTYAUX_MAJOR,1)) {
  3.1353 +		struct console *c = console_drivers;
  3.1354 +		for (c = console_drivers; c; c = c->next) {
  3.1355 +			if (!c->device)
  3.1356 +				continue;
  3.1357 +			driver = c->device(c, &index);
  3.1358 +			if (!driver)
  3.1359 +				continue;
  3.1360 +			/* Don't let /dev/console block */
  3.1361 +			filp->f_flags |= O_NONBLOCK;
  3.1362 +			noctty = 1;
  3.1363 +			goto got_driver;
  3.1364 +		}
  3.1365 +		return -ENODEV;
  3.1366 +	}
  3.1367 +
  3.1368 +#ifdef CONFIG_UNIX98_PTYS
  3.1369 +	if (device == MKDEV(TTYAUX_MAJOR,2)) {
  3.1370 +		/* find a device that is not in use. */
  3.1371 +		static int next_ptmx_dev = 0;
  3.1372 +		retval = -1;
  3.1373 +		driver = ptm_driver;
  3.1374 +		while (driver->refcount < pty_limit) {
  3.1375 +			index = next_ptmx_dev;
  3.1376 +			next_ptmx_dev = (next_ptmx_dev+1) % driver->num;
  3.1377 +			if (!init_dev(driver, index, &tty))
  3.1378 +				goto ptmx_found; /* ok! */
  3.1379 +		}
  3.1380 +		return -EIO; /* no free ptys */
  3.1381 +	ptmx_found:
  3.1382 +		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
  3.1383 +		if (devpts_pty_new(tty->link)) {
  3.1384 +			/* BADNESS - need to destroy both ptm and pts! */
  3.1385 +			return -ENOMEM;
  3.1386 +		}
  3.1387 +		noctty = 1;
  3.1388 +	} else
  3.1389 +#endif
  3.1390 +	{
  3.1391 +		driver = get_tty_driver(device, &index);
  3.1392 +		if (!driver)
  3.1393 +			return -ENODEV;
  3.1394 +got_driver:
  3.1395 +		retval = init_dev(driver, index, &tty);
  3.1396 +		if (retval)
  3.1397 +			return retval;
  3.1398 +	}
  3.1399 +
  3.1400 +	filp->private_data = tty;
  3.1401 +	file_move(filp, &tty->tty_files);
  3.1402 +	check_tty_count(tty, "tty_open");
  3.1403 +	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
  3.1404 +	    tty->driver->subtype == PTY_TYPE_MASTER)
  3.1405 +		noctty = 1;
  3.1406 +#ifdef TTY_DEBUG_HANGUP
  3.1407 +	printk(KERN_DEBUG "opening %s...", tty->name);
  3.1408 +#endif
  3.1409 +	if (tty->driver->open)
  3.1410 +		retval = tty->driver->open(tty, filp);
  3.1411 +	else
  3.1412 +		retval = -ENODEV;
  3.1413 +	filp->f_flags = saved_flags;
  3.1414 +
  3.1415 +	if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
  3.1416 +		retval = -EBUSY;
  3.1417 +
  3.1418 +	if (retval) {
  3.1419 +#ifdef TTY_DEBUG_HANGUP
  3.1420 +		printk(KERN_DEBUG "error %d in opening %s...", retval,
  3.1421 +		       tty->name);
  3.1422 +#endif
  3.1423 +
  3.1424 +		release_dev(filp);
  3.1425 +		if (retval != -ERESTARTSYS)
  3.1426 +			return retval;
  3.1427 +		if (signal_pending(current))
  3.1428 +			return retval;
  3.1429 +		schedule();
  3.1430 +		/*
  3.1431 +		 * Need to reset f_op in case a hangup happened.
  3.1432 +		 */
  3.1433 +		if (filp->f_op == &hung_up_tty_fops)
  3.1434 +			filp->f_op = &tty_fops;
  3.1435 +		goto retry_open;
  3.1436 +	}
  3.1437 +	if (!noctty &&
  3.1438 +	    current->signal->leader &&
  3.1439 +	    !current->signal->tty &&
  3.1440 +	    tty->session == 0) {
  3.1441 +	    	task_lock(current);
  3.1442 +		current->signal->tty = tty;
  3.1443 +		task_unlock(current);
  3.1444 +		current->signal->tty_old_pgrp = 0;
  3.1445 +		tty->session = current->signal->session;
  3.1446 +		tty->pgrp = process_group(current);
  3.1447 +	}
  3.1448 +	return 0;
  3.1449 +}
  3.1450 +
  3.1451 +static int tty_release(struct inode * inode, struct file * filp)
  3.1452 +{
  3.1453 +	lock_kernel();
  3.1454 +	release_dev(filp);
  3.1455 +	unlock_kernel();
  3.1456 +	return 0;
  3.1457 +}
  3.1458 +
  3.1459 +/* No kernel lock held - fine */
  3.1460 +static unsigned int tty_poll(struct file * filp, poll_table * wait)
  3.1461 +{
  3.1462 +	struct tty_struct * tty;
  3.1463 +
  3.1464 +	tty = (struct tty_struct *)filp->private_data;
  3.1465 +	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
  3.1466 +		return 0;
  3.1467 +
  3.1468 +	if (tty->ldisc.poll)
  3.1469 +		return (tty->ldisc.poll)(tty, filp, wait);
  3.1470 +	return 0;
  3.1471 +}
  3.1472 +
  3.1473 +static int tty_fasync(int fd, struct file * filp, int on)
  3.1474 +{
  3.1475 +	struct tty_struct * tty;
  3.1476 +	int retval;
  3.1477 +
  3.1478 +	tty = (struct tty_struct *)filp->private_data;
  3.1479 +	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync"))
  3.1480 +		return 0;
  3.1481 +	
  3.1482 +	retval = fasync_helper(fd, filp, on, &tty->fasync);
  3.1483 +	if (retval <= 0)
  3.1484 +		return retval;
  3.1485 +
  3.1486 +	if (on) {
  3.1487 +		if (!waitqueue_active(&tty->read_wait))
  3.1488 +			tty->minimum_to_wake = 1;
  3.1489 +		retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
  3.1490 +		if (retval)
  3.1491 +			return retval;
  3.1492 +	} else {
  3.1493 +		if (!tty->fasync && !waitqueue_active(&tty->read_wait))
  3.1494 +			tty->minimum_to_wake = N_TTY_BUF_SIZE;
  3.1495 +	}
  3.1496 +	return 0;
  3.1497 +}
  3.1498 +
  3.1499 +static int tiocsti(struct tty_struct *tty, char __user *p)
  3.1500 +{
  3.1501 +	char ch, mbz = 0;
  3.1502 +
  3.1503 +	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
  3.1504 +		return -EPERM;
  3.1505 +	if (get_user(ch, p))
  3.1506 +		return -EFAULT;
  3.1507 +	tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
  3.1508 +	return 0;
  3.1509 +}
  3.1510 +
  3.1511 +static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
  3.1512 +{
  3.1513 +	if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
  3.1514 +		return -EFAULT;
  3.1515 +	return 0;
  3.1516 +}
  3.1517 +
  3.1518 +static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
  3.1519 +	struct winsize __user * arg)
  3.1520 +{
  3.1521 +	struct winsize tmp_ws;
  3.1522 +
  3.1523 +	if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
  3.1524 +		return -EFAULT;
  3.1525 +	if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
  3.1526 +		return 0;
  3.1527 +#ifdef CONFIG_VT
  3.1528 +	if (console_use_vt && tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
  3.1529 +		unsigned int currcons = tty->index;
  3.1530 +		int rc;
  3.1531 +
  3.1532 +		acquire_console_sem();
  3.1533 +		rc = vc_resize(currcons, tmp_ws.ws_col, tmp_ws.ws_row);
  3.1534 +		release_console_sem();
  3.1535 +		if (rc)
  3.1536 +			return -ENXIO;
  3.1537 +	}
  3.1538 +#endif
  3.1539 +	if (tty->pgrp > 0)
  3.1540 +		kill_pg(tty->pgrp, SIGWINCH, 1);
  3.1541 +	if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
  3.1542 +		kill_pg(real_tty->pgrp, SIGWINCH, 1);
  3.1543 +	tty->winsize = tmp_ws;
  3.1544 +	real_tty->winsize = tmp_ws;
  3.1545 +	return 0;
  3.1546 +}
  3.1547 +
  3.1548 +static int tioccons(struct file *file)
  3.1549 +{
  3.1550 +	if (file->f_op->write == redirected_tty_write) {
  3.1551 +		struct file *f;
  3.1552 +		if (!capable(CAP_SYS_ADMIN))
  3.1553 +			return -EPERM;
  3.1554 +		spin_lock(&redirect_lock);
  3.1555 +		f = redirect;
  3.1556 +		redirect = NULL;
  3.1557 +		spin_unlock(&redirect_lock);
  3.1558 +		if (f)
  3.1559 +			fput(f);
  3.1560 +		return 0;
  3.1561 +	}
  3.1562 +	spin_lock(&redirect_lock);
  3.1563 +	if (redirect) {
  3.1564 +		spin_unlock(&redirect_lock);
  3.1565 +		return -EBUSY;
  3.1566 +	}
  3.1567 +	get_file(file);
  3.1568 +	redirect = file;
  3.1569 +	spin_unlock(&redirect_lock);
  3.1570 +	return 0;
  3.1571 +}
  3.1572 +
  3.1573 +
  3.1574 +static int fionbio(struct file *file, int __user *p)
  3.1575 +{
  3.1576 +	int nonblock;
  3.1577 +
  3.1578 +	if (get_user(nonblock, p))
  3.1579 +		return -EFAULT;
  3.1580 +
  3.1581 +	if (nonblock)
  3.1582 +		file->f_flags |= O_NONBLOCK;
  3.1583 +	else
  3.1584 +		file->f_flags &= ~O_NONBLOCK;
  3.1585 +	return 0;
  3.1586 +}
  3.1587 +
  3.1588 +static int tiocsctty(struct tty_struct *tty, int arg)
  3.1589 +{
  3.1590 +	struct list_head *l;
  3.1591 +	struct pid *pid;
  3.1592 +	task_t *p;
  3.1593 +
  3.1594 +	if (current->signal->leader &&
  3.1595 +	    (current->signal->session == tty->session))
  3.1596 +		return 0;
  3.1597 +	/*
  3.1598 +	 * The process must be a session leader and
  3.1599 +	 * not have a controlling tty already.
  3.1600 +	 */
  3.1601 +	if (!current->signal->leader || current->signal->tty)
  3.1602 +		return -EPERM;
  3.1603 +	if (tty->session > 0) {
  3.1604 +		/*
  3.1605 +		 * This tty is already the controlling
  3.1606 +		 * tty for another session group!
  3.1607 +		 */
  3.1608 +		if ((arg == 1) && capable(CAP_SYS_ADMIN)) {
  3.1609 +			/*
  3.1610 +			 * Steal it away
  3.1611 +			 */
  3.1612 +
  3.1613 +			read_lock(&tasklist_lock);
  3.1614 +			for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
  3.1615 +				p->signal->tty = NULL;
  3.1616 +			read_unlock(&tasklist_lock);
  3.1617 +		} else
  3.1618 +			return -EPERM;
  3.1619 +	}
  3.1620 +	task_lock(current);
  3.1621 +	current->signal->tty = tty;
  3.1622 +	task_unlock(current);
  3.1623 +	current->signal->tty_old_pgrp = 0;
  3.1624 +	tty->session = current->signal->session;
  3.1625 +	tty->pgrp = process_group(current);
  3.1626 +	return 0;
  3.1627 +}
  3.1628 +
  3.1629 +static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
  3.1630 +{
  3.1631 +	/*
  3.1632 +	 * (tty == real_tty) is a cheap way of
  3.1633 +	 * testing if the tty is NOT a master pty.
  3.1634 +	 */
  3.1635 +	if (tty == real_tty && current->signal->tty != real_tty)
  3.1636 +		return -ENOTTY;
  3.1637 +	return put_user(real_tty->pgrp, p);
  3.1638 +}
  3.1639 +
  3.1640 +static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
  3.1641 +{
  3.1642 +	pid_t pgrp;
  3.1643 +	int retval = tty_check_change(real_tty);
  3.1644 +
  3.1645 +	if (retval == -EIO)
  3.1646 +		return -ENOTTY;
  3.1647 +	if (retval)
  3.1648 +		return retval;
  3.1649 +	if (!current->signal->tty ||
  3.1650 +	    (current->signal->tty != real_tty) ||
  3.1651 +	    (real_tty->session != current->signal->session))
  3.1652 +		return -ENOTTY;
  3.1653 +	if (get_user(pgrp, p))
  3.1654 +		return -EFAULT;
  3.1655 +	if (pgrp < 0)
  3.1656 +		return -EINVAL;
  3.1657 +	if (session_of_pgrp(pgrp) != current->signal->session)
  3.1658 +		return -EPERM;
  3.1659 +	real_tty->pgrp = pgrp;
  3.1660 +	return 0;
  3.1661 +}
  3.1662 +
  3.1663 +static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
  3.1664 +{
  3.1665 +	/*
  3.1666 +	 * (tty == real_tty) is a cheap way of
  3.1667 +	 * testing if the tty is NOT a master pty.
  3.1668 +	*/
  3.1669 +	if (tty == real_tty && current->signal->tty != real_tty)
  3.1670 +		return -ENOTTY;
  3.1671 +	if (real_tty->session <= 0)
  3.1672 +		return -ENOTTY;
  3.1673 +	return put_user(real_tty->session, p);
  3.1674 +}
  3.1675 +
  3.1676 +static int tiocsetd(struct tty_struct *tty, int __user *p)
  3.1677 +{
  3.1678 +	int ldisc;
  3.1679 +
  3.1680 +	if (get_user(ldisc, p))
  3.1681 +		return -EFAULT;
  3.1682 +	return tty_set_ldisc(tty, ldisc);
  3.1683 +}
  3.1684 +
  3.1685 +static int send_break(struct tty_struct *tty, int duration)
  3.1686 +{
  3.1687 +	set_current_state(TASK_INTERRUPTIBLE);
  3.1688 +
  3.1689 +	tty->driver->break_ctl(tty, -1);
  3.1690 +	if (!signal_pending(current))
  3.1691 +		schedule_timeout(duration);
  3.1692 +	tty->driver->break_ctl(tty, 0);
  3.1693 +	if (signal_pending(current))
  3.1694 +		return -EINTR;
  3.1695 +	return 0;
  3.1696 +}
  3.1697 +
  3.1698 +static int
  3.1699 +tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
  3.1700 +{
  3.1701 +	int retval = -EINVAL;
  3.1702 +
  3.1703 +	if (tty->driver->tiocmget) {
  3.1704 +		retval = tty->driver->tiocmget(tty, file);
  3.1705 +
  3.1706 +		if (retval >= 0)
  3.1707 +			retval = put_user(retval, p);
  3.1708 +	}
  3.1709 +	return retval;
  3.1710 +}
  3.1711 +
  3.1712 +static int
  3.1713 +tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
  3.1714 +	     unsigned __user *p)
  3.1715 +{
  3.1716 +	int retval = -EINVAL;
  3.1717 +
  3.1718 +	if (tty->driver->tiocmset) {
  3.1719 +		unsigned int set, clear, val;
  3.1720 +
  3.1721 +		retval = get_user(val, p);
  3.1722 +		if (retval)
  3.1723 +			return retval;
  3.1724 +
  3.1725 +		set = clear = 0;
  3.1726 +		switch (cmd) {
  3.1727 +		case TIOCMBIS:
  3.1728 +			set = val;
  3.1729 +			break;
  3.1730 +		case TIOCMBIC:
  3.1731 +			clear = val;
  3.1732 +			break;
  3.1733 +		case TIOCMSET:
  3.1734 +			set = val;
  3.1735 +			clear = ~val;
  3.1736 +			break;
  3.1737 +		}
  3.1738 +
  3.1739 +		set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
  3.1740 +		clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
  3.1741 +
  3.1742 +		retval = tty->driver->tiocmset(tty, file, set, clear);
  3.1743 +	}
  3.1744 +	return retval;
  3.1745 +}
  3.1746 +
  3.1747 +/*
  3.1748 + * Split this up, as gcc can choke on it otherwise..
  3.1749 + */
  3.1750 +int tty_ioctl(struct inode * inode, struct file * file,
  3.1751 +	      unsigned int cmd, unsigned long arg)
  3.1752 +{
  3.1753 +	struct tty_struct *tty, *real_tty;
  3.1754 +	void __user *p = (void __user *)arg;
  3.1755 +	int retval;
  3.1756 +	
  3.1757 +	tty = (struct tty_struct *)file->private_data;
  3.1758 +	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
  3.1759 +		return -EINVAL;
  3.1760 +
  3.1761 +	real_tty = tty;
  3.1762 +	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
  3.1763 +	    tty->driver->subtype == PTY_TYPE_MASTER)
  3.1764 +		real_tty = tty->link;
  3.1765 +
  3.1766 +	/*
  3.1767 +	 * Break handling by driver
  3.1768 +	 */
  3.1769 +	if (!tty->driver->break_ctl) {
  3.1770 +		switch(cmd) {
  3.1771 +		case TIOCSBRK:
  3.1772 +		case TIOCCBRK:
  3.1773 +			if (tty->driver->ioctl)
  3.1774 +				return tty->driver->ioctl(tty, file, cmd, arg);
  3.1775 +			return -EINVAL;
  3.1776 +			
  3.1777 +		/* These two ioctl's always return success; even if */
  3.1778 +		/* the driver doesn't support them. */
  3.1779 +		case TCSBRK:
  3.1780 +		case TCSBRKP:
  3.1781 +			if (!tty->driver->ioctl)
  3.1782 +				return 0;
  3.1783 +			retval = tty->driver->ioctl(tty, file, cmd, arg);
  3.1784 +			if (retval == -ENOIOCTLCMD)
  3.1785 +				retval = 0;
  3.1786 +			return retval;
  3.1787 +		}
  3.1788 +	}
  3.1789 +
  3.1790 +	/*
  3.1791 +	 * Factor out some common prep work
  3.1792 +	 */
  3.1793 +	switch (cmd) {
  3.1794 +	case TIOCSETD:
  3.1795 +	case TIOCSBRK:
  3.1796 +	case TIOCCBRK:
  3.1797 +	case TCSBRK:
  3.1798 +	case TCSBRKP:			
  3.1799 +		retval = tty_check_change(tty);
  3.1800 +		if (retval)
  3.1801 +			return retval;
  3.1802 +		if (cmd != TIOCCBRK) {
  3.1803 +			tty_wait_until_sent(tty, 0);
  3.1804 +			if (signal_pending(current))
  3.1805 +				return -EINTR;
  3.1806 +		}
  3.1807 +		break;
  3.1808 +	}
  3.1809 +
  3.1810 +	switch (cmd) {
  3.1811 +		case TIOCSTI:
  3.1812 +			return tiocsti(tty, p);
  3.1813 +		case TIOCGWINSZ:
  3.1814 +			return tiocgwinsz(tty, p);
  3.1815 +		case TIOCSWINSZ:
  3.1816 +			return tiocswinsz(tty, real_tty, p);
  3.1817 +		case TIOCCONS:
  3.1818 +			return real_tty!=tty ? -EINVAL : tioccons(file);
  3.1819 +		case FIONBIO:
  3.1820 +			return fionbio(file, p);
  3.1821 +		case TIOCEXCL:
  3.1822 +			set_bit(TTY_EXCLUSIVE, &tty->flags);
  3.1823 +			return 0;
  3.1824 +		case TIOCNXCL:
  3.1825 +			clear_bit(TTY_EXCLUSIVE, &tty->flags);
  3.1826 +			return 0;
  3.1827 +		case TIOCNOTTY:
  3.1828 +			if (current->signal->tty != tty)
  3.1829 +				return -ENOTTY;
  3.1830 +			if (current->signal->leader)
  3.1831 +				disassociate_ctty(0);
  3.1832 +			task_lock(current);
  3.1833 +			current->signal->tty = NULL;
  3.1834 +			task_unlock(current);
  3.1835 +			return 0;
  3.1836 +		case TIOCSCTTY:
  3.1837 +			return tiocsctty(tty, arg);
  3.1838 +		case TIOCGPGRP:
  3.1839 +			return tiocgpgrp(tty, real_tty, p);
  3.1840 +		case TIOCSPGRP:
  3.1841 +			return tiocspgrp(tty, real_tty, p);
  3.1842 +		case TIOCGSID:
  3.1843 +			return tiocgsid(tty, real_tty, p);
  3.1844 +		case TIOCGETD:
  3.1845 +			return put_user(tty->ldisc.num, (int __user *)p);
  3.1846 +		case TIOCSETD:
  3.1847 +			return tiocsetd(tty, p);
  3.1848 +#ifdef CONFIG_VT
  3.1849 +		case TIOCLINUX:
  3.1850 +			return tioclinux(tty, arg);
  3.1851 +#endif
  3.1852 +		/*
  3.1853 +		 * Break handling
  3.1854 +		 */
  3.1855 +		case TIOCSBRK:	/* Turn break on, unconditionally */
  3.1856 +			tty->driver->break_ctl(tty, -1);
  3.1857 +			return 0;
  3.1858 +			
  3.1859 +		case TIOCCBRK:	/* Turn break off, unconditionally */
  3.1860 +			tty->driver->break_ctl(tty, 0);
  3.1861 +			return 0;
  3.1862 +		case TCSBRK:   /* SVID version: non-zero arg --> no break */
  3.1863 +			/*
  3.1864 +			 * XXX is the above comment correct, or the
  3.1865 +			 * code below correct?  Is this ioctl used at
  3.1866 +			 * all by anyone?
  3.1867 +			 */
  3.1868 +			if (!arg)
  3.1869 +				return send_break(tty, HZ/4);
  3.1870 +			return 0;
  3.1871 +		case TCSBRKP:	/* support for POSIX tcsendbreak() */	
  3.1872 +			return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
  3.1873 +
  3.1874 +		case TIOCMGET:
  3.1875 +			return tty_tiocmget(tty, file, p);
  3.1876 +
  3.1877 +		case TIOCMSET:
  3.1878 +		case TIOCMBIC:
  3.1879 +		case TIOCMBIS:
  3.1880 +			return tty_tiocmset(tty, file, cmd, p);
  3.1881 +	}
  3.1882 +	if (tty->driver->ioctl) {
  3.1883 +		int retval = (tty->driver->ioctl)(tty, file, cmd, arg);
  3.1884 +		if (retval != -ENOIOCTLCMD)
  3.1885 +			return retval;
  3.1886 +	}
  3.1887 +	if (tty->ldisc.ioctl) {
  3.1888 +		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
  3.1889 +		if (retval != -ENOIOCTLCMD)
  3.1890 +			return retval;
  3.1891 +	}
  3.1892 +	return -EINVAL;
  3.1893 +}
  3.1894 +
  3.1895 +
  3.1896 +/*
  3.1897 + * This implements the "Secure Attention Key" ---  the idea is to
  3.1898 + * prevent trojan horses by killing all processes associated with this
  3.1899 + * tty when the user hits the "Secure Attention Key".  Required for
  3.1900 + * super-paranoid applications --- see the Orange Book for more details.
  3.1901 + * 
  3.1902 + * This code could be nicer; ideally it should send a HUP, wait a few
  3.1903 + * seconds, then send a INT, and then a KILL signal.  But you then
  3.1904 + * have to coordinate with the init process, since all processes associated
  3.1905 + * with the current tty must be dead before the new getty is allowed
  3.1906 + * to spawn.
  3.1907 + *
  3.1908 + * Now, if it would be correct ;-/ The current code has a nasty hole -
  3.1909 + * it doesn't catch files in flight. We may send the descriptor to ourselves
  3.1910 + * via AF_UNIX socket, close it and later fetch from socket. FIXME.
  3.1911 + *
  3.1912 + * Nasty bug: do_SAK is being called in interrupt context.  This can
  3.1913 + * deadlock.  We punt it up to process context.  AKPM - 16Mar2001
  3.1914 + */
  3.1915 +static void __do_SAK(void *arg)
  3.1916 +{
  3.1917 +#ifdef TTY_SOFT_SAK
  3.1918 +	tty_hangup(tty);
  3.1919 +#else
  3.1920 +	struct tty_struct *tty = arg;
  3.1921 +	struct task_struct *p;
  3.1922 +	struct list_head *l;
  3.1923 +	struct pid *pid;
  3.1924 +	int session;
  3.1925 +	int		i;
  3.1926 +	struct file	*filp;
  3.1927 +	
  3.1928 +	if (!tty)
  3.1929 +		return;
  3.1930 +	session  = tty->session;
  3.1931 +	if (tty->ldisc.flush_buffer)
  3.1932 +		tty->ldisc.flush_buffer(tty);
  3.1933 +	if (tty->driver->flush_buffer)
  3.1934 +		tty->driver->flush_buffer(tty);
  3.1935 +	read_lock(&tasklist_lock);
  3.1936 +	for_each_task_pid(session, PIDTYPE_SID, p, l, pid) {
  3.1937 +		if (p->signal->tty == tty || session > 0) {
  3.1938 +			printk(KERN_NOTICE "SAK: killed process %d"
  3.1939 +			    " (%s): p->signal->session==tty->session\n",
  3.1940 +			    p->pid, p->comm);
  3.1941 +			send_sig(SIGKILL, p, 1);
  3.1942 +			continue;
  3.1943 +		}
  3.1944 +		task_lock(p);
  3.1945 +		if (p->files) {
  3.1946 +			spin_lock(&p->files->file_lock);
  3.1947 +			for (i=0; i < p->files->max_fds; i++) {
  3.1948 +				filp = fcheck_files(p->files, i);
  3.1949 +				if (!filp)
  3.1950 +					continue;
  3.1951 +				if (filp->f_op->read == tty_read &&
  3.1952 +				    filp->private_data == tty) {
  3.1953 +					printk(KERN_NOTICE "SAK: killed process %d"
  3.1954 +					    " (%s): fd#%d opened to the tty\n",
  3.1955 +					    p->pid, p->comm, i);
  3.1956 +					send_sig(SIGKILL, p, 1);
  3.1957 +					break;
  3.1958 +				}
  3.1959 +			}
  3.1960 +			spin_unlock(&p->files->file_lock);
  3.1961 +		}
  3.1962 +		task_unlock(p);
  3.1963 +	}
  3.1964 +	read_unlock(&tasklist_lock);
  3.1965 +#endif
  3.1966 +}
  3.1967 +
  3.1968 +/*
  3.1969 + * The tq handling here is a little racy - tty->SAK_work may already be queued.
  3.1970 + * Fortunately we don't need to worry, because if ->SAK_work is already queued,
  3.1971 + * the values which we write to it will be identical to the values which it
  3.1972 + * already has. --akpm
  3.1973 + */
  3.1974 +void do_SAK(struct tty_struct *tty)
  3.1975 +{
  3.1976 +	if (!tty)
  3.1977 +		return;
  3.1978 +	PREPARE_WORK(&tty->SAK_work, __do_SAK, tty);
  3.1979 +	schedule_work(&tty->SAK_work);
  3.1980 +}
  3.1981 +
  3.1982 +EXPORT_SYMBOL(do_SAK);
  3.1983 +
  3.1984 +/*
  3.1985 + * This routine is called out of the software interrupt to flush data
  3.1986 + * from the flip buffer to the line discipline.
  3.1987 + */
  3.1988 +static void flush_to_ldisc(void *private_)
  3.1989 +{
  3.1990 +	struct tty_struct *tty = (struct tty_struct *) private_;
  3.1991 +	unsigned char	*cp;
  3.1992 +	char		*fp;
  3.1993 +	int		count;
  3.1994 +	unsigned long flags;
  3.1995 +
  3.1996 +	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
  3.1997 +		/*
  3.1998 +		 * Do it after the next timer tick:
  3.1999 +		 */
  3.2000 +		schedule_delayed_work(&tty->flip.work, 1);
  3.2001 +		return;
  3.2002 +	}
  3.2003 +
  3.2004 +	spin_lock_irqsave(&tty->read_lock, flags);
  3.2005 +	if (tty->flip.buf_num) {
  3.2006 +		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
  3.2007 +		fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
  3.2008 +		tty->flip.buf_num = 0;
  3.2009 +		tty->flip.char_buf_ptr = tty->flip.char_buf;
  3.2010 +		tty->flip.flag_buf_ptr = tty->flip.flag_buf;
  3.2011 +	} else {
  3.2012 +		cp = tty->flip.char_buf;
  3.2013 +		fp = tty->flip.flag_buf;
  3.2014 +		tty->flip.buf_num = 1;
  3.2015 +		tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
  3.2016 +		tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
  3.2017 +	}
  3.2018 +	count = tty->flip.count;
  3.2019 +	tty->flip.count = 0;
  3.2020 +	spin_unlock_irqrestore(&tty->read_lock, flags);
  3.2021 +
  3.2022 +	tty->ldisc.receive_buf(tty, cp, fp, count);
  3.2023 +}
  3.2024 +
  3.2025 +/*
  3.2026 + * Routine which returns the baud rate of the tty
  3.2027 + *
  3.2028 + * Note that the baud_table needs to be kept in sync with the
  3.2029 + * include/asm/termbits.h file.
  3.2030 + */
  3.2031 +static int baud_table[] = {
  3.2032 +	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
  3.2033 +	9600, 19200, 38400, 57600, 115200, 230400, 460800,
  3.2034 +#ifdef __sparc__
  3.2035 +	76800, 153600, 307200, 614400, 921600
  3.2036 +#else
  3.2037 +	500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
  3.2038 +	2500000, 3000000, 3500000, 4000000
  3.2039 +#endif
  3.2040 +};
  3.2041 +
  3.2042 +static int n_baud_table = ARRAY_SIZE(baud_table);
  3.2043 +
  3.2044 +int tty_termios_baud_rate(struct termios *termios)
  3.2045 +{
  3.2046 +	unsigned int cbaud = termios->c_cflag & CBAUD;
  3.2047 +
  3.2048 +	if (cbaud & CBAUDEX) {
  3.2049 +		cbaud &= ~CBAUDEX;
  3.2050 +
  3.2051 +		if (cbaud < 1 || cbaud + 15 > n_baud_table)
  3.2052 +			termios->c_cflag &= ~CBAUDEX;
  3.2053 +		else
  3.2054 +			cbaud += 15;
  3.2055 +	}
  3.2056 +
  3.2057 +	return baud_table[cbaud];
  3.2058 +}
  3.2059 +
  3.2060 +EXPORT_SYMBOL(tty_termios_baud_rate);
  3.2061 +
  3.2062 +int tty_get_baud_rate(struct tty_struct *tty)
  3.2063 +{
  3.2064 +	int baud = tty_termios_baud_rate(tty->termios);
  3.2065 +
  3.2066 +	if (baud == 38400 && tty->alt_speed) {
  3.2067 +		if (!tty->warned) {
  3.2068 +			printk(KERN_WARNING "Use of setserial/setrocket to "
  3.2069 +					    "set SPD_* flags is deprecated\n");
  3.2070 +			tty->warned = 1;
  3.2071 +		}
  3.2072 +		baud = tty->alt_speed;
  3.2073 +	}
  3.2074 +	
  3.2075 +	return baud;
  3.2076 +}
  3.2077 +
  3.2078 +EXPORT_SYMBOL(tty_get_baud_rate);
  3.2079 +
  3.2080 +void tty_flip_buffer_push(struct tty_struct *tty)
  3.2081 +{
  3.2082 +	if (tty->low_latency)
  3.2083 +		flush_to_ldisc((void *) tty);
  3.2084 +	else
  3.2085 +		schedule_delayed_work(&tty->flip.work, 1);
  3.2086 +}
  3.2087 +
  3.2088 +EXPORT_SYMBOL(tty_flip_buffer_push);
  3.2089 +
  3.2090 +/*
  3.2091 + * This subroutine initializes a tty structure.
  3.2092 + */
  3.2093 +static void initialize_tty_struct(struct tty_struct *tty)
  3.2094 +{
  3.2095 +	memset(tty, 0, sizeof(struct tty_struct));
  3.2096 +	tty->magic = TTY_MAGIC;
  3.2097 +	tty->ldisc = ldiscs[N_TTY];
  3.2098 +	tty->pgrp = -1;
  3.2099 +	tty->flip.char_buf_ptr = tty->flip.char_buf;
  3.2100 +	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
  3.2101 +	INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
  3.2102 +	init_MUTEX(&tty->flip.pty_sem);
  3.2103 +	init_waitqueue_head(&tty->write_wait);
  3.2104 +	init_waitqueue_head(&tty->read_wait);
  3.2105 +	INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
  3.2106 +	sema_init(&tty->atomic_read, 1);
  3.2107 +	sema_init(&tty->atomic_write, 1);
  3.2108 +	spin_lock_init(&tty->read_lock);
  3.2109 +	INIT_LIST_HEAD(&tty->tty_files);
  3.2110 +	INIT_WORK(&tty->SAK_work, NULL, NULL);
  3.2111 +}
  3.2112 +
  3.2113 +/*
  3.2114 + * The default put_char routine if the driver did not define one.
  3.2115 + */
  3.2116 +static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
  3.2117 +{
  3.2118 +	tty->driver->write(tty, 0, &ch, 1);
  3.2119 +}
  3.2120 +
  3.2121 +static struct class_simple *tty_class;
  3.2122 +
  3.2123 +/**
  3.2124 + * tty_register_device - register a tty device
  3.2125 + * @driver: the tty driver that describes the tty device
  3.2126 + * @index: the index in the tty driver for this tty device
  3.2127 + * @device: a struct device that is associated with this tty device.
  3.2128 + *	This field is optional, if there is no known struct device for this
  3.2129 + *	tty device it can be set to NULL safely.
  3.2130 + *
  3.2131 + * This call is required to be made to register an individual tty device if
  3.2132 + * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set.  If that
  3.2133 + * bit is not set, this function should not be called.
  3.2134 + */
  3.2135 +void tty_register_device(struct tty_driver *driver, unsigned index,
  3.2136 +			 struct device *device)
  3.2137 +{
  3.2138 +	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
  3.2139 +
  3.2140 +	if (index >= driver->num) {
  3.2141 +		printk(KERN_ERR "Attempt to register invalid tty line number "
  3.2142 +		       " (%d).\n", index);
  3.2143 +		return;
  3.2144 +	}
  3.2145 +
  3.2146 +	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
  3.2147 +			"%s%d", driver->devfs_name, index + driver->name_base);
  3.2148 +
  3.2149 +	/* we don't care about the ptys */
  3.2150 +	/* how nice to hide this behind some crappy interface.. */
  3.2151 +	if (driver->type != TTY_DRIVER_TYPE_PTY) {
  3.2152 +		char name[64];
  3.2153 +		tty_line_name(driver, index, name);
  3.2154 +		class_simple_device_add(tty_class, dev, device, name);
  3.2155 +	}
  3.2156 +}
  3.2157 +
  3.2158 +/**
  3.2159 + * tty_unregister_device - unregister a tty device
  3.2160 + * @driver: the tty driver that describes the tty device
  3.2161 + * @index: the index in the tty driver for this tty device
  3.2162 + *
  3.2163 + * If a tty device is registered with a call to tty_register_device() then
  3.2164 + * this function must be made when the tty device is gone.
  3.2165 + */
  3.2166 +void tty_unregister_device(struct tty_driver *driver, unsigned index)
  3.2167 +{
  3.2168 +	devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
  3.2169 +	class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index);
  3.2170 +}
  3.2171 +
  3.2172 +EXPORT_SYMBOL(tty_register_device);
  3.2173 +EXPORT_SYMBOL(tty_unregister_device);
  3.2174 +
  3.2175 +struct tty_driver *alloc_tty_driver(int lines)
  3.2176 +{
  3.2177 +	struct tty_driver *driver;
  3.2178 +
  3.2179 +	driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
  3.2180 +	if (driver) {
  3.2181 +		memset(driver, 0, sizeof(struct tty_driver));
  3.2182 +		driver->magic = TTY_DRIVER_MAGIC;
  3.2183 +		driver->num = lines;
  3.2184 +		/* later we'll move allocation of tables here */
  3.2185 +	}
  3.2186 +	return driver;
  3.2187 +}
  3.2188 +
  3.2189 +void put_tty_driver(struct tty_driver *driver)
  3.2190 +{
  3.2191 +	kfree(driver);
  3.2192 +}
  3.2193 +
  3.2194 +void tty_set_operations(struct tty_driver *driver, struct tty_operations *op)
  3.2195 +{
  3.2196 +	driver->open = op->open;
  3.2197 +	driver->close = op->close;
  3.2198 +	driver->write = op->write;
  3.2199 +	driver->put_char = op->put_char;
  3.2200 +	driver->flush_chars = op->flush_chars;
  3.2201 +	driver->write_room = op->write_room;
  3.2202 +	driver->chars_in_buffer = op->chars_in_buffer;
  3.2203 +	driver->ioctl = op->ioctl;
  3.2204 +	driver->set_termios = op->set_termios;
  3.2205 +	driver->throttle = op->throttle;
  3.2206 +	driver->unthrottle = op->unthrottle;
  3.2207 +	driver->stop = op->stop;
  3.2208 +	driver->start = op->start;
  3.2209 +	driver->hangup = op->hangup;
  3.2210 +	driver->break_ctl = op->break_ctl;
  3.2211 +	driver->flush_buffer = op->flush_buffer;
  3.2212 +	driver->set_ldisc = op->set_ldisc;
  3.2213 +	driver->wait_until_sent = op->wait_until_sent;
  3.2214 +	driver->send_xchar = op->send_xchar;
  3.2215 +	driver->read_proc = op->read_proc;
  3.2216 +	driver->write_proc = op->write_proc;
  3.2217 +	driver->tiocmget = op->tiocmget;
  3.2218 +	driver->tiocmset = op->tiocmset;
  3.2219 +}
  3.2220 +
  3.2221 +
  3.2222 +EXPORT_SYMBOL(alloc_tty_driver);
  3.2223 +EXPORT_SYMBOL(put_tty_driver);
  3.2224 +EXPORT_SYMBOL(tty_set_operations);
  3.2225 +
  3.2226 +/*
  3.2227 + * Called by a tty driver to register itself.
  3.2228 + */
  3.2229 +int tty_register_driver(struct tty_driver *driver)
  3.2230 +{
  3.2231 +	int error;
  3.2232 +        int i;
  3.2233 +	dev_t dev;
  3.2234 +	void **p = NULL;
  3.2235 +
  3.2236 +	if (driver->flags & TTY_DRIVER_INSTALLED)
  3.2237 +		return 0;
  3.2238 +
  3.2239 +	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
  3.2240 +		p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
  3.2241 +		if (!p)
  3.2242 +			return -ENOMEM;
  3.2243 +		memset(p, 0, driver->num * 3 * sizeof(void *));
  3.2244 +	}
  3.2245 +
  3.2246 +	if (!driver->major) {
  3.2247 +		error = alloc_chrdev_region(&dev, driver->minor_start, driver->num,
  3.2248 +						(char*)driver->name);
  3.2249 +		if (!error) {
  3.2250 +			driver->major = MAJOR(dev);
  3.2251 +			driver->minor_start = MINOR(dev);
  3.2252 +		}
  3.2253 +	} else {
  3.2254 +		dev = MKDEV(driver->major, driver->minor_start);
  3.2255 +		error = register_chrdev_region(dev, driver->num,
  3.2256 +						(char*)driver->name);
  3.2257 +	}
  3.2258 +	if (error < 0) {
  3.2259 +		kfree(p);
  3.2260 +		return error;
  3.2261 +	}
  3.2262 +
  3.2263 +	if (p) {
  3.2264 +		driver->ttys = (struct tty_struct **)p;
  3.2265 +		driver->termios = (struct termios **)(p + driver->num);
  3.2266 +		driver->termios_locked = (struct termios **)(p + driver->num * 2);
  3.2267 +	} else {
  3.2268 +		driver->ttys = NULL;
  3.2269 +		driver->termios = NULL;
  3.2270 +		driver->termios_locked = NULL;
  3.2271 +	}
  3.2272 +
  3.2273 +	cdev_init(&driver->cdev, &tty_fops);
  3.2274 +	driver->cdev.owner = driver->owner;
  3.2275 +	error = cdev_add(&driver->cdev, dev, driver->num);
  3.2276 +	if (error) {
  3.2277 +		cdev_del(&driver->cdev);
  3.2278 +		unregister_chrdev_region(dev, driver->num);
  3.2279 +		driver->ttys = NULL;
  3.2280 +		driver->termios = driver->termios_locked = NULL;
  3.2281 +		kfree(p);
  3.2282 +		return error;
  3.2283 +	}
  3.2284 +
  3.2285 +	if (!driver->put_char)
  3.2286 +		driver->put_char = tty_default_put_char;
  3.2287 +	
  3.2288 +	list_add(&driver->tty_drivers, &tty_drivers);
  3.2289 +	
  3.2290 +	if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) {
  3.2291 +		for(i = 0; i < driver->num; i++)
  3.2292 +		    tty_register_device(driver, i, NULL);
  3.2293 +	}
  3.2294 +	proc_tty_register_driver(driver);
  3.2295 +	return 0;
  3.2296 +}
  3.2297 +
  3.2298 +EXPORT_SYMBOL(tty_register_driver);
  3.2299 +
  3.2300 +/*
  3.2301 + * Called by a tty driver to unregister itself.
  3.2302 + */
  3.2303 +int tty_unregister_driver(struct tty_driver *driver)
  3.2304 +{
  3.2305 +	int i;
  3.2306 +	struct termios *tp;
  3.2307 +	void *p;
  3.2308 +
  3.2309 +	if (driver->refcount)
  3.2310 +		return -EBUSY;
  3.2311 +
  3.2312 +	unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
  3.2313 +				driver->num);
  3.2314 +
  3.2315 +	list_del(&driver->tty_drivers);
  3.2316 +
  3.2317 +	/*
  3.2318 +	 * Free the termios and termios_locked structures because
  3.2319 +	 * we don't want to get memory leaks when modular tty
  3.2320 +	 * drivers are removed from the kernel.
  3.2321 +	 */
  3.2322 +	for (i = 0; i < driver->num; i++) {
  3.2323 +		tp = driver->termios[i];
  3.2324 +		if (tp) {
  3.2325 +			driver->termios[i] = NULL;
  3.2326 +			kfree(tp);
  3.2327 +		}
  3.2328 +		tp = driver->termios_locked[i];
  3.2329 +		if (tp) {
  3.2330 +			driver->termios_locked[i] = NULL;
  3.2331 +			kfree(tp);
  3.2332 +		}
  3.2333 +		if (!(driver->flags & TTY_DRIVER_NO_DEVFS))
  3.2334 +			tty_unregister_device(driver, i);
  3.2335 +	}
  3.2336 +	p = driver->ttys;
  3.2337 +	proc_tty_unregister_driver(driver);
  3.2338 +	driver->ttys = NULL;
  3.2339 +	driver->termios = driver->termios_locked = NULL;
  3.2340 +	kfree(p);
  3.2341 +	cdev_del(&driver->cdev);
  3.2342 +	return 0;
  3.2343 +}
  3.2344 +
  3.2345 +EXPORT_SYMBOL(tty_unregister_driver);
  3.2346 +
  3.2347 +
  3.2348 +/*
  3.2349 + * Initialize the console device. This is called *early*, so
  3.2350 + * we can't necessarily depend on lots of kernel help here.
  3.2351 + * Just do some early initializations, and do the complex setup
  3.2352 + * later.
  3.2353 + */
  3.2354 +void __init console_init(void)
  3.2355 +{
  3.2356 +	initcall_t *call;
  3.2357 +
  3.2358 +	/* Setup the default TTY line discipline. */
  3.2359 +	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
  3.2360 +
  3.2361 +	/*
  3.2362 +	 * set up the console device so that later boot sequences can 
  3.2363 +	 * inform about problems etc..
  3.2364 +	 */
  3.2365 +#ifdef CONFIG_EARLY_PRINTK
  3.2366 +	disable_early_printk();
  3.2367 +#endif
  3.2368 +#ifdef CONFIG_SERIAL_68360
  3.2369 + 	/* This is not a console initcall. I know not what it's doing here.
  3.2370 +	   So I haven't moved it. dwmw2 */
  3.2371 +        rs_360_init();
  3.2372 +#endif
  3.2373 +	call = &__con_initcall_start;
  3.2374 +	while (call < &__con_initcall_end) {
  3.2375 +		(*call)();
  3.2376 +		call++;
  3.2377 +	}
  3.2378 +}
  3.2379 +
  3.2380 +#ifdef CONFIG_VT
  3.2381 +extern int vty_init(void);
  3.2382 +#endif
  3.2383 +
  3.2384 +static int __init tty_class_init(void)
  3.2385 +{
  3.2386 +	tty_class = class_simple_create(THIS_MODULE, "tty");
  3.2387 +	if (IS_ERR(tty_class))
  3.2388 +		return PTR_ERR(tty_class);
  3.2389 +	return 0;
  3.2390 +}
  3.2391 +
  3.2392 +postcore_initcall(tty_class_init);
  3.2393 +
  3.2394 +/* 3/2004 jmc: why do these devices exist? */
  3.2395 +
  3.2396 +static struct cdev tty_cdev, console_cdev;
  3.2397 +#ifdef CONFIG_UNIX98_PTYS
  3.2398 +static struct cdev ptmx_cdev;
  3.2399 +#endif
  3.2400 +#ifdef CONFIG_VT
  3.2401 +static struct cdev vc0_cdev;
  3.2402 +#endif
  3.2403 +
  3.2404 +/*
  3.2405 + * Ok, now we can initialize the rest of the tty devices and can count
  3.2406 + * on memory allocations, interrupts etc..
  3.2407 + */
  3.2408 +static int __init tty_init(void)
  3.2409 +{
  3.2410 +	cdev_init(&tty_cdev, &tty_fops);
  3.2411 +	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
  3.2412 +	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
  3.2413 +		panic("Couldn't register /dev/tty driver\n");
  3.2414 +	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
  3.2415 +	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
  3.2416 +
  3.2417 +	cdev_init(&console_cdev, &console_fops);
  3.2418 +	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
  3.2419 +	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
  3.2420 +		panic("Couldn't register /dev/console driver\n");
  3.2421 +	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
  3.2422 +	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
  3.2423 +
  3.2424 +#ifdef CONFIG_UNIX98_PTYS
  3.2425 +	cdev_init(&ptmx_cdev, &tty_fops);
  3.2426 +	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
  3.2427 +	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
  3.2428 +		panic("Couldn't register /dev/ptmx driver\n");
  3.2429 +	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
  3.2430 +	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
  3.2431 +#endif
  3.2432 +
  3.2433 +#ifdef CONFIG_VT
  3.2434 +	if (console_use_vt) {
  3.2435 +		cdev_init(&vc0_cdev, &console_fops);
  3.2436 +		if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
  3.2437 +		    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1,
  3.2438 +					   "/dev/vc/0") < 0)
  3.2439 +			panic("Couldn't register /dev/tty0 driver\n");
  3.2440 +		devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR,
  3.2441 +			      "vc/0");
  3.2442 +		class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL,
  3.2443 +					"tty0");
  3.2444 +
  3.2445 +		vty_init();
  3.2446 +	}
  3.2447 +#endif
  3.2448 +	return 0;
  3.2449 +}
  3.2450 +module_init(tty_init);
     4.1 --- a/linux-2.6.7-xen-sparse/drivers/xen/console/console.c	Wed Aug 04 17:10:01 2004 +0000
     4.2 +++ b/linux-2.6.7-xen-sparse/drivers/xen/console/console.c	Wed Aug 04 18:58:56 2004 +0000
     4.3 @@ -164,14 +164,7 @@ void xen_console_init(void)
     4.4      else
     4.5      {
     4.6          if ( xc_mode == XC_DEFAULT )
     4.7 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && defined(CONFIG_VT)
     4.8 -            /* On a kernel built with VT support, default to serial
     4.9 -             * console because the VT driver has already allocated the
    4.10 -             * /dev/tty device nodes */
    4.11 -            xc_mode = XC_SERIAL;
    4.12 -#else
    4.13              xc_mode = XC_TTY;
    4.14 -#endif
    4.15          kcons_info.write = kcons_write;
    4.16      }
    4.17  
    4.18 @@ -597,6 +590,44 @@ static struct tty_operations xencons_ops
    4.19      .unthrottle = xencons_unthrottle,
    4.20      .wait_until_sent = xencons_wait_until_sent,
    4.21  };
    4.22 +
    4.23 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
    4.24 +static const char *xennullcon_startup(void)
    4.25 +{
    4.26 +    return NULL;
    4.27 +}
    4.28 +
    4.29 +static int xennullcon_dummy(void)
    4.30 +{
    4.31 +    return 0;
    4.32 +}
    4.33 +
    4.34 +#define DUMMY	(void *)xennullcon_dummy
    4.35 +
    4.36 +/*
    4.37 + *  The console `switch' structure for the dummy console
    4.38 + *
    4.39 + *  Most of the operations are dummies.
    4.40 + */
    4.41 +
    4.42 +const struct consw xennull_con = {
    4.43 +    .owner =		THIS_MODULE,
    4.44 +    .con_startup =	xennullcon_startup,
    4.45 +    .con_init =		DUMMY,
    4.46 +    .con_deinit =	DUMMY,
    4.47 +    .con_clear =	DUMMY,
    4.48 +    .con_putc =		DUMMY,
    4.49 +    .con_putcs =	DUMMY,
    4.50 +    .con_cursor =	DUMMY,
    4.51 +    .con_scroll =	DUMMY,
    4.52 +    .con_bmove =	DUMMY,
    4.53 +    .con_switch =	DUMMY,
    4.54 +    .con_blank =	DUMMY,
    4.55 +    .con_font_op =	DUMMY,
    4.56 +    .con_set_palette =	DUMMY,
    4.57 +    .con_scrolldelta =	DUMMY,
    4.58 +};
    4.59 +#endif
    4.60  #endif
    4.61  
    4.62  static int __init xencons_init(void)