vserver 2.0 rc7
[linux-2.6.git] / drivers / char / vt_ioctl.c
index ad3a5d3..8971484 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/console.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -33,7 +34,7 @@
 #include <linux/kbd_diacr.h>
 #include <linux/selection.h>
 
-char vt_dont_switch;
+static char vt_dont_switch;
 extern struct tty_driver *console_driver;
 
 #define VT_IS_IN_USE(i)        (console_driver->ttys[i] && console_driver->ttys[i]->count)
@@ -52,17 +53,12 @@ extern struct tty_driver *console_driver;
  * to the current console is done by the main ioctl code.
  */
 
-struct vt_struct *vt_cons[MAX_NR_CONSOLES];
-
-/* Keyboard type: Default is KB_101, but can be set by machine
- * specific code.
- */
-unsigned char keyboard_type = KB_101;
-
 #ifdef CONFIG_X86
 #include <linux/syscalls.h>
 #endif
 
+static void complete_change_console(struct vc_data *vc);
+
 /*
  * these are the valid i/o ports we're allowed to change. they map all the
  * video ports
@@ -311,7 +307,7 @@ do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struc
                op->height = cfdarg.charheight;
                op->charcount = cfdarg.charcount;
                op->data = cfdarg.chardata;
-               return con_font_op(fg_console, op);
+               return con_font_op(vc_cons[fg_console].d, op);
        case GIO_FONTX: {
                op->op = KD_FONT_OP_GET;
                op->flags = KD_FONT_FLAG_OLD;
@@ -319,7 +315,7 @@ do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struc
                op->height = cfdarg.charheight;
                op->charcount = cfdarg.charcount;
                op->data = cfdarg.chardata;
-               i = con_font_op(fg_console, op);
+               i = con_font_op(vc_cons[fg_console].d, op);
                if (i)
                        return i;
                cfdarg.charheight = op->height;
@@ -333,27 +329,25 @@ do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struc
 }
 
 static inline int 
-do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, unsigned int console)
+do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
 {
        struct unimapdesc tmp;
-       int i = 0; 
 
        if (copy_from_user(&tmp, user_ud, sizeof tmp))
                return -EFAULT;
-       if (tmp.entries) {
-               i = verify_area(VERIFY_WRITE, tmp.entries, 
-                                               tmp.entry_ct*sizeof(struct unipair));
-               if (i) return i;
-       }
+       if (tmp.entries)
+               if (!access_ok(VERIFY_WRITE, tmp.entries,
+                               tmp.entry_ct*sizeof(struct unipair)))
+                       return -EFAULT;
        switch (cmd) {
        case PIO_UNIMAP:
                if (!perm)
                        return -EPERM;
-               return con_set_unimap(console, tmp.entry_ct, tmp.entries);
+               return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
        case GIO_UNIMAP:
-               if (!perm && fg_console != console)
+               if (!perm && fg_console != vc->vc_num)
                        return -EPERM;
-               return con_get_unimap(console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
+               return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
        }
        return 0;
 }
@@ -365,8 +359,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, unsigned i
 int vt_ioctl(struct tty_struct *tty, struct file * file,
             unsigned int cmd, unsigned long arg)
 {
-       struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
-       struct vc_data *vc = vc_cons[vt->vc_num].d;
+       struct vc_data *vc = (struct vc_data *)tty->driver_data;
        struct console_font_op op;      /* used in multiple places here */
        struct kbd_struct * kbd;
        unsigned int console;
@@ -374,7 +367,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        void __user *up = (void __user *)arg;
        int i, perm;
        
-       console = vt->vc_num;
+       console = vc->vc_num;
 
        if (!vc_cons_allocated(console))        /* impossible? */
                return -ENOIOCTLCMD;
@@ -419,7 +412,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                /*
                 * this is naive.
                 */
