vt_ioctl.c revision 04c71976500352d02f60616d2b960267d8c5fe24
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/char/vt_ioctl.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1992 obz under the linux copyright 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic keymap and string allocation - aeb@cwi.nl - May 1994 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some code moved for less code duplication - Andi Kleen - Mar 1997 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kd.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 2604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault#include <linux/consolemap.h> 277ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 28bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus#include <linux/timex.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38b257bc051f06607beb3004d9a1c297085e728becAndrew Johnsonchar vt_dont_switch; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct tty_driver *console_driver; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console (vt and kd) routines, as defined by USL SVR4 manual, and by 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * experimentation and study of X386 SYSV handling. 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the current console is done by the main ioctl code. 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/syscalls.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these are the valid i/o ports we're allowed to change. they map all the 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video ports 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPFIRST 0x3b4 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPLAST 0x3df 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPNUM (GPLAST - GPFIRST + 1) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define i (tmp.kb_index) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define s (tmp.kb_table) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define v (tmp.kb_value) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbentry tmp; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort *key_map, val, ov; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 83e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti if (!capable(CAP_SYS_TTY_CONFIG)) 84e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 85e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map) { 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = U(key_map[i]); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = K_HOLE; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = (i ? K_HOLE : K_NOSUCHMAP); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(val, &user_kbe->kb_value); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i && v == K_NOSUCHMAP) { 100ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate map */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s && key_map) { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = NULL; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map[0] == U(K_ALLOCATED)) { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(key_map); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count--; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KTYP(v) < NR_TYPES) { 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KVAL(v) > max_vals[KTYP(v)]) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ++Geert: non-PC keyboards may generate keycode zero */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__mc68000__) && !defined(__powerpc__) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* assignment to entry 0 only tests validity of args */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(key_map = key_maps[s])) { 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int j; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !capable(CAP_SYS_RESOURCE)) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1335cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day key_map = kmalloc(sizeof(plain_map), 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!key_map) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = key_map; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[0] = U(K_ALLOCATED); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 1; j < NR_KEYS; j++) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[j] = U(K_HOLE); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count++; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ov = U(key_map[i]); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v == ov) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* nothing to do */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attention Key. 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[i] = U(v); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT)) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef i 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef s 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef v 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbkeycode tmp; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kc = 0; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode))) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = getkeycode(tmp.scancode); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kc >= 0) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = put_user(kc, &user_kbkc->keycode); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = setkeycode(tmp.scancode, tmp.keycode); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return kc; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbsentry *kbs; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *q; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char __user *up; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sz; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int delta; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *first_free, *fj, *fnw; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, k; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1980b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton if (!capable(CAP_SYS_TTY_CONFIG)) 199e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 2000b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!kbs) { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we mostly copy too much here (512bytes), but who cares ;) */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = kbs->kb_func; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = sizeof(kbs->kb_string) - 1; /* sz should have been 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a struct member */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up = user_kdgkb->kb_string; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = func_table[i]; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for ( ; *p && sz; p++, sz--) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(*p, up++)) { 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user('\0', up)) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((p && *p) ? -EOVERFLOW : 0); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EPERM; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = func_table[i]; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first_free = funcbufptr + (funcbufsize - funcbufleft); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = func_table[j]; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = first_free; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (delta <= funcbufleft) { /* it fits in current buf */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fj + delta, fj, first_free - fj); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] += delta; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft -= delta; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* allocate a larger buffer */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = 256; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (sz < funcbufsize - funcbufleft + delta) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz <<= 1; 2635cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day fnw = kmalloc(sz, GFP_KERNEL); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!fnw) { 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fj > funcbufptr) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw, funcbufptr, fj - funcbufptr); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k < j; k++) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (first_free > fj) { 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (funcbufptr != func_buf) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(funcbufptr); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufptr = fnw; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft = funcbufleft - delta + sz - funcbufsize; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufsize = sz; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(func_table[i], kbs->kb_string); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreterr: 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct consolefontdesc cfdarg; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_SET; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, op); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: { 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_GET; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, op); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charheight = op->height; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charcount = op->charcount; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct unimapdesc tmp; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_ud, sizeof tmp)) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.entries) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, tmp.entries, 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.entry_ct*sizeof(struct unipair))) 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_unimap(vc, tmp.entry_ct, tmp.entries); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && fg_console != vc->vc_num) 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here. We allow the 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console. 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_ioctl(struct tty_struct *tty, struct file * file, 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc = (struct vc_data *)tty->driver_data; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct console_font_op op; /* used in multiple places here */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_struct * kbd; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int console; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char ucval; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *up = (void __user *)arg; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, perm; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console = vc->vc_num; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons_allocated(console)) /* impossible? */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To have permissions to do most of the vt ioctls, we either have 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 0; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 1; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd = kbd_table + console; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KIOCSOUND: 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) 396bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus arg = CLOCK_TICK_RATE / arg; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(arg, 0); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMKTONE: 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ticks, count; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generate the tone for the appropriate number of ticks. 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the time is zero, turn off sound ourselves. 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ticks = HZ * ((arg >> 16) & 0xffff) / 1000; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = ticks ? (arg & 0xffff) : 0; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count) 413bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus count = CLOCK_TICK_RATE / count; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(count, ticks); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBTYPE: 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this is naive. 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = KB_101; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These cannot be implemented on any machine that implements 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioperm() in user level (such as Alpha PCs) or not at all. 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX: you should never use these, just call ioperm directly.. 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDADDIO: 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDELIO: 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KDADDIO and KDDELIO may be able to add ports beyond what 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we reject here, but to be safe... 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg < GPFIRST || arg > GPLAST) 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDENABIO: 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDISABIO: 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sys_ioperm(GPFIRST, GPNUM, 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd == KDENABIO)) ? -ENXIO : 0; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDKBDREP: 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_repeat kbrep; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = kbd_rate(&kbrep); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETMODE: 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * currently, setting the mode from KD_TEXT to KD_GRAPHICS 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't do a whole lot. i'm not sure if it should do any 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * restoration of modes or what... 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX It should at least call into the driver, fbdev's definitely 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to restore their engine state. --BenH 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (arg) { 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_GRAPHICS: 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT0: 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT1: 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg = KD_TEXT; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT: 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == (unsigned char) arg) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = (unsigned char) arg; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (console != fg_console) 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * explicitly blank/unblank the screen if switching modes 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == KD_TEXT) 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETMODE: 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = vc->vc_mode; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMAPDISP: 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDUNMAPDISP: 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these work like a combination of mmap and KDENABIO. 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this could be easily finished. 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMODE: 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_RAW: 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_RAW; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_MEDIUMRAW: 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_MEDIUMRAW; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_XLATE: 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_XLATE; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_UNICODE: 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_UNICODE; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_ldisc_flush(tty); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMODE: 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds K_XLATE); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this could be folded into KDSKBMODE, but for compatibility 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMETA: 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_METABIT: 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clr_vc_kbd_mode(kbd, VC_META); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_ESCPREFIX: 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_vc_kbd_mode(kbd, VC_META); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMETA: 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setint: 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(ucval, (int __user *)arg); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!capable(CAP_SYS_TTY_CONFIG)) 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm=0; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_kbkeycode_ioctl(cmd, up, perm); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_kdsk_ioctl(cmd, up, perm, kbd); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_kdgkb_ioctl(cmd, up, perm); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBDIACR: 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 58604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacr diacr; 58704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault int i; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(accent_table_size, &a->kb_cnt)) 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 59104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault for (i = 0; i < accent_table_size; i++) { 59204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr); 59304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.base = conv_uni_to_8bit(accent_table[i].base); 59404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.result = conv_uni_to_8bit(accent_table[i].result); 59504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) 59604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return -EFAULT; 59704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 59804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return 0; 59904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 60004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDGKBDIACRUC: 60104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault { 60204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacrsuc __user *a = up; 60304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 60404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (put_user(accent_table_size, &a->kb_cnt)) 60504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return -EFAULT; 60604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (copy_to_user(a->kbdiacruc, accent_table, accent_table_size*sizeof(struct kbdiacruc))) 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBDIACR: 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 61404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacr diacr; 61504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault unsigned int ct; 61604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault int i; 61704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 61804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (!perm) 61904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return -EPERM; 62004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (get_user(ct,&a->kb_cnt)) 62104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return -EFAULT; 62204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (ct >= MAX_DIACR) 62304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return -EINVAL; 62404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table_size = ct; 62504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault for (i = 0; i < ct; i++) { 62604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) 62704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return -EFAULT; 62804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr); 62904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].base = conv_8bit_to_uni(diacr.base); 63004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].result = conv_8bit_to_uni(diacr.result); 63104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 63204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault return 0; 63304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 63404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 63504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDSKBDIACRUC: 63604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault { 63704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacrsuc __user *a = up; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ct; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ct,&a->kb_cnt)) 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ct >= MAX_DIACR) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds accent_table_size = ct; 64704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc))) 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below read/set the flags usually shown in the leds */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't use them - they will go away without warning */ 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBLED: 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBLED: 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg & ~0x77) 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->ledflagstate = (arg & 7); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->default_ledflagstate = ((arg >> 4) & 7); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_leds(); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below only set the lights, not the functions */ 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for those, see KDGKBLED and KDSKBLED above */ 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETLED: 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = getledstate(); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setchar: 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(ucval, (char __user *)arg); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETLED: 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setledstate(kbd, arg); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A process can indicate its willingness to accept signals 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generated by pressing an appropriate key combination. 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus, one can have a daemon that e.g. spawns a new console 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon a keypress and then changes to it. 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See also the kbrequest field of inittab(5). 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSIGACCEPT: 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm || !capable(CAP_KILL)) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6927ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 69481af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman 69581af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman spin_lock_irq(&vt_spawn_con.lock); 69681af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman put_pid(vt_spawn_con.pid); 69781af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman vt_spawn_con.pid = get_pid(task_pid(current)); 69881af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman vt_spawn_con.sig = arg; 69981af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44Eric W. Biederman spin_unlock_irq(&vt_spawn_con.lock); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_SETMODE: 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode = tmp; 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the frsig is ignored, so we set it to 0 */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 7178b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 7188b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = get_pid(task_pid(current)); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no switch is required -- saw@shade.msu.ru */ 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETMODE: 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc ? -EFAULT : 0; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns global vt state. Note that VT 0 is always open, since 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's an alias for the current VT, and people can't use it here. 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot return state for more than 16 VTs, since v_state is short. 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETSTATE: 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_stat __user *vtstat = up; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short state, mask; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(fg_console + 1, &vtstat->v_active)) 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = 1; /* /dev/tty0 is always open */ 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_IS_IN_USE(i)) 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state |= mask; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(state, &vtstat->v_state); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the first available (non-opened) console. 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_OPENQRY: 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; ++i) 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_IS_IN_USE(i)) 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with num >= 1 (switches to vt 0, our console, are not allowed, just 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to preserve sanity). 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_ACTIVATE: 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = vc_allocate(arg); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_console(arg); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait until the specified VT has been activated 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_WAITACTIVE: 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return vt_waitactive(arg-1); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a vt is under process control, the kernel will not switch to it 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * immediately, but postpone the operation until the process calls this 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl, allowing the switch to complete. 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * According to the X sources this is the behavior: 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0: pending switch-from not OK 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1: pending switch-from OK 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2: completed switch-to OK 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RELDISP: 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode != VT_PROCESS) 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switching-from response 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8158792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz acquire_console_sem(); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_newvt >= 0) { 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch disallowed, so forget we were trying 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to do it. 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The current vt has been released, so 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete the switch. 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int newvt; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newvt = vc->vt_newvt; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = vc_allocate(newvt); 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) { 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When we actually do the console switch, 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * make sure we are atomic with respect to 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other console switches.. 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(vc_cons[newvt].d); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switched-to response 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it's just an ACK, ignore it 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8548792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz if (arg != VT_ACKACQ) { 8558792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz release_console_sem(); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8578792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz } 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8598792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz release_console_sem(); 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disallocate memory associated to VT (but leave VT1) 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_DISALLOCATE: 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg > MAX_NR_CONSOLES) 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) { 870ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate all unused consoles, but leave 0 */ 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=1; i<MAX_NR_CONSOLES; i++) 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_BUSY(i)) 874ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(i); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 877ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate a single console, if possible */ 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_BUSY(arg)) 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) { /* leave 0 */ 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 883ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(arg); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZE: 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_sizes __user *vtsizes = up; 892e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas struct vc_data *vc; 893e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ll, &vtsizes->v_rows) || 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_user(cc, &vtsizes->v_cols)) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 900e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 901e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas for (i = 0; i < MAX_NR_CONSOLES; i++) { 902e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc = vc_cons[i].d; 903e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 904e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas if (vc) { 905e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc->vc_resize_user = 1; 906e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc_lock_resize(vc_cons[i].d, cc, ll); 907e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 908e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 909e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZEX: 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_consize __user *vtconsize = up; 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc,vlin,clin,vcol,ccol; 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, vtconsize, 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct vt_consize))) 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ll, &vtconsize->v_rows); 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(cc, &vtconsize->v_cols); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vlin, &vtconsize->v_vlin); 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(clin, &vtconsize->v_clin); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vcol, &vtconsize->v_vcol); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ccol, &vtconsize->v_ccol); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vlin = vlin ? vlin : vc->vc_scan_lines; 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) { 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll) { 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll != vlin/clin) 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; /* Parameters don't add up */ 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ll = vlin/clin; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcol && ccol) { 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc) { 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc != vcol/ccol) 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc = vcol/ccol; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin > 32) 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons[i].d) 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vlin) 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_scan_lines = vlin; 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_font.height = clin; 955e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc_cons[i].d->vc_resize_user = 1; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_resize(vc_cons[i].d, cc, ll); 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONT: { 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 0; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, &op); 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONT: { 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_GET; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD; 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 32; 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, &op); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_CMAP: 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_cmap(up); 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_CMAP: 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_cmap(up); 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_fontx_ioctl(cmd, up, perm, &op); 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTRESET: 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* With BROKEN_GRAPHICS_PROGRAMS defined, the default 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds font is not saved. */ 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOSYS; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET_DEFAULT; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = NULL; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, &op); 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_set_default_unimap(vc_cons[fg_console].d); 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDFONTOP: { 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&op, up, sizeof(op))) 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && op.op != KD_FONT_OP_GET) 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc, &op); 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) return i; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &op, sizeof(op))) 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_SCRNMAP: 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_trans_old(up); 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_SCRNMAP: 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_trans_old(up); 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNISCRNMAP: 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_trans_new(up); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNISCRNMAP: 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_trans_new(up); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAPCLR: 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { struct unimapinit ui; 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = copy_from_user(&ui, up, sizeof(struct unimapinit)); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) return -EFAULT; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_clear_unimap(vc, &ui); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_unimap_ioctl(cmd, up, perm, vc); 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_LOCKSWITCH: 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 1; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_UNLOCKSWITCH: 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 0; 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1070533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault case VT_GETHIFONTMASK: 1071533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg); 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sometimes we want to wait until a particular VT has been activated. We 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do it in a very simple manner. Everybody waits on a single queue and 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get woken up at once. Those that are satisfied go on with their business, 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * while those not ready go back to sleep. Seems overkill to add a wait 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to each vt just for this - usually this does nothing! 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue); 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sleeps until a vt is activated, or the task is interrupted. Returns 108870cb97935b8859f27296772885104b599f560576Linus Torvalds * 0 if activation, -EINTR if interrupted by a signal handler. 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_waitactive(int vt) 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_wait_queue(&vt_activate_queue, &wait); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 1098f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski 1099f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski /* 1100f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * Synchronize with redraw_screen(). By acquiring the console 1101f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * semaphore we make sure that the console switch is completed 1102f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * before we return. If we didn't wait for the semaphore, we 1103f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * could return at a point where fg_console has already been 1104f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * updated, but the console switch hasn't been completed. 1105f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski */ 1106f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski acquire_console_sem(); 1107f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski set_current_state(TASK_INTERRUPTIBLE); 1108f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski if (vt == fg_console) { 1109f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski release_console_sem(); 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1111f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski } 1112f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski release_console_sem(); 111370cb97935b8859f27296772885104b599f560576Linus Torvalds retval = -ERESTARTNOHAND; 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule(); 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&vt_activate_queue, &wait); 1119cc0a8fbb7ce00f65dc337dd91389b7151f44ed30Milind Arun Choudhary __set_current_state(TASK_RUNNING); 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define vt_wake_waitactive() wake_up(&vt_activate_queue) 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc) 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = KD_TEXT; 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd_table[vc->vc_num].kbdmode = VC_XLATE; 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.mode = VT_AUTO; 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.waitv = 0; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.relsig = 0; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.acqsig = 0; 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 11348b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 11358b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = NULL; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_palette(vc); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11418b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biedermanvoid vc_SAK(struct work_struct *work) 11428b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman{ 11438b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc *vc_con = 11448b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman container_of(work, struct vc, SAK_work); 11458b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc_data *vc; 11468b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct tty_struct *tty; 11478b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 11488b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman acquire_console_sem(); 11498b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc = vc_con->d; 11508b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (vc) { 11518b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman tty = vc->vc_tty; 11528b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman /* 11538b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * SAK should also work in all raw modes and reset 11548b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * them properly. 11558b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman */ 11568b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (tty) 11578b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman __do_SAK(tty); 11588b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman reset_vc(vc); 11598b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman } 11608b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman release_console_sem(); 11618b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman} 11628b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the back end of a vt switch 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc) 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char old_vc_mode; 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_console = fg_console; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're switching, we could be going from KD_GRAPHICS to 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KD_TEXT mode or vice versa, which means we need to blank or 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unblank the screen later. 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_vc_mode = vc_cons[fg_console].d->vc_mode; 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch_screen(vc); 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11813dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * This can't appear below a successful kill_pid(). If it did, 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then the *blank_screen operation could occur while X, having 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * received acqsig, is waking up on another processor. This 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * condition can lead to overlapping accesses to the VGA range 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the framebuffer (causing system lockups). 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To account for this we duplicate this code below only if the 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controlling process is gone and we've called reset_vc. 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this new console is under process control, send it a signal 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * telling it that it has acquired. Also check if it has died and 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clean up (similar to logic employed in change_console()) 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode == VT_PROCESS) { 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12043dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is awry 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1208bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wake anyone waiting for their VT to activate 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_wake_waitactive(); 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc) 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch) 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this vt is in process mode, then we need to handshake with 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that process before switching. Essentially, we store where that 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt wants to switch to and wait for it to tell us when it's done 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (via VT_RELDISP ioctl). 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We also check to see if the controlling process still exists. 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it doesn't, we reset this vt to auto mode and continue. 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a cheap way to track process control. The worst thing 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that can happen is: we send a signal to a process, it dies, and 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the switch gets "lost" waiting for a response; hopefully, the 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user will try again, we'll detect the process is gone (unless 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user waits just the right amount of time :-) and revert the 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt to auto control. 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc = vc_cons[fg_console].d; 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode == VT_PROCESS) { 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12643dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 1266a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * is awry. 1267a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * 1268a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * We need to set vt_newvt *before* sending the signal or we 1269a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * have a race. 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1271a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe vc->vt_newvt = new_vc->vc_num; 1272bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It worked. Mark the vt to switch to and 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return. The process needs to send us a 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VT_RELDISP ioctl to complete the switch. 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fall through to normal (VT_AUTO) handling of the switch... 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all switches in KD_GRAPHICS+VT_AUTO mode 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_GRAPHICS) 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(new_vc); 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1305