git.y1.nz

fbui

Framebuffer-based graphical environment
download: https://git.y1.nz/archives/fbui.tar.gz
README | Files | Log | Refs

drivers/char/vt_ioctl.c

      1 /*
      2  *  linux/drivers/char/vt_ioctl.c
      3  *
      4  *  Copyright (C) 1992 obz under the linux copyright
      5  *
      6  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
      7  *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
      8  *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
      9  *  Some code moved for less code duplication - Andi Kleen - Mar 1997
     10  *  Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001
     11  */
     12 
     13 #include <linux/config.h>
     14 #include <linux/types.h>
     15 #include <linux/errno.h>
     16 #include <linux/sched.h>
     17 #include <linux/tty.h>
     18 #include <linux/timer.h>
     19 #include <linux/kernel.h>
     20 #include <linux/kd.h>
     21 #include <linux/vt.h>
     22 #include <linux/string.h>
     23 #include <linux/slab.h>
     24 #include <linux/major.h>
     25 #include <linux/fs.h>
     26 #include <linux/console.h>
     27 
     28 #include <asm/io.h>
     29 #include <asm/uaccess.h>
     30 
     31 #include <linux/kbd_kern.h>
     32 #include <linux/vt_kern.h>
     33 #include <linux/kbd_diacr.h>
     34 #include <linux/selection.h>
     35 
     36 char vt_dont_switch;
     37 extern struct tty_driver *console_driver;
     38 
     39 #define VT_IS_IN_USE(i)	(console_driver->ttys[i] && console_driver->ttys[i]->count)
     40 #define VT_BUSY(i)	(VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
     41 
     42 /*
     43  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
     44  * experimentation and study of X386 SYSV handling.
     45  *
     46  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
     47  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
     48  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
     49  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
     50  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
     51  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
     52  * to the current console is done by the main ioctl code.
     53  */
     54 
     55 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
     56 
     57 /* Keyboard type: Default is KB_101, but can be set by machine
     58  * specific code.
     59  */
     60 unsigned char keyboard_type = KB_101;
     61 
     62 #ifdef CONFIG_X86
     63 #include <linux/syscalls.h>
     64 #endif
     65 
     66 /*
     67  * these are the valid i/o ports we're allowed to change. they map all the
     68  * video ports
     69  */
     70 #define GPFIRST 0x3b4
     71 #define GPLAST 0x3df
     72 #define GPNUM (GPLAST - GPFIRST + 1)
     73 
     74 #define i (tmp.kb_index)
     75 #define s (tmp.kb_table)
     76 #define v (tmp.kb_value)
     77 static inline int
     78 do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd)
     79 {
     80 	struct kbentry tmp;
     81 	ushort *key_map, val, ov;
     82 
     83 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
     84 		return -EFAULT;
     85 
     86 	switch (cmd) {
     87 	case KDGKBENT:
     88 		key_map = key_maps[s];
     89 		if (key_map) {
     90 		    val = U(key_map[i]);
     91 		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
     92 			val = K_HOLE;
     93 		} else
     94 		    val = (i ? K_HOLE : K_NOSUCHMAP);
     95 		return put_user(val, &user_kbe->kb_value);
     96 	case KDSKBENT:
     97 		if (!perm)
     98 			return -EPERM;
     99 		if (!i && v == K_NOSUCHMAP) {
    100 			/* disallocate map */
    101 			key_map = key_maps[s];
    102 			if (s && key_map) {
    103 			    key_maps[s] = NULL;
    104 			    if (key_map[0] == U(K_ALLOCATED)) {
    105 					kfree(key_map);
    106 					keymap_count--;
    107 			    }
    108 			}
    109 			break;
    110 		}
    111 
    112 		if (KTYP(v) < NR_TYPES) {
    113 		    if (KVAL(v) > max_vals[KTYP(v)])
    114 				return -EINVAL;
    115 		} else
    116 		    if (kbd->kbdmode != VC_UNICODE)
    117 				return -EINVAL;
    118 
    119 		/* ++Geert: non-PC keyboards may generate keycode zero */
    120 #if !defined(__mc68000__) && !defined(__powerpc__)
    121 		/* assignment to entry 0 only tests validity of args */
    122 		if (!i)
    123 			break;
    124 #endif
    125 
    126 		if (!(key_map = key_maps[s])) {
    127 			int j;
    128 
    129 			if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
    130 			    !capable(CAP_SYS_RESOURCE))
    131 				return -EPERM;
    132 
    133 			key_map = (ushort *) kmalloc(sizeof(plain_map),
    134 						     GFP_KERNEL);
    135 			if (!key_map)
    136 				return -ENOMEM;
    137 			key_maps[s] = key_map;
    138 			key_map[0] = U(K_ALLOCATED);
    139 			for (j = 1; j < NR_KEYS; j++)
    140 				key_map[j] = U(K_HOLE);
    141 			keymap_count++;
    142 		}
    143 		ov = U(key_map[i]);
    144 		if (v == ov)
    145 			break;	/* nothing to do */
    146 		/*
    147 		 * Attention Key.
    148 		 */
    149 		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
    150 			return -EPERM;
    151 		key_map[i] = U(v);
    152 		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
    153 			compute_shiftstate();
    154 		break;
    155 	}
    156 	return 0;
    157 }
    158 #undef i
    159 #undef s
    160 #undef v
    161 
    162 static inline int 
    163 do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm)
    164 {
    165 	struct kbkeycode tmp;
    166 	int kc = 0;
    167 
    168 	if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
    169 		return -EFAULT;
    170 	switch (cmd) {
    171 	case KDGETKEYCODE:
    172 		kc = getkeycode(tmp.scancode);
    173 		if (kc >= 0)
    174 			kc = put_user(kc, &user_kbkc->keycode);
    175 		break;
    176 	case KDSETKEYCODE:
    177 		if (!perm)
    178 			return -EPERM;
    179 		kc = setkeycode(tmp.scancode, tmp.keycode);
    180 		break;
    181 	}
    182 	return kc;
    183 }
    184 
    185 static inline int
    186 do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
    187 {
    188 	struct kbsentry *kbs;
    189 	char *p;
    190 	u_char *q;
    191 	u_char __user *up;
    192 	int sz;
    193 	int delta;
    194 	char *first_free, *fj, *fnw;
    195 	int i, j, k;
    196 	int ret;
    197 
    198 	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
    199 	if (!kbs) {
    200 		ret = -ENOMEM;
    201 		goto reterr;
    202 	}
    203 
    204 	/* we mostly copy too much here (512bytes), but who cares ;) */
    205 	if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
    206 		ret = -EFAULT;
    207 		goto reterr;
    208 	}
    209 	kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
    210 	i = kbs->kb_func;
    211 
    212 	switch (cmd) {
    213 	case KDGKBSENT:
    214 		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
    215 						  a struct member */
    216 		up = user_kdgkb->kb_string;
    217 		p = func_table[i];
    218 		if(p)
    219 			for ( ; *p && sz; p++, sz--)
    220 				if (put_user(*p, up++)) {
    221 					ret = -EFAULT;
    222 					goto reterr;
    223 				}
    224 		if (put_user('\0', up)) {
    225 			ret = -EFAULT;
    226 			goto reterr;
    227 		}
    228 		kfree(kbs);
    229 		return ((p && *p) ? -EOVERFLOW : 0);
    230 	case KDSKBSENT:
    231 		if (!perm) {
    232 			ret = -EPERM;
    233 			goto reterr;
    234 		}
    235 
    236 		q = func_table[i];
    237 		first_free = funcbufptr + (funcbufsize - funcbufleft);
    238 		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 
    239 			;
    240 		if (j < MAX_NR_FUNC)
    241 			fj = func_table[j];
    242 		else
    243 			fj = first_free;
    244 
    245 		delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
    246 		if (delta <= funcbufleft) { 	/* it fits in current buf */
    247 		    if (j < MAX_NR_FUNC) {
    248 			memmove(fj + delta, fj, first_free - fj);
    249 			for (k = j; k < MAX_NR_FUNC; k++)
    250 			    if (func_table[k])
    251 				func_table[k] += delta;
    252 		    }
    253 		    if (!q)
    254 		      func_table[i] = fj;
    255 		    funcbufleft -= delta;
    256 		} else {			/* allocate a larger buffer */
    257 		    sz = 256;
    258 		    while (sz < funcbufsize - funcbufleft + delta)
    259 		      sz <<= 1;
    260 		    fnw = (char *) kmalloc(sz, GFP_KERNEL);
    261 		    if(!fnw) {
    262 		      ret = -ENOMEM;
    263 		      goto reterr;
    264 		    }
    265 
    266 		    if (!q)
    267 		      func_table[i] = fj;
    268 		    if (fj > funcbufptr)
    269 			memmove(fnw, funcbufptr, fj - funcbufptr);
    270 		    for (k = 0; k < j; k++)
    271 		      if (func_table[k])
    272 			func_table[k] = fnw + (func_table[k] - funcbufptr);
    273 
    274 		    if (first_free > fj) {
    275 			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
    276 			for (k = j; k < MAX_NR_FUNC; k++)
    277 			  if (func_table[k])
    278 			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
    279 		    }
    280 		    if (funcbufptr != func_buf)
    281 		      kfree(funcbufptr);
    282 		    funcbufptr = fnw;
    283 		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
    284 		    funcbufsize = sz;
    285 		}
    286 		strcpy(func_table[i], kbs->kb_string);
    287 		break;
    288 	}
    289 	ret = 0;
    290 reterr:
    291 	kfree(kbs);
    292 	return ret;
    293 }
    294 
    295 static inline int 
    296 do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
    297 {
    298 	struct consolefontdesc cfdarg;
    299 	int i;
    300 
    301 	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 
    302 		return -EFAULT;
    303  	
    304 	switch (cmd) {
    305 	case PIO_FONTX:
    306 		if (!perm)
    307 			return -EPERM;
    308 		op->op = KD_FONT_OP_SET;
    309 		op->flags = KD_FONT_FLAG_OLD;
    310 		op->width = 8;
    311 		op->height = cfdarg.charheight;
    312 		op->charcount = cfdarg.charcount;
    313 		op->data = cfdarg.chardata;
    314 		return con_font_op(fg_console, op);
    315 	case GIO_FONTX: {
    316 		op->op = KD_FONT_OP_GET;
    317 		op->flags = KD_FONT_FLAG_OLD;
    318 		op->width = 8;
    319 		op->height = cfdarg.charheight;
    320 		op->charcount = cfdarg.charcount;
    321 		op->data = cfdarg.chardata;
    322 		i = con_font_op(fg_console, op);
    323 		if (i)
    324 			return i;
    325 		cfdarg.charheight = op->height;
    326 		cfdarg.charcount = op->charcount;
    327 		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
    328 			return -EFAULT;
    329 		return 0;
    330 		}
    331 	}
    332 	return -EINVAL;
    333 }
    334 
    335 static inline int 
    336 do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, unsigned int console)
    337 {
    338 	struct unimapdesc tmp;
    339 	int i = 0; 
    340 
    341 	if (copy_from_user(&tmp, user_ud, sizeof tmp))
    342 		return -EFAULT;
    343 	if (tmp.entries) {
    344 		i = verify_area(VERIFY_WRITE, tmp.entries, 
    345 						tmp.entry_ct*sizeof(struct unipair));
    346 		if (i) return i;
    347 	}
    348 	switch (cmd) {
    349 	case PIO_UNIMAP:
    350 		if (!perm)
    351 			return -EPERM;
    352 		return con_set_unimap(console, tmp.entry_ct, tmp.entries);
    353 	case GIO_UNIMAP:
    354 		if (!perm && fg_console != console)
    355 			return -EPERM;
    356 		return con_get_unimap(console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
    357 	}
    358 	return 0;
    359 }
    360 
    361 /*
    362  * We handle the console-specific ioctl's here.  We allow the
    363  * capability to modify any console, not just the fg_console. 
    364  */
    365 int vt_ioctl(struct tty_struct *tty, struct file * file,
    366 	     unsigned int cmd, unsigned long arg)
    367 {
    368 	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
    369 	struct vc_data *vc = vc_cons[vt->vc_num].d;
    370 	struct console_font_op op;	/* used in multiple places here */
    371 	struct kbd_struct * kbd;
    372 	unsigned int console;
    373 	unsigned char ucval;
    374 	void __user *up = (void __user *)arg;
    375 	int i, perm;
    376 	
    377 	console = vt->vc_num;
    378 
    379 	if (!vc_cons_allocated(console)) 	/* impossible? */
    380 		return -ENOIOCTLCMD;
    381 
    382 	/*
    383 	 * To have permissions to do most of the vt ioctls, we either have
    384 	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
    385 	 */
    386 	perm = 0;
    387 	if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
    388 		perm = 1;
    389  
    390 	kbd = kbd_table + console;
    391 	switch (cmd) {
    392 	case KIOCSOUND:
    393 		if (!perm)
    394 			return -EPERM;
    395 		if (arg)
    396 			arg = 1193182 / arg;
    397 		kd_mksound(arg, 0);
    398 		return 0;
    399 
    400 	case KDMKTONE:
    401 		if (!perm)
    402 			return -EPERM;
    403 	{
    404 		unsigned int ticks, count;
    405 		
    406 		/*
    407 		 * Generate the tone for the appropriate number of ticks.
    408 		 * If the time is zero, turn off sound ourselves.
    409 		 */
    410 		ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
    411 		count = ticks ? (arg & 0xffff) : 0;
    412 		if (count)
    413 			count = 1193182 / count;
    414 		kd_mksound(count, ticks);
    415 		return 0;
    416 	}
    417 
    418 	case KDGKBTYPE:
    419 		/*
    420 		 * this is naive.
    421 		 */
    422 		ucval = keyboard_type;
    423 		goto setchar;
    424 
    425 		/*
    426 		 * These cannot be implemented on any machine that implements
    427 		 * ioperm() in user level (such as Alpha PCs) or not at all.
    428 		 *
    429 		 * XXX: you should never use these, just call ioperm directly..
    430 		 */
    431 #ifdef CONFIG_X86
    432 	case KDADDIO:
    433 	case KDDELIO:
    434 		/*
    435 		 * KDADDIO and KDDELIO may be able to add ports beyond what
    436 		 * we reject here, but to be safe...
    437 		 */
    438 		if (arg < GPFIRST || arg > GPLAST)
    439 			return -EINVAL;
    440 		return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
    441 
    442 	case KDENABIO:
    443 	case KDDISABIO:
    444 		return sys_ioperm(GPFIRST, GPNUM,
    445 				  (cmd == KDENABIO)) ? -ENXIO : 0;
    446 #endif
    447 
    448 	/* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
    449 		
    450 	case KDKBDREP:
    451 	{
    452 		struct kbd_repeat kbrep;
    453 		int err;
    454 		
    455 		if (!capable(CAP_SYS_TTY_CONFIG))
    456 			return -EPERM;
    457 
    458 		if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
    459 			return -EFAULT;
    460 		err = kbd_rate(&kbrep);
    461 		if (err)
    462 			return err;
    463 		if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
    464 			return -EFAULT;
    465 		return 0;
    466 	}
    467 
    468 	case KDSETMODE:
    469 		/*
    470 		 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
    471 		 * doesn't do a whole lot. i'm not sure if it should do any
    472 		 * restoration of modes or what...
    473 		 *
    474 		 * XXX It should at least call into the driver, fbdev's definitely
    475 		 * need to restore their engine state. --BenH
    476 		 */
    477 		if (!perm)
    478 			return -EPERM;
    479 		switch (arg) {
    480 		case KD_GRAPHICS:
    481 			break;
    482 		case KD_TEXT0:
    483 		case KD_TEXT1:
    484 			arg = KD_TEXT;
    485 		case KD_TEXT:
    486 			break;
    487 		default:
    488 			return -EINVAL;
    489 		}
    490 		if (vt_cons[console]->vc_mode == (unsigned char) arg)
    491 			return 0;
    492 		vt_cons[console]->vc_mode = (unsigned char) arg;
    493 		if (console != fg_console)
    494 			return 0;
    495 		/*
    496 		 * explicitly blank/unblank the screen if switching modes
    497 		 */
    498 		acquire_console_sem();
    499 		if (arg == KD_TEXT)
    500 			do_unblank_screen(1);
    501 		else
    502 			do_blank_screen(1);
    503 		release_console_sem();
    504 		return 0;
    505 
    506 	case KDGETMODE:
    507 		ucval = vt_cons[console]->vc_mode;
    508 		goto setint;
    509 
    510 	case KDMAPDISP:
    511 	case KDUNMAPDISP:
    512 		/*
    513 		 * these work like a combination of mmap and KDENABIO.
    514 		 * this could be easily finished.
    515 		 */
    516 		return -EINVAL;
    517 
    518 	case KDSKBMODE:
    519 		if (!perm)
    520 			return -EPERM;
    521 		switch(arg) {
    522 		  case K_RAW:
    523 			kbd->kbdmode = VC_RAW;
    524 			break;
    525 		  case K_MEDIUMRAW:
    526 			kbd->kbdmode = VC_MEDIUMRAW;
    527 			break;
    528 		  case K_XLATE:
    529 			kbd->kbdmode = VC_XLATE;
    530 			compute_shiftstate();
    531 			break;
    532 		  case K_UNICODE:
    533 			kbd->kbdmode = VC_UNICODE;
    534 			compute_shiftstate();
    535 			break;
    536 		  default:
    537 			return -EINVAL;
    538 		}
    539 		tty_ldisc_flush(tty);
    540 		return 0;
    541 
    542 	case KDGKBMODE:
    543 		ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
    544 				 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
    545 				 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
    546 				 K_XLATE);
    547 		goto setint;
    548 
    549 	/* this could be folded into KDSKBMODE, but for compatibility
    550 	   reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
    551 	case KDSKBMETA:
    552 		switch(arg) {
    553 		  case K_METABIT:
    554 			clr_vc_kbd_mode(kbd, VC_META);
    555 			break;
    556 		  case K_ESCPREFIX:
    557 			set_vc_kbd_mode(kbd, VC_META);
    558 			break;
    559 		  default:
    560 			return -EINVAL;
    561 		}
    562 		return 0;
    563 
    564 	case KDGKBMETA:
    565 		ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
    566 	setint:
    567 		return put_user(ucval, (int __user *)arg); 
    568 
    569 	case KDGETKEYCODE:
    570 	case KDSETKEYCODE:
    571 		if(!capable(CAP_SYS_TTY_CONFIG))
    572 			perm=0;
    573 		return do_kbkeycode_ioctl(cmd, up, perm);
    574 
    575 	case KDGKBENT:
    576 	case KDSKBENT:
    577 		return do_kdsk_ioctl(cmd, up, perm, kbd);
    578 
    579 	case KDGKBSENT:
    580 	case KDSKBSENT:
    581 		return do_kdgkb_ioctl(cmd, up, perm);
    582 
    583 	case KDGKBDIACR:
    584 	{
    585 		struct kbdiacrs __user *a = up;
    586 
    587 		if (put_user(accent_table_size, &a->kb_cnt))
    588 			return -EFAULT;
    589 		if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))
    590 			return -EFAULT;
    591 		return 0;
    592 	}
    593 
    594 	case KDSKBDIACR:
    595 	{
    596 		struct kbdiacrs __user *a = up;
    597 		unsigned int ct;
    598 
    599 		if (!perm)
    600 			return -EPERM;
    601 		if (get_user(ct,&a->kb_cnt))
    602 			return -EFAULT;
    603 		if (ct >= MAX_DIACR)
    604 			return -EINVAL;
    605 		accent_table_size = ct;
    606 		if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))
    607 			return -EFAULT;
    608 		return 0;
    609 	}
    610 
    611 	/* the ioctls below read/set the flags usually shown in the leds */
    612 	/* don't use them - they will go away without warning */
    613 	case KDGKBLED:
    614 		ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
    615 		goto setchar;
    616 
    617 	case KDSKBLED:
    618 		if (!perm)
    619 			return -EPERM;
    620 		if (arg & ~0x77)
    621 			return -EINVAL;
    622 		kbd->ledflagstate = (arg & 7);
    623 		kbd->default_ledflagstate = ((arg >> 4) & 7);
    624 		set_leds();
    625 		return 0;
    626 
    627 	/* the ioctls below only set the lights, not the functions */
    628 	/* for those, see KDGKBLED and KDSKBLED above */
    629 	case KDGETLED:
    630 		ucval = getledstate();
    631 	setchar:
    632 		return put_user(ucval, (char __user *)arg);
    633 
    634 	case KDSETLED:
    635 		if (!perm)
    636 		  return -EPERM;
    637 		setledstate(kbd, arg);
    638 		return 0;
    639 
    640 	/*
    641 	 * A process can indicate its willingness to accept signals
    642 	 * generated by pressing an appropriate key combination.
    643 	 * Thus, one can have a daemon that e.g. spawns a new console
    644 	 * upon a keypress and then changes to it.
    645 	 * See also the kbrequest field of inittab(5).
    646 	 */
    647 	case KDSIGACCEPT:
    648 	{
    649 		extern int spawnpid, spawnsig;
    650 		if (!perm || !capable(CAP_KILL))
    651 		  return -EPERM;
    652 		if (arg < 1 || arg > _NSIG || arg == SIGKILL)
    653 		  return -EINVAL;
    654 		spawnpid = current->pid;
    655 		spawnsig = arg;
    656 		return 0;
    657 	}
    658 
    659 	case VT_SETMODE:
    660 	{
    661 		struct vt_mode tmp;
    662 
    663 		if (!perm)
    664 			return -EPERM;
    665 		if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
    666 			return -EFAULT;
    667 		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
    668 			return -EINVAL;
    669 		acquire_console_sem();
    670 		vt_cons[console]->vt_mode = tmp;
    671 		/* the frsig is ignored, so we set it to 0 */
    672 		vt_cons[console]->vt_mode.frsig = 0;
    673 		vt_cons[console]->vt_pid = current->pid;
    674 		/* no switch is required -- saw@shade.msu.ru */
    675 		vt_cons[console]->vt_newvt = -1; 
    676 		release_console_sem();
    677 		return 0;
    678 	}
    679 
    680 	case VT_GETMODE:
    681 	{
    682 		struct vt_mode tmp;
    683 		int rc;
    684 
    685 		acquire_console_sem();
    686 		memcpy(&tmp, &vt_cons[console]->vt_mode, sizeof(struct vt_mode));
    687 		release_console_sem();
    688 
    689 		rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
    690 		return rc ? -EFAULT : 0;
    691 	}
    692 
    693 	/*
    694 	 * Returns global vt state. Note that VT 0 is always open, since
    695 	 * it's an alias for the current VT, and people can't use it here.
    696 	 * We cannot return state for more than 16 VTs, since v_state is short.
    697 	 */
    698 	case VT_GETSTATE:
    699 	{
    700 		struct vt_stat __user *vtstat = up;
    701 		unsigned short state, mask;
    702 
    703 		if (put_user(fg_console + 1, &vtstat->v_active))
    704 			return -EFAULT;
    705 		state = 1;	/* /dev/tty0 is always open */
    706 		for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
    707 			if (VT_IS_IN_USE(i))
    708 				state |= mask;
    709 		return put_user(state, &vtstat->v_state);
    710 	}
    711 
    712 	/*
    713 	 * Returns the first available (non-opened) console.
    714 	 */
    715 	case VT_OPENQRY:
    716 		for (i = 0; i < MAX_NR_CONSOLES; ++i)
    717 			if (! VT_IS_IN_USE(i))
    718 				break;
    719 		ucval = i < MAX_NR_CONSOLES ? (i+1) : -1;
    720 		goto setint;		 
    721 
    722 	/*
    723 	 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
    724 	 * with num >= 1 (switches to vt 0, our console, are not allowed, just
    725 	 * to preserve sanity).
    726 	 */
    727 	case VT_ACTIVATE:
    728 		if (!perm)
    729 			return -EPERM;
    730 		if (arg == 0 || arg > MAX_NR_CONSOLES)
    731 			return -ENXIO;
    732 		arg--;
    733 		acquire_console_sem();
    734 		i = vc_allocate(arg);
    735 		release_console_sem();
    736 		if (i)
    737 			return i;
    738 		set_console(arg);
    739 		return 0;
    740 
    741 	/*
    742 	 * wait until the specified VT has been activated
    743 	 */
    744 	case VT_WAITACTIVE:
    745 		if (!perm)
    746 			return -EPERM;
    747 		if (arg == 0 || arg > MAX_NR_CONSOLES)
    748 			return -ENXIO;
    749 		return vt_waitactive(arg-1);
    750 
    751 	/*
    752 	 * If a vt is under process control, the kernel will not switch to it
    753 	 * immediately, but postpone the operation until the process calls this
    754 	 * ioctl, allowing the switch to complete.
    755 	 *
    756 	 * According to the X sources this is the behavior:
    757 	 *	0:	pending switch-from not OK
    758 	 *	1:	pending switch-from OK
    759 	 *	2:	completed switch-to OK
    760 	 */
    761 	case VT_RELDISP:
    762 		if (!perm)
    763 			return -EPERM;
    764 		if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
    765 			return -EINVAL;
    766 
    767 		/*
    768 		 * Switching-from response
    769 		 */
    770 		if (vt_cons[console]->vt_newvt >= 0)
    771 		{
    772 			if (arg == 0)
    773 				/*
    774 				 * Switch disallowed, so forget we were trying
    775 				 * to do it.
    776 				 */
    777 				vt_cons[console]->vt_newvt = -1;
    778 
    779 			else
    780 			{
    781 				/*
    782 				 * The current vt has been released, so
    783 				 * complete the switch.
    784 				 */
    785 				int newvt;
    786 				acquire_console_sem();
    787 				newvt = vt_cons[console]->vt_newvt;
    788 				vt_cons[console]->vt_newvt = -1;
    789 				i = vc_allocate(newvt);
    790 				if (i) {
    791 					release_console_sem();
    792 					return i;
    793 				}
    794 				/*
    795 				 * When we actually do the console switch,
    796 				 * make sure we are atomic with respect to
    797 				 * other console switches..
    798 				 */
    799 				complete_change_console(newvt);
    800 				release_console_sem();
    801 			}
    802 		}
    803 
    804 		/*
    805 		 * Switched-to response
    806 		 */
    807 		else
    808 		{
    809 			/*
    810 			 * If it's just an ACK, ignore it
    811 			 */
    812 			if (arg != VT_ACKACQ)
    813 				return -EINVAL;
    814 		}
    815 
    816 		return 0;
    817 
    818 	 /*
    819 	  * Disallocate memory associated to VT (but leave VT1)
    820 	  */
    821 	 case VT_DISALLOCATE:
    822 		if (arg > MAX_NR_CONSOLES)
    823 			return -ENXIO;
    824 		if (arg == 0) {
    825 		    /* disallocate all unused consoles, but leave 0 */
    826 			acquire_console_sem();
    827 			for (i=1; i<MAX_NR_CONSOLES; i++)
    828 				if (! VT_BUSY(i))
    829 					vc_disallocate(i);
    830 			release_console_sem();
    831 		} else {
    832 			/* disallocate a single console, if possible */
    833 			arg--;
    834 			if (VT_BUSY(arg))
    835 				return -EBUSY;
    836 			if (arg) {			      /* leave 0 */
    837 				acquire_console_sem();
    838 				vc_disallocate(arg);
    839 				release_console_sem();
    840 			}
    841 		}
    842 		return 0;
    843 
    844 	case VT_RESIZE:
    845 	{
    846 		struct vt_sizes __user *vtsizes = up;
    847 		ushort ll,cc;
    848 		if (!perm)
    849 			return -EPERM;
    850 		if (get_user(ll, &vtsizes->v_rows) ||
    851 		    get_user(cc, &vtsizes->v_cols))
    852 			return -EFAULT;
    853 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
    854 			acquire_console_sem();
    855                         vc_resize(i, cc, ll);
    856 			release_console_sem();
    857 		}
    858 		return 0;
    859 	}
    860 
    861 	case VT_RESIZEX:
    862 	{
    863 		struct vt_consize __user *vtconsize = up;
    864 		ushort ll,cc,vlin,clin,vcol,ccol;
    865 		if (!perm)
    866 			return -EPERM;
    867 		if (verify_area(VERIFY_READ, vtconsize,
    868 				sizeof(struct vt_consize)))
    869 			return -EFAULT;
    870 		__get_user(ll, &vtconsize->v_rows);
    871 		__get_user(cc, &vtconsize->v_cols);
    872 		__get_user(vlin, &vtconsize->v_vlin);
    873 		__get_user(clin, &vtconsize->v_clin);
    874 		__get_user(vcol, &vtconsize->v_vcol);
    875 		__get_user(ccol, &vtconsize->v_ccol);
    876 		vlin = vlin ? vlin : vc->vc_scan_lines;
    877 		if (clin) {
    878 			if (ll) {
    879 				if (ll != vlin/clin)
    880 					return -EINVAL; /* Parameters don't add up */
    881 			} else 
    882 				ll = vlin/clin;
    883 		}
    884 		if (vcol && ccol) {
    885 			if (cc) {
    886 				if (cc != vcol/ccol)
    887 					return -EINVAL;
    888 			} else
    889 				cc = vcol/ccol;
    890 		}
    891 
    892 		if (clin > 32)
    893 			return -EINVAL;
    894 		    
    895 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
    896 			if (!vc_cons[i].d)
    897 				continue;
    898 			acquire_console_sem();
    899 			if (vlin)
    900 				vc_cons[i].d->vc_scan_lines = vlin;
    901 			if (clin)
    902 				vc_cons[i].d->vc_font.height = clin;
    903 			vc_resize(i, cc, ll);
    904 			release_console_sem();
    905 		}
    906   		return 0;
    907 	}
    908 
    909 	case PIO_FONT: {
    910 		if (!perm)
    911 			return -EPERM;
    912 		op.op = KD_FONT_OP_SET;
    913 		op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC;	/* Compatibility */
    914 		op.width = 8;
    915 		op.height = 0;
    916 		op.charcount = 256;
    917 		op.data = up;
    918 		return con_font_op(fg_console, &op);
    919 	}
    920 
    921 	case GIO_FONT: {
    922 		op.op = KD_FONT_OP_GET;
    923 		op.flags = KD_FONT_FLAG_OLD;
    924 		op.width = 8;
    925 		op.height = 32;
    926 		op.charcount = 256;
    927 		op.data = up;
    928 		return con_font_op(fg_console, &op);
    929 	}
    930 
    931 	case PIO_CMAP:
    932                 if (!perm)
    933 			return -EPERM;
    934                 return con_set_cmap(up);
    935 
    936 	case GIO_CMAP:
    937                 return con_get_cmap(up);
    938 
    939 	case PIO_FONTX:
    940 	case GIO_FONTX:
    941 		return do_fontx_ioctl(cmd, up, perm, &op);
    942 
    943 	case PIO_FONTRESET:
    944 	{
    945 		if (!perm)
    946 			return -EPERM;
    947 
    948 #ifdef BROKEN_GRAPHICS_PROGRAMS
    949 		/* With BROKEN_GRAPHICS_PROGRAMS defined, the default
    950 		   font is not saved. */
    951 		return -ENOSYS;
    952 #else
    953 		{
    954 		op.op = KD_FONT_OP_SET_DEFAULT;
    955 		op.data = NULL;
    956 		i = con_font_op(fg_console, &op);
    957 		if (i) return i;
    958 		con_set_default_unimap(fg_console);
    959 		return 0;
    960 		}
    961 #endif
    962 	}
    963 
    964 	case KDFONTOP: {
    965 		if (copy_from_user(&op, up, sizeof(op)))
    966 			return -EFAULT;
    967 		if (!perm && op.op != KD_FONT_OP_GET)
    968 			return -EPERM;
    969 		i = con_font_op(console, &op);
    970 		if (i) return i;
    971 		if (copy_to_user(up, &op, sizeof(op)))
    972 			return -EFAULT;
    973 		return 0;
    974 	}
    975 
    976 	case PIO_SCRNMAP:
    977 		if (!perm)
    978 			return -EPERM;
    979 		return con_set_trans_old(up);
    980 
    981 	case GIO_SCRNMAP:
    982 		return con_get_trans_old(up);
    983 
    984 	case PIO_UNISCRNMAP:
    985 		if (!perm)
    986 			return -EPERM;
    987 		return con_set_trans_new(up);
    988 
    989 	case GIO_UNISCRNMAP:
    990 		return con_get_trans_new(up);
    991 
    992 	case PIO_UNIMAPCLR:
    993 	      { struct unimapinit ui;
    994 		if (!perm)
    995 			return -EPERM;
    996 		i = copy_from_user(&ui, up, sizeof(struct unimapinit));
    997 		if (i) return -EFAULT;
    998 		con_clear_unimap(console, &ui);
    999 		return 0;
   1000 	      }
   1001 
   1002 	case PIO_UNIMAP:
   1003 	case GIO_UNIMAP:
   1004 		return do_unimap_ioctl(cmd, up, perm, console);
   1005 
   1006 	case VT_LOCKSWITCH:
   1007 		if (!capable(CAP_SYS_TTY_CONFIG))
   1008 		   return -EPERM;
   1009 		vt_dont_switch = 1;
   1010 		return 0;
   1011 	case VT_UNLOCKSWITCH:
   1012 		if (!capable(CAP_SYS_TTY_CONFIG))
   1013 		   return -EPERM;
   1014 		vt_dont_switch = 0;
   1015 		return 0;
   1016 	default:
   1017 		return -ENOIOCTLCMD;
   1018 	}
   1019 }
   1020 
   1021 /*
   1022  * Sometimes we want to wait until a particular VT has been activated. We
   1023  * do it in a very simple manner. Everybody waits on a single queue and
   1024  * get woken up at once. Those that are satisfied go on with their business,
   1025  * while those not ready go back to sleep. Seems overkill to add a wait
   1026  * to each vt just for this - usually this does nothing!
   1027  */
   1028 static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
   1029 
   1030 /*
   1031  * Sleeps until a vt is activated, or the task is interrupted. Returns
   1032  * 0 if activation, -EINTR if interrupted.
   1033  */
   1034 int vt_waitactive(int vt)
   1035 {
   1036 	int retval;
   1037 	DECLARE_WAITQUEUE(wait, current);
   1038 
   1039 	add_wait_queue(&vt_activate_queue, &wait);
   1040 	for (;;) {
   1041 		set_current_state(TASK_INTERRUPTIBLE);
   1042 		retval = 0;
   1043 		if (vt == fg_console)
   1044 			break;
   1045 		retval = -EINTR;
   1046 		if (signal_pending(current))
   1047 			break;
   1048 		schedule();
   1049 	}
   1050 	remove_wait_queue(&vt_activate_queue, &wait);
   1051 	current->state = TASK_RUNNING;
   1052 	return retval;
   1053 }
   1054 
   1055 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
   1056 
   1057 void reset_vc(unsigned int new_console)
   1058 {
   1059 	vt_cons[new_console]->vc_mode = KD_TEXT;
   1060 	kbd_table[new_console].kbdmode = VC_XLATE;
   1061 	vt_cons[new_console]->vt_mode.mode = VT_AUTO;
   1062 	vt_cons[new_console]->vt_mode.waitv = 0;
   1063 	vt_cons[new_console]->vt_mode.relsig = 0;
   1064 	vt_cons[new_console]->vt_mode.acqsig = 0;
   1065 	vt_cons[new_console]->vt_mode.frsig = 0;
   1066 	vt_cons[new_console]->vt_pid = -1;
   1067 	vt_cons[new_console]->vt_newvt = -1;
   1068 	if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
   1069 		reset_palette(new_console) ;
   1070 }
   1071 
   1072 /*
   1073  * Performs the back end of a vt switch
   1074  */
   1075 void complete_change_console(unsigned int new_console)
   1076 {
   1077 	unsigned char old_vc_mode;
   1078 
   1079 	last_console = fg_console;
   1080 
   1081 	/*
   1082 	 * If we're switching, we could be going from KD_GRAPHICS to
   1083 	 * KD_TEXT mode or vice versa, which means we need to blank or
   1084 	 * unblank the screen later.
   1085 	 */
   1086 	old_vc_mode = vt_cons[fg_console]->vc_mode;
   1087 	switch_screen(new_console);
   1088 
   1089 	/*
   1090 	 * This can't appear below a successful kill_proc().  If it did,
   1091 	 * then the *blank_screen operation could occur while X, having
   1092 	 * received acqsig, is waking up on another processor.  This
   1093 	 * condition can lead to overlapping accesses to the VGA range
   1094 	 * and the framebuffer (causing system lockups).
   1095 	 *
   1096 	 * To account for this we duplicate this code below only if the
   1097 	 * controlling process is gone and we've called reset_vc.
   1098 	 */
   1099 	if (old_vc_mode != vt_cons[new_console]->vc_mode)
   1100 	{
   1101 		if (vt_cons[new_console]->vc_mode == KD_TEXT)
   1102 			do_unblank_screen(1);
   1103 		else
   1104 			do_blank_screen(1);
   1105 	}
   1106 
   1107 	/*
   1108 	 * If this new console is under process control, send it a signal
   1109 	 * telling it that it has acquired. Also check if it has died and
   1110 	 * clean up (similar to logic employed in change_console())
   1111 	 */
   1112 	if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
   1113 	{
   1114 		/*
   1115 		 * Send the signal as privileged - kill_proc() will
   1116 		 * tell us if the process has gone or something else
   1117 		 * is awry
   1118 		 */
   1119 		if (kill_proc(vt_cons[new_console]->vt_pid,
   1120 			      vt_cons[new_console]->vt_mode.acqsig,
   1121 			      1) != 0)
   1122 		{
   1123 		/*
   1124 		 * The controlling process has died, so we revert back to
   1125 		 * normal operation. In this case, we'll also change back
   1126 		 * to KD_TEXT mode. I'm not sure if this is strictly correct
   1127 		 * but it saves the agony when the X server dies and the screen
   1128 		 * remains blanked due to KD_GRAPHICS! It would be nice to do
   1129 		 * this outside of VT_PROCESS but there is no single process
   1130 		 * to account for and tracking tty count may be undesirable.
   1131 		 */
   1132 		        reset_vc(new_console);
   1133 
   1134 			if (old_vc_mode != vt_cons[new_console]->vc_mode)
   1135 			{
   1136 				if (vt_cons[new_console]->vc_mode == KD_TEXT)
   1137 					do_unblank_screen(1);
   1138 				else
   1139 					do_blank_screen(1);
   1140 			}
   1141 		}
   1142 	}
   1143 
   1144 	/*
   1145 	 * Wake anyone waiting for their VT to activate
   1146 	 */
   1147 	vt_wake_waitactive();
   1148 	return;
   1149 }
   1150 
   1151 /*
   1152  * Performs the front-end of a vt switch
   1153  */
   1154 void change_console(unsigned int new_console)
   1155 {
   1156         if ((new_console == fg_console) || (vt_dont_switch))
   1157                 return;
   1158         if (!vc_cons_allocated(new_console))
   1159 		return;
   1160 
   1161 	/*
   1162 	 * If this vt is in process mode, then we need to handshake with
   1163 	 * that process before switching. Essentially, we store where that
   1164 	 * vt wants to switch to and wait for it to tell us when it's done
   1165 	 * (via VT_RELDISP ioctl).
   1166 	 *
   1167 	 * We also check to see if the controlling process still exists.
   1168 	 * If it doesn't, we reset this vt to auto mode and continue.
   1169 	 * This is a cheap way to track process control. The worst thing
   1170 	 * that can happen is: we send a signal to a process, it dies, and
   1171 	 * the switch gets "lost" waiting for a response; hopefully, the
   1172 	 * user will try again, we'll detect the process is gone (unless
   1173 	 * the user waits just the right amount of time :-) and revert the
   1174 	 * vt to auto control.
   1175 	 */
   1176 	if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
   1177 	{
   1178 		/*
   1179 		 * Send the signal as privileged - kill_proc() will
   1180 		 * tell us if the process has gone or something else
   1181 		 * is awry
   1182 		 */
   1183 		if (kill_proc(vt_cons[fg_console]->vt_pid,
   1184 			      vt_cons[fg_console]->vt_mode.relsig,
   1185 			      1) == 0)
   1186 		{
   1187 			/*
   1188 			 * It worked. Mark the vt to switch to and
   1189 			 * return. The process needs to send us a
   1190 			 * VT_RELDISP ioctl to complete the switch.
   1191 			 */
   1192 			vt_cons[fg_console]->vt_newvt = new_console;
   1193 			return;
   1194 		}
   1195 
   1196 		/*
   1197 		 * The controlling process has died, so we revert back to
   1198 		 * normal operation. In this case, we'll also change back
   1199 		 * to KD_TEXT mode. I'm not sure if this is strictly correct
   1200 		 * but it saves the agony when the X server dies and the screen
   1201 		 * remains blanked due to KD_GRAPHICS! It would be nice to do
   1202 		 * this outside of VT_PROCESS but there is no single process
   1203 		 * to account for and tracking tty count may be undesirable.
   1204 		 */
   1205 		reset_vc(fg_console);
   1206 
   1207 		/*
   1208 		 * Fall through to normal (VT_AUTO) handling of the switch...
   1209 		 */
   1210 	}
   1211 
   1212 	/*
   1213 	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
   1214 	 */
   1215 #ifndef CONFIG_FB_UI
   1216 	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
   1217 		return;
   1218 #endif
   1219 
   1220 	complete_change_console(new_console);
   1221 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.