-               ucval = keyboard_type;
+               ucval = KB_101;
                goto setchar;
 
                /*
@@ -487,9 +480,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                default:
                        return -EINVAL;
                }
-               if (vt_cons[console]->vc_mode == (unsigned char) arg)
+               if (vc->vc_mode == (unsigned char) arg)
                        return 0;
-               vt_cons[console]->vc_mode = (unsigned char) arg;
+               vc->vc_mode = (unsigned char) arg;
                if (console != fg_console)
                        return 0;
                /*
@@ -504,7 +497,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                return 0;
 
        case KDGETMODE:
-               ucval = vt_cons[console]->vc_mode;
+               ucval = vc->vc_mode;
                goto setint;
 
        case KDMAPDISP:
@@ -649,7 +642,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                extern int spawnpid, spawnsig;
                if (!perm || !capable(CAP_KILL))
                  return -EPERM;
-               if (arg < 1 || arg > _NSIG || arg == SIGKILL)
+               if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
                  return -EINVAL;
                spawnpid = current->pid;
                spawnsig = arg;
@@ -667,12 +660,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
                        return -EINVAL;
                acquire_console_sem();
-               vt_cons[console]->vt_mode = tmp;
+               vc->vt_mode = tmp;
                /* the frsig is ignored, so we set it to 0 */
-               vt_cons[console]->vt_mode.frsig = 0;
-               vt_cons[console]->vt_pid = current->pid;
+               vc->vt_mode.frsig = 0;
+               vc->vt_pid = current->pid;
                /* no switch is required -- saw@shade.msu.ru */
-               vt_cons[console]->vt_newvt = -1; 
+               vc->vt_newvt = -1;
                release_console_sem();
                return 0;
        }
@@ -683,7 +676,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                int rc;
 
                acquire_console_sem();
-               memcpy(&tmp, &vt_cons[console]->vt_mode, sizeof(struct vt_mode));
+               memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
                release_console_sem();
 
                rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
@@ -761,31 +754,29 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        case VT_RELDISP:
                if (!perm)
                        return -EPERM;
-               if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
+               if (vc->vt_mode.mode != VT_PROCESS)
                        return -EINVAL;
 
                /*
                 * Switching-from response
                 */
-               if (vt_cons[console]->vt_newvt >= 0)
-               {
+               if (vc->vt_newvt >= 0) {
                        if (arg == 0)
                                /*
                                 * Switch disallowed, so forget we were trying
                                 * to do it.
                                 */
-                               vt_cons[console]->vt_newvt = -1;
+                               vc->vt_newvt = -1;
 
-                       else
-                       {
+                       else {
                                /*
                                 * The current vt has been released, so
                                 * complete the switch.
                                 */
                                int newvt;
                                acquire_console_sem();
-                               newvt = vt_cons[console]->vt_newvt;
-                               vt_cons[console]->vt_newvt = -1;
+                               newvt = vc->vt_newvt;
+                               vc->vt_newvt = -1;
                                i = vc_allocate(newvt);
                                if (i) {
                                        release_console_sem();
@@ -796,7 +787,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                 * make sure we are atomic with respect to
                                 * other console switches..
                                 */
-                               complete_change_console(newvt);
+                               complete_change_console(vc_cons[newvt].d);
                                release_console_sem();
                        }
                }
@@ -852,7 +843,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        return -EFAULT;
                for (i = 0; i < MAX_NR_CONSOLES; i++) {
                        acquire_console_sem();
-                        vc_resize(i, cc, ll);
+                       vc_resize(vc_cons[i].d, cc, ll);
                        release_console_sem();
                }
                return 0;
@@ -864,7 +855,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                ushort ll,cc,vlin,clin,vcol,ccol;
                if (!perm)
                        return -EPERM;
-               if (verify_area(VERIFY_READ, vtconsize,
+               if (!access_ok(VERIFY_READ, vtconsize,
                                sizeof(struct vt_consize)))
                        return -EFAULT;
                __get_user(ll, &vtconsize->v_rows);
@@ -900,7 +891,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                vc_cons[i].d->vc_scan_lines = vlin;
                        if (clin)
                                vc_cons[i].d->vc_font.height = clin;
-                       vc_resize(i, cc, ll);
+                       vc_resize(vc_cons[i].d, cc, ll);
                        release_console_sem();
                }
                return 0;
@@ -915,7 +906,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                op.height = 0;
                op.charcount = 256;
                op.data = up;
-               return con_font_op(fg_console, &op);
+               return con_font_op(vc_cons[fg_console].d, &op);
        }
 
        case GIO_FONT: {
@@ -925,7 +916,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                op.height = 32;
                op.charcount = 256;
                op.data = up;
-               return con_font_op(fg_console, &op);
+               return con_font_op(vc_cons[fg_console].d, &op);
        }
 
        case PIO_CMAP:
@@ -953,9 +944,10 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                {
                op.op = KD_FONT_OP_SET_DEFAULT;
                op.data = NULL;
-               i = con_font_op(fg_console, &op);
-               if (i) return i;
-               con_set_default_unimap(fg_console);
+               i = con_font_op(vc_cons[fg_console].d, &op);
+               if (i)
+                       return i;
+               con_set_default_unimap(vc_cons[fg_console].d);
                return 0;
                }
 #endif
@@ -966,7 +958,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        return -EFAULT;
                if (!perm && op.op != KD_FONT_OP_GET)
                        return -EPERM;
-               i = con_font_op(console, &op);
+               i = con_font_op(vc, &op);
                if (i) return i;
                if (copy_to_user(up, &op, sizeof(op)))
                        return -EFAULT;
@@ -995,13 +987,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        return -EPERM;
                i = copy_from_user(&ui, up, sizeof(struct unimapinit));
                if (i) return -EFAULT;
-               con_clear_unimap(console, &ui);
+               con_clear_unimap(vc, &ui);
                return 0;
              }
 
        case PIO_UNIMAP:
        case GIO_UNIMAP:
-               return do_unimap_ioctl(cmd, up, perm, console);
+               return do_unimap_ioctl(cmd, up, perm, vc);
 
        case VT_LOCKSWITCH:
                if (!capable(CAP_SYS_TTY_CONFIG))
@@ -1054,25 +1046,25 @@ int vt_waitactive(int vt)
 
 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
 
-void reset_vc(unsigned int new_console)
+void reset_vc(struct vc_data *vc)
 {
-       vt_cons[new_console]->vc_mode = KD_TEXT;
-       kbd_table[new_console].kbdmode = VC_XLATE;
-       vt_cons[new_console]->vt_mode.mode = VT_AUTO;
-       vt_cons[new_console]->vt_mode.waitv = 0;
-       vt_cons[new_console]->vt_mode.relsig = 0;
-       vt_cons[new_console]->vt_mode.acqsig = 0;
-       vt_cons[new_console]->vt_mode.frsig = 0;
-       vt_cons[new_console]->vt_pid = -1;
-       vt_cons[new_console]->vt_newvt = -1;
+       vc->vc_mode = KD_TEXT;
+       kbd_table[vc->vc_num].kbdmode = VC_XLATE;
+       vc->vt_mode.mode = VT_AUTO;
+       vc->vt_mode.waitv = 0;
+       vc->vt_mode.relsig = 0;
+       vc->vt_mode.acqsig = 0;
+       vc->vt_mode.frsig = 0;
+       vc->vt_pid = -1;
+       vc->vt_newvt = -1;
        if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
-               reset_palette(new_console) ;
+               reset_palette(vc);
 }
 
 /*
  * Performs the back end of a vt switch
  */
-void complete_change_console(unsigned int new_console)
+static void complete_change_console(struct vc_data *vc)
 {
        unsigned char old_vc_mode;
 
@@ -1083,8 +1075,8 @@ void complete_change_console(unsigned int new_console)
         * KD_TEXT mode or vice versa, which means we need to blank or
         * unblank the screen later.
         */
-       old_vc_mode = vt_cons[fg_console]->vc_mode;
-       switch_screen(new_console);
+       old_vc_mode = vc_cons[fg_console].d->vc_mode;
+       switch_screen(vc);
 
        /*
         * This can't appear below a successful kill_proc().  If it did,
@@ -1096,9 +1088,8 @@ void complete_change_console(unsigned int new_console)
         * To account for this we duplicate this code below only if the
         * controlling process is gone and we've called reset_vc.
         */
-       if (old_vc_mode != vt_cons[new_console]->vc_mode)
-       {
-               if (vt_cons[new_console]->vc_mode == KD_TEXT)
+       if (old_vc_mode != vc->vc_mode) {
+               if (vc->vc_mode == KD_TEXT)
                        do_unblank_screen(1);
                else
                        do_blank_screen(1);
@@ -1109,17 +1100,13 @@ void complete_change_console(unsigned int new_console)
         * telling it that it has acquired. Also check if it has died and
         * clean up (similar to logic employed in change_console())
         */
-       if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
-       {
+       if (vc->vt_mode.mode == VT_PROCESS) {
                /*
                 * Send the signal as privileged - kill_proc() will
                 * tell us if the process has gone or something else
                 * is awry
                 */
-               if (kill_proc(vt_cons[new_console]->vt_pid,
-                             vt_cons[new_console]->vt_mode.acqsig,
-                             1) != 0)
-               {
+               if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
                /*
                 * The controlling process has died, so we revert back to
                 * normal operation. In this case, we'll also change back
@@ -1129,11 +1116,10 @@ void complete_change_console(unsigned int new_console)
                 * this outside of VT_PROCESS but there is no single process
                 * to account for and tracking tty count may be undesirable.
                 */
-                       reset_vc(new_console);
+                       reset_vc(vc);
 
-                       if (old_vc_mode != vt_cons[new_console]->vc_mode)
-                       {
-                               if (vt_cons[new_console]->vc_mode == KD_TEXT)
+                       if (old_vc_mode != vc->vc_mode) {
+                               if (vc->vc_mode == KD_TEXT)
                                        do_unblank_screen(1);
                                else
                                        do_blank_screen(1);
@@ -1151,11 +1137,11 @@ void complete_change_console(unsigned int new_console)
 /*
  * Performs the front-end of a vt switch
  */
-void change_console(unsigned int new_console)
+void change_console(struct vc_data *new_vc)
 {
-        if ((new_console == fg_console) || (vt_dont_switch))
-                return;
-        if (!vc_cons_allocated(new_console))
+       struct vc_data *vc;
+
+       if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
                return;
 
        /*
@@ -1173,23 +1159,20 @@ void change_console(unsigned int new_console)
         * the user waits just the right amount of time :-) and revert the
         * vt to auto control.
         */
-       if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
-       {
+       vc = vc_cons[fg_console].d;
+       if (vc->vt_mode.mode == VT_PROCESS) {
                /*
                 * Send the signal as privileged - kill_proc() will
                 * tell us if the process has gone or something else
                 * is awry
                 */
-               if (kill_proc(vt_cons[fg_console]->vt_pid,
-                             vt_cons[fg_console]->vt_mode.relsig,
-                             1) == 0)
-               {
+               if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
                        /*
                         * It worked. Mark the vt to switch to and
                         * return. The process needs to send us a
                         * VT_RELDISP ioctl to complete the switch.
                         */
-                       vt_cons[fg_console]->vt_newvt = new_console;
+                       vc->vt_newvt = new_vc->vc_num;
                        return;
                }
 
@@ -1202,7 +1185,7 @@ void change_console(unsigned int new_console)
                 * this outside of VT_PROCESS but there is no single process
                 * to account for and tracking tty count may be undesirable.
                 */
-               reset_vc(fg_console);
+               reset_vc(vc);
 
                /*
                 * Fall through to normal (VT_AUTO) handling of the switch...
@@ -1212,8 +1195,8 @@ void change_console(unsigned int new_console)
        /*
         * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
         */
-       if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+       if (vc->vc_mode == KD_GRAPHICS)
                return;
 
-       complete_change_console(new_console);
+       complete_change_console(new_vc);
 }