root/drivers/char/vt.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kd_size_changed
  2. kd_nosound
  3. kd_mksound
  4. vt_ioctl

   1 /*
   2  *  linux/drivers/char/vt.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  */
  10 
  11 #include <linux/types.h>
  12 #include <linux/errno.h>
  13 #include <linux/sched.h>
  14 #include <linux/tty.h>
  15 #include <linux/timer.h>
  16 #include <linux/kernel.h>
  17 #include <linux/kd.h>
  18 #include <linux/vt.h>
  19 #include <linux/string.h>
  20 #include <linux/malloc.h>
  21 #include <linux/major.h>
  22 #include <linux/fs.h>
  23 
  24 #include <asm/io.h>
  25 #include <asm/segment.h>
  26 
  27 #include "kbd_kern.h"
  28 #include "vt_kern.h"
  29 #include "diacr.h"
  30 #include "selection.h"
  31 
  32 extern char vt_dont_switch;
  33 extern struct tty_driver console_driver;
  34 
  35 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
  36 #define VT_BUSY(i)      (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
  37 
  38 /*
  39  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  40  * experimentation and study of X386 SYSV handling.
  41  *
  42  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  43  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  44  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
  45  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
  46  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  47  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  48  * to the current console is done by the main ioctl code.
  49  */
  50 
  51 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
  52 
  53 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
  54 
  55 extern int getkeycode(unsigned int scancode);
  56 extern int setkeycode(unsigned int scancode, unsigned int keycode);
  57 extern void compute_shiftstate(void);
  58 extern void change_console(unsigned int new_console);
  59 extern void complete_change_console(unsigned int new_console);
  60 extern int vt_waitactive(void);
  61 extern void do_blank_screen(int nopowersave);
  62 
  63 extern unsigned int keymap_count;
  64 
  65 /*
  66  * routines to load custom translation table, EGA/VGA font and
  67  * VGA colour palette from console.c
  68  */
  69 extern int con_set_trans_old(unsigned char * table);
  70 extern int con_get_trans_old(unsigned char * table);
  71 extern int con_set_trans_new(unsigned short * table);
  72 extern int con_get_trans_new(unsigned short * table);
  73 extern void con_clear_unimap(struct unimapinit *ui);
  74 extern int con_set_unimap(ushort ct, struct unipair *list);
  75 extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
  76 extern void con_set_default_unimap(void);
  77 extern int con_set_font(char * fontmap, int ch512);
  78 extern int con_get_font(char * fontmap);
  79 extern int con_set_cmap(unsigned char *cmap);
  80 extern int con_get_cmap(unsigned char *cmap);
  81 extern void reset_palette(int currcons);
  82 extern int con_adjust_height(unsigned long fontheight);
  83 
  84 extern int video_mode_512ch;
  85 extern unsigned long video_font_height;
  86 extern unsigned long default_font_height;
  87 extern unsigned long video_scan_lines;
  88 
  89 /*
  90  * these are the valid i/o ports we're allowed to change. they map all the
  91  * video ports
  92  */
  93 #define GPFIRST 0x3b4
  94 #define GPLAST 0x3df
  95 #define GPNUM (GPLAST - GPFIRST + 1)
  96 
  97 /*
  98  * This function is called when the size of the physical screen has been
  99  * changed.  If either the row or col argument is nonzero, set the appropriate
 100  * entry in each winsize structure for all the virtual consoles, then
 101  * send SIGWINCH to all processes with a virtual console as controlling
 102  * tty.
 103  */
 104 
 105 static int
 106 kd_size_changed(int row, int col)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108   struct task_struct *p;
 109   int i;
 110 
 111   if ( !row && !col ) return 0;
 112 
 113   for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ )
 114     {
 115       if ( console_driver.table[i] )
 116         {
 117           if ( row ) console_driver.table[i]->winsize.ws_row = row;
 118           if ( col ) console_driver.table[i]->winsize.ws_col = col;
 119         }
 120     }
 121 
 122   for_each_task(p)
 123     {
 124       if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR &&
 125            MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) )
 126         {
 127           send_sig(SIGWINCH, p, 1);
 128         }
 129     }
 130 
 131   return 0;
 132 }
 133 
 134 /*
 135  * Generates sound of some count for some number of clock ticks
 136  * [count = 1193180 / frequency]
 137  *
 138  * If freq is 0, will turn off sound, else will turn it on for that time.
 139  * If msec is 0, will return immediately, else will sleep for msec time, then
 140  * turn sound off.
 141  *
 142  * We use the BEEP_TIMER vector since we're using the same method to
 143  * generate sound, and we'll overwrite any beep in progress. That may
 144  * be something to fix later, if we like.
 145  *
 146  * We also return immediately, which is what was implied within the X
 147  * comments - KDMKTONE doesn't put the process to sleep.
 148  */
 149 static void
 150 kd_nosound(unsigned long ignored)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         /* disable counter 2 */
 153         outb(inb_p(0x61)&0xFC, 0x61);
 154         return;
 155 }
 156 
 157 void
 158 kd_mksound(unsigned int count, unsigned int ticks)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160         static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
 161 
 162         cli();
 163         del_timer(&sound_timer);
 164         if (count) {
 165                 /* enable counter 2 */
 166                 outb_p(inb_p(0x61)|3, 0x61);
 167                 /* set command for counter 2, 2 byte write */
 168                 outb_p(0xB6, 0x43);
 169                 /* select desired HZ */
 170                 outb_p(count & 0xff, 0x42);
 171                 outb((count >> 8) & 0xff, 0x42);
 172 
 173                 if (ticks) {
 174                         sound_timer.expires = jiffies+ticks;
 175                         add_timer(&sound_timer);
 176                 }
 177         } else
 178                 kd_nosound(0);
 179         sti();
 180         return;
 181 }
 182 
 183 /*
 184  * We handle the console-specific ioctl's here.  We allow the
 185  * capability to modify any console, not just the fg_console. 
 186  */
 187 int vt_ioctl(struct tty_struct *tty, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 188              unsigned int cmd, unsigned long arg)
 189 {
 190         int i, perm;
 191         unsigned int console;
 192         unsigned char ucval;
 193         struct kbd_struct * kbd;
 194         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 195 
 196         console = vt->vc_num;
 197 
 198         if (!vc_cons_allocated(console))        /* impossible? */
 199                 return -ENOIOCTLCMD;
 200 
 201         /*
 202          * To have permissions to do most of the vt ioctls, we either have
 203          * to be the owner of the tty, or super-user.
 204          */
 205         perm = 0;
 206         if (current->tty == tty || suser())
 207                 perm = 1;
 208 
 209         kbd = kbd_table + console;
 210         switch (cmd) {
 211         case KIOCSOUND:
 212                 if (!perm)
 213                         return -EPERM;
 214                 kd_mksound((unsigned int)arg, 0);
 215                 return 0;
 216 
 217         case KDMKTONE:
 218                 if (!perm)
 219                         return -EPERM;
 220         {
 221                 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
 222 
 223                 /*
 224                  * Generate the tone for the appropriate number of ticks.
 225                  * If the time is zero, turn off sound ourselves.
 226                  */
 227                 kd_mksound(arg & 0xffff, ticks);
 228                 if (ticks == 0)
 229                         kd_nosound(0);
 230                 return 0;
 231         }
 232 
 233         case KDGKBTYPE:
 234                 /*
 235                  * this is naive.
 236                  */
 237                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 238                 if (!i)
 239                         put_user(KB_101, (char *) arg);
 240                 return i;
 241 
 242         case KDADDIO:
 243         case KDDELIO:
 244                 /*
 245                  * KDADDIO and KDDELIO may be able to add ports beyond what
 246                  * we reject here, but to be safe...
 247                  */
 248                 if (arg < GPFIRST || arg > GPLAST)
 249                         return -EINVAL;
 250                 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
 251 
 252         case KDENABIO:
 253         case KDDISABIO:
 254                 return sys_ioperm(GPFIRST, GPNUM,
 255                                   (cmd == KDENABIO)) ? -ENXIO : 0;
 256 
 257         case KDSETMODE:
 258                 /*
 259                  * currently, setting the mode from KD_TEXT to KD_GRAPHICS
 260                  * doesn't do a whole lot. i'm not sure if it should do any
 261                  * restoration of modes or what...
 262                  */
 263                 if (!perm)
 264                         return -EPERM;
 265                 switch (arg) {
 266                 case KD_GRAPHICS:
 267                         break;
 268                 case KD_TEXT0:
 269                 case KD_TEXT1:
 270                         arg = KD_TEXT;
 271                 case KD_TEXT:
 272                         break;
 273                 default:
 274                         return -EINVAL;
 275                 }
 276                 if (vt_cons[console]->vc_mode == (unsigned char) arg)
 277                         return 0;
 278                 vt_cons[console]->vc_mode = (unsigned char) arg;
 279                 if (console != fg_console)
 280                         return 0;
 281                 /*
 282                  * explicitly blank/unblank the screen if switching modes
 283                  */
 284                 if (arg == KD_TEXT)
 285                         do_unblank_screen();
 286                 else
 287                         do_blank_screen(1);
 288                 return 0;
 289 
 290         case KDGETMODE:
 291                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 292                 if (!i)
 293                         put_user(vt_cons[console]->vc_mode, (int *) arg);
 294                 return i;
 295 
 296         case KDMAPDISP:
 297         case KDUNMAPDISP:
 298                 /*
 299                  * these work like a combination of mmap and KDENABIO.
 300                  * this could be easily finished.
 301                  */
 302                 return -EINVAL;
 303 
 304         case KDSKBMODE:
 305                 if (!perm)
 306                         return -EPERM;
 307                 switch(arg) {
 308                   case K_RAW:
 309                         kbd->kbdmode = VC_RAW;
 310                         break;
 311                   case K_MEDIUMRAW:
 312                         kbd->kbdmode = VC_MEDIUMRAW;
 313                         break;
 314                   case K_XLATE:
 315                         kbd->kbdmode = VC_XLATE;
 316                         compute_shiftstate();
 317                         break;
 318                   case K_UNICODE:
 319                         kbd->kbdmode = VC_UNICODE;
 320                         compute_shiftstate();
 321                         break;
 322                   default:
 323                         return -EINVAL;
 324                 }
 325                 if (tty->ldisc.flush_buffer)
 326                         tty->ldisc.flush_buffer(tty);
 327                 return 0;
 328 
 329         case KDGKBMODE:
 330                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 331                 if (!i) {
 332                         ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
 333                                  (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
 334                                  (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 335                                  K_XLATE);
 336                         put_user(ucval, (int *) arg);
 337                 }
 338                 return i;
 339 
 340         /* this could be folded into KDSKBMODE, but for compatibility
 341            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
 342         case KDSKBMETA:
 343                 switch(arg) {
 344                   case K_METABIT:
 345                         clr_vc_kbd_mode(kbd, VC_META);
 346                         break;
 347                   case K_ESCPREFIX:
 348                         set_vc_kbd_mode(kbd, VC_META);
 349                         break;
 350                   default:
 351                         return -EINVAL;
 352                 }
 353                 return 0;
 354 
 355         case KDGKBMETA:
 356                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 357                 if (!i) {
 358                         ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
 359                                  K_METABIT);
 360                         put_user(ucval, (int *) arg);
 361                 }
 362                 return i;
 363 
 364         case KDGETKEYCODE:
 365         {
 366                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 367                 unsigned int sc;
 368                 int kc;
 369 
 370                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
 371                 if (i)
 372                         return i;
 373                 sc = get_user(&a->scancode);
 374                 kc = getkeycode(sc);
 375                 if (kc < 0)
 376                         return kc;
 377                 put_user(kc, &a->keycode);
 378                 return 0;
 379         }
 380 
 381         case KDSETKEYCODE:
 382         {
 383                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 384                 unsigned int sc, kc;
 385 
 386                 if (!perm)
 387                         return -EPERM;
 388                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
 389                 if (i)
 390                         return i;
 391                 sc = get_user(&a->scancode);
 392                 kc = get_user(&a->keycode);
 393                 return setkeycode(sc, kc);
 394         }
 395 
 396         case KDGKBENT:
 397         {
 398                 struct kbentry * const a = (struct kbentry *)arg;
 399                 ushort *key_map, val;
 400                 u_char s;
 401 
 402                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
 403                 if (i)
 404                         return i;
 405                 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
 406                         return -EINVAL;
 407                 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
 408                         return -EINVAL;
 409                 key_map = key_maps[s];
 410                 if (key_map) {
 411                     val = U(key_map[i]);
 412                     if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
 413                         val = K_HOLE;
 414                 } else
 415                     val = (i ? K_HOLE : K_NOSUCHMAP);
 416                 put_user(val, &a->kb_value);
 417                 return 0;
 418         }
 419 
 420         case KDSKBENT:
 421         {
 422                 const struct kbentry * a = (struct kbentry *)arg;
 423                 ushort *key_map;
 424                 u_char s;
 425                 u_short v, ov;
 426 
 427                 if (!perm)
 428                         return -EPERM;
 429                 i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
 430                 if (i)
 431                         return i;
 432                 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
 433                         return -EINVAL;
 434                 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
 435                         return -EINVAL;
 436                 v = get_user(&a->kb_value);
 437                 if (!i && v == K_NOSUCHMAP) {
 438                         /* disallocate map */
 439                         key_map = key_maps[s];
 440                         if (s && key_map) {
 441                             key_maps[s] = 0;
 442                             if (key_map[0] == U(K_ALLOCATED)) {
 443                                 kfree_s(key_map, sizeof(plain_map));
 444                                 keymap_count--;
 445                             }
 446                         }
 447                         return 0;
 448                 }
 449 
 450                 if (KTYP(v) < NR_TYPES) {
 451                     if (KVAL(v) > max_vals[KTYP(v)])
 452                         return -EINVAL;
 453                 } else
 454                     if (kbd->kbdmode != VC_UNICODE)
 455                         return -EINVAL;
 456 
 457                 /* assignment to entry 0 only tests validity of args */
 458                 if (!i)
 459                         return 0;
 460 
 461                 if (!(key_map = key_maps[s])) {
 462                         int j;
 463 
 464                         if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
 465                                 return -EPERM;
 466 
 467                         key_map = (ushort *) kmalloc(sizeof(plain_map),
 468                                                      GFP_KERNEL);
 469                         if (!key_map)
 470                                 return -ENOMEM;
 471                         key_maps[s] = key_map;
 472                         key_map[0] = U(K_ALLOCATED);
 473                         for (j = 1; j < NR_KEYS; j++)
 474                                 key_map[j] = U(K_HOLE);
 475                         keymap_count++;
 476                 }
 477                 ov = U(key_map[i]);
 478                 if (v == ov)
 479                         return 0;       /* nothing to do */
 480                 /*
 481                  * Only the Superuser can set or unset the Secure
 482                  * Attention Key.
 483                  */
 484                 if (((ov == K_SAK) || (v == K_SAK)) && !suser())
 485                         return -EPERM;
 486                 key_map[i] = U(v);
 487                 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
 488                         compute_shiftstate();
 489                 return 0;
 490         }
 491 
 492         case KDGKBSENT:
 493         {
 494                 struct kbsentry *a = (struct kbsentry *)arg;
 495                 char *p;
 496                 u_char *q;
 497                 int sz;
 498 
 499                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 500                 if (i)
 501                         return i;
 502                 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
 503                         return -EINVAL;
 504                 sz = sizeof(a->kb_string) - 1; /* sz should have been
 505                                                   a struct member */
 506                 q = a->kb_string;
 507                 p = func_table[i];
 508                 if(p)
 509                         for ( ; *p && sz; p++, sz--)
 510                                 put_user(*p, q++);
 511                 put_user('\0', q);
 512                 return ((p && *p) ? -EOVERFLOW : 0);
 513         }
 514 
 515         case KDSKBSENT:
 516         {
 517                 struct kbsentry * const a = (struct kbsentry *)arg;
 518                 int delta;
 519                 char *first_free, *fj, *fnw;
 520                 int j, k, sz;
 521                 u_char *p;
 522                 char *q;
 523 
 524                 if (!perm)
 525                         return -EPERM;
 526                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 527                 if (i)
 528                         return i;
 529                 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
 530                         return -EINVAL;
 531                 q = func_table[i];
 532 
 533                 first_free = funcbufptr + (funcbufsize - funcbufleft);
 534                 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
 535                 if (j < MAX_NR_FUNC)
 536                         fj = func_table[j];
 537                 else
 538                         fj = first_free;
 539 
 540                 delta = (q ? -strlen(q) : 1);
 541                 sz = sizeof(a->kb_string);      /* sz should have been
 542                                                    a struct member */
 543                 for (p = a->kb_string; get_user(p) && sz; p++,sz--)
 544                         delta++;
 545                 if (!sz)
 546                         return -EOVERFLOW;
 547                 if (delta <= funcbufleft) {     /* it fits in current buf */
 548                     if (j < MAX_NR_FUNC) {
 549                         memmove(fj + delta, fj, first_free - fj);
 550                         for (k = j; k < MAX_NR_FUNC; k++)
 551                             if (func_table[k])
 552                                 func_table[k] += delta;
 553                     }
 554                     if (!q)
 555                       func_table[i] = fj;
 556                     funcbufleft -= delta;
 557                 } else {                        /* allocate a larger buffer */
 558                     sz = 256;
 559                     while (sz < funcbufsize - funcbufleft + delta)
 560                       sz <<= 1;
 561                     fnw = (char *) kmalloc(sz, GFP_KERNEL);
 562                     if(!fnw)
 563                       return -ENOMEM;
 564 
 565                     if (!q)
 566                       func_table[i] = fj;
 567                     if (fj > funcbufptr)
 568                         memmove(fnw, funcbufptr, fj - funcbufptr);
 569                     for (k = 0; k < j; k++)
 570                       if (func_table[k])
 571                         func_table[k] = fnw + (func_table[k] - funcbufptr);
 572 
 573                     if (first_free > fj) {
 574                         memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
 575                         for (k = j; k < MAX_NR_FUNC; k++)
 576                           if (func_table[k])
 577                             func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
 578                     }
 579                     if (funcbufptr != func_buf)
 580                       kfree_s(funcbufptr, funcbufsize);
 581                     funcbufptr = fnw;
 582                     funcbufleft = funcbufleft - delta + sz - funcbufsize;
 583                     funcbufsize = sz;
 584                 }
 585                 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
 586                         if (!(*q = get_user(p)))
 587                                 break;
 588                 return 0;
 589         }
 590 
 591         case KDGKBDIACR:
 592         {
 593                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 594 
 595                 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
 596                 if (i)
 597                         return i;
 598                 put_user(accent_table_size, &a->kb_cnt);
 599                 memcpy_tofs(a->kbdiacr, accent_table,
 600                             accent_table_size*sizeof(struct kbdiacr));
 601                 return 0;
 602         }
 603 
 604         case KDSKBDIACR:
 605         {
 606                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 607                 unsigned int ct;
 608 
 609                 if (!perm)
 610                         return -EPERM;
 611                 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 612                 if (i)
 613                         return i;
 614                 ct = get_user(&a->kb_cnt);
 615                 if (ct >= MAX_DIACR)
 616                         return -EINVAL;
 617                 accent_table_size = ct;
 618                 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 619                 return 0;
 620         }
 621 
 622         /* the ioctls below read/set the flags usually shown in the leds */
 623         /* don't use them - they will go away without warning */
 624         case KDGKBLED:
 625                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 626                 if (i)
 627                         return i;
 628                 put_user(kbd->ledflagstate |
 629                          (kbd->default_ledflagstate << 4), (char *) arg);
 630                 return 0;
 631 
 632         case KDSKBLED:
 633                 if (!perm)
 634                         return -EPERM;
 635                 if (arg & ~0x77)
 636                         return -EINVAL;
 637                 kbd->ledflagstate = (arg & 7);
 638                 kbd->default_ledflagstate = ((arg >> 4) & 7);
 639                 set_leds();
 640                 return 0;
 641 
 642         /* the ioctls below only set the lights, not the functions */
 643         /* for those, see KDGKBLED and KDSKBLED above */
 644         case KDGETLED:
 645                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 646                 if (i)
 647                         return i;
 648                 put_user(getledstate(), (char *) arg);
 649                 return 0;
 650 
 651         case KDSETLED:
 652                 if (!perm)
 653                   return -EPERM;
 654                 setledstate(kbd, arg);
 655                 return 0;
 656 
 657         /*
 658          * A process can indicate its willingness to accept signals
 659          * generated by pressing an appropriate key combination.
 660          * Thus, one can have a daemon that e.g. spawns a new console
 661          * upon a keypress and then changes to it.
 662          * Probably init should be changed to do this (and have a
 663          * field ks (`keyboard signal') in inittab describing the
 664          * desired action), so that the number of background daemons
 665          * does not increase.
 666          */
 667         case KDSIGACCEPT:
 668         {
 669                 extern int spawnpid, spawnsig;
 670                 if (!perm)
 671                   return -EPERM;
 672                 if (arg < 1 || arg > NSIG || arg == SIGKILL)
 673                   return -EINVAL;
 674                 spawnpid = current->pid;
 675                 spawnsig = arg;
 676                 return 0;
 677         }
 678 
 679         case VT_SETMODE:
 680         {
 681                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 682                 char mode;
 683 
 684                 if (!perm)
 685                         return -EPERM;
 686                 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
 687                 if (i)
 688                         return i;
 689                 mode = get_user(&vtmode->mode);
 690                 if (mode != VT_AUTO && mode != VT_PROCESS)
 691                         return -EINVAL;
 692                 vt_cons[console]->vt_mode.mode = mode;
 693                 vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
 694                 vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
 695                 vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
 696                 /* the frsig is ignored, so we set it to 0 */
 697                 vt_cons[console]->vt_mode.frsig = 0;
 698                 vt_cons[console]->vt_pid = current->pid;
 699                 vt_cons[console]->vt_newvt = 0;
 700                 return 0;
 701         }
 702 
 703         case VT_GETMODE:
 704         {
 705                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 706 
 707                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 708                 if (i)
 709                         return i;
 710                 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
 711                 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
 712                 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
 713                 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 714                 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 715                 return 0;
 716         }
 717 
 718         /*
 719          * Returns global vt state. Note that VT 0 is always open, since
 720          * it's an alias for the current VT, and people can't use it here.
 721          * We cannot return state for more than 16 VTs, since v_state is short.
 722          */
 723         case VT_GETSTATE:
 724         {
 725                 struct vt_stat *vtstat = (struct vt_stat *)arg;
 726                 unsigned short state, mask;
 727 
 728                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 729                 if (i)
 730                         return i;
 731                 put_user(fg_console + 1, &vtstat->v_active);
 732                 state = 1;      /* /dev/tty0 is always open */
 733                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 734                         if (VT_IS_IN_USE(i))
 735                                 state |= mask;
 736                 put_user(state, &vtstat->v_state);
 737                 return 0;
 738         }
 739 
 740         /*
 741          * Returns the first available (non-opened) console.
 742          */
 743         case VT_OPENQRY:
 744                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 745                 if (i)
 746                         return i;
 747                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
 748                         if (! VT_IS_IN_USE(i))
 749                                 break;
 750                 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
 751                 return 0;
 752 
 753         /*
 754          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
 755          * with num >= 1 (switches to vt 0, our console, are not allowed, just
 756          * to preserve sanity).
 757          */
 758         case VT_ACTIVATE:
 759                 if (!perm)
 760                         return -EPERM;
 761                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 762                         return -ENXIO;
 763                 arg--;
 764                 i = vc_allocate(arg);
 765                 if (i)
 766                         return i;
 767                 change_console(arg);
 768                 return 0;
 769 
 770         /*
 771          * wait until the specified VT has been activated
 772          */
 773         case VT_WAITACTIVE:
 774                 if (!perm)
 775                         return -EPERM;
 776                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 777                         return -ENXIO;
 778                 arg--;
 779                 while (fg_console != arg)
 780                 {
 781                         if (vt_waitactive() < 0)
 782                                 return -EINTR;
 783                 }
 784                 return 0;
 785 
 786         /*
 787          * If a vt is under process control, the kernel will not switch to it
 788          * immediately, but postpone the operation until the process calls this
 789          * ioctl, allowing the switch to complete.
 790          *
 791          * According to the X sources this is the behavior:
 792          *      0:      pending switch-from not OK
 793          *      1:      pending switch-from OK
 794          *      2:      completed switch-to OK
 795          */
 796         case VT_RELDISP:
 797                 if (!perm)
 798                         return -EPERM;
 799                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 800                         return -EINVAL;
 801 
 802                 /*
 803                  * Switching-from response
 804                  */
 805                 if (vt_cons[console]->vt_newvt >= 0)
 806                 {
 807                         if (arg == 0)
 808                                 /*
 809                                  * Switch disallowed, so forget we were trying
 810                                  * to do it.
 811                                  */
 812                                 vt_cons[console]->vt_newvt = -1;
 813 
 814                         else
 815                         {
 816                                 /*
 817                                  * The current vt has been released, so
 818                                  * complete the switch.
 819                                  */
 820                                 int newvt = vt_cons[console]->vt_newvt;
 821                                 vt_cons[console]->vt_newvt = -1;
 822                                 i = vc_allocate(newvt);
 823                                 if (i)
 824                                         return i;
 825                                 complete_change_console(newvt);
 826                         }
 827                 }
 828 
 829                 /*
 830                  * Switched-to response
 831                  */
 832                 else
 833                 {
 834                         /*
 835                          * If it's just an ACK, ignore it
 836                          */
 837                         if (arg != VT_ACKACQ)
 838                                 return -EINVAL;
 839                 }
 840 
 841                 return 0;
 842 
 843          /*
 844           * Disallocate memory associated to VT (but leave VT1)
 845           */
 846          case VT_DISALLOCATE:
 847                 if (arg > MAX_NR_CONSOLES)
 848                         return -ENXIO;
 849                 if (arg == 0) {
 850                     /* disallocate all unused consoles, but leave 0 */
 851                     for (i=1; i<MAX_NR_CONSOLES; i++)
 852                       if (! VT_BUSY(i))
 853                         vc_disallocate(i);
 854                 } else {
 855                     /* disallocate a single console, if possible */
 856                     arg--;
 857                     if (VT_BUSY(arg))
 858                       return -EBUSY;
 859                     if (arg)                          /* leave 0 */
 860                       vc_disallocate(arg);
 861                 }
 862                 return 0;
 863 
 864         case VT_RESIZE:
 865         {
 866                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
 867                 ushort ll,cc;
 868                 if (!perm)
 869                         return -EPERM;
 870                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 871                 if (i)
 872                         return i;
 873                 ll = get_user(&vtsizes->v_rows);
 874                 cc = get_user(&vtsizes->v_cols);
 875                 i = vc_resize(ll, cc);
 876                 return i ? i :  kd_size_changed(ll, cc);
 877         }
 878 
 879         case VT_RESIZEX:
 880         {
 881                 struct vt_consize *vtconsize = (struct vt_consize *) arg;
 882                 ushort ll,cc,vlin,clin,vcol,ccol;
 883                 if (!perm)
 884                         return -EPERM;
 885                 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
 886                 if (i)
 887                         return i;
 888                 ll = get_user(&vtconsize->v_rows);
 889                 cc = get_user(&vtconsize->v_cols);
 890                 vlin = get_user(&vtconsize->v_vlin);
 891                 clin = get_user(&vtconsize->v_clin);
 892                 vcol = get_user(&vtconsize->v_vcol);
 893                 ccol = get_user(&vtconsize->v_ccol);
 894                 vlin = vlin ? vlin : video_scan_lines;
 895                 if ( clin )
 896                   {
 897                     if ( ll )
 898                       {
 899                         if ( ll != vlin/clin )
 900                           return EINVAL; /* Parameters don't add up */
 901                       }
 902                     else 
 903                       ll = vlin/clin;
 904                   }
 905                 if ( vcol && ccol )
 906                   {
 907                     if ( cc )
 908                       {
 909                         if ( cc != vcol/ccol )
 910                           return EINVAL;
 911                       }
 912                     else
 913                       cc = vcol/ccol;
 914                   }
 915 
 916                 if ( clin > 32 )
 917                   return EINVAL;
 918                     
 919                 if ( vlin )
 920                   video_scan_lines = vlin;
 921                 if ( clin )
 922                   video_font_height = clin;
 923                 
 924                 i = vc_resize(ll, cc);
 925                 if (i)
 926                         return i;
 927 
 928                 kd_size_changed(ll, cc);
 929                 return 0;
 930         }
 931 
 932         case PIO_FONT:
 933                 if (!perm)
 934                         return -EPERM;
 935                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 936                         return -EINVAL;
 937                 return con_set_font((char *)arg, 0);
 938                 /* con_set_font() defined in console.c */
 939 
 940         case GIO_FONT:
 941                 if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
 942                     video_mode_512ch)
 943                         return -EINVAL;
 944                 return con_get_font((char *)arg);
 945                 /* con_get_font() defined in console.c */
 946 
 947         case PIO_CMAP:
 948                 if (!perm)
 949                         return -EPERM;
 950                 return con_set_cmap((char *)arg);
 951                 /* con_set_cmap() defined in console.c */
 952 
 953         case GIO_CMAP:
 954                 return con_get_cmap((char *)arg);
 955                 /* con_get_cmap() defined in console.c */
 956 
 957         case PIO_FONTX:
 958         {
 959                 struct consolefontdesc cfdarg;
 960 
 961                 if (!perm)
 962                         return -EPERM;
 963                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 964                         return -EINVAL;
 965                 i = verify_area(VERIFY_READ, (void *)arg,
 966                                 sizeof(struct consolefontdesc));
 967                 if (i) return i;
 968                 memcpy_fromfs(&cfdarg, (void *)arg,
 969                               sizeof(struct consolefontdesc)); 
 970                 
 971                 if ( cfdarg.charcount == 256 ||
 972                      cfdarg.charcount == 512 ) {
 973                         i = con_set_font(cfdarg.chardata,
 974                                 cfdarg.charcount == 512);
 975                         if (i)
 976                                 return i;
 977                         i = con_adjust_height(cfdarg.charheight);
 978                         return (i <= 0) ? i : kd_size_changed(i, 0);
 979                 } else
 980                         return -EINVAL;
 981         }
 982 
 983         case PIO_FONTRESET:
 984         {
 985                 if (!perm)
 986                         return -EPERM;
 987                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 988                         return -EINVAL;
 989 
 990 #ifdef BROKEN_GRAPHICS_PROGRAMS
 991                 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
 992                    font is not saved. */
 993                 return -ENOSYS;
 994 #else
 995 
 996                 i = con_set_font(NULL, 0);      /* Set font to default */
 997                 if (i) return i;
 998 
 999                 i = con_adjust_height(default_font_height);
1000                 if ( i > 0 ) kd_size_changed(i, 0);
1001                 con_set_default_unimap();
1002 
1003                 return 0;
1004 #endif
1005         }
1006 
1007         case GIO_FONTX:
1008         {
1009                 struct consolefontdesc cfdarg;
1010                 int nchar;
1011 
1012                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1013                         return -EINVAL;
1014                 i = verify_area(VERIFY_WRITE, (void *)arg,
1015                         sizeof(struct consolefontdesc));
1016                 if (i) return i;        
1017                 memcpy_fromfs(&cfdarg, (void *) arg,
1018                               sizeof(struct consolefontdesc)); 
1019                 i = cfdarg.charcount;
1020                 cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
1021                 cfdarg.charheight = video_font_height;
1022                 memcpy_tofs((void *) arg, &cfdarg,
1023                             sizeof(struct consolefontdesc)); 
1024                 if ( cfdarg.chardata )
1025                 {
1026                         if ( i < nchar )
1027                                 return -ENOMEM;
1028                         return con_get_font(cfdarg.chardata);
1029                 } else
1030                         return 0;
1031         }
1032 
1033         case PIO_SCRNMAP:
1034                 if (!perm)
1035                         return -EPERM;
1036                 return con_set_trans_old((unsigned char *)arg);
1037 
1038         case GIO_SCRNMAP:
1039                 return con_get_trans_old((unsigned char *)arg);
1040 
1041         case PIO_UNISCRNMAP:
1042                 if (!perm)
1043                         return -EPERM;
1044                 return con_set_trans_new((unsigned short *)arg);
1045 
1046         case GIO_UNISCRNMAP:
1047                 return con_get_trans_new((unsigned short *)arg);
1048 
1049         case PIO_UNIMAPCLR:
1050               { struct unimapinit ui;
1051                 if (!perm)
1052                         return -EPERM;
1053                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1054                 if (i)
1055                   return i;
1056                 memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1057                 con_clear_unimap(&ui);
1058                 return 0;
1059               }
1060 
1061         case PIO_UNIMAP:
1062               { struct unimapdesc *ud;
1063                 u_short ct;
1064                 struct unipair *list;
1065 
1066                 if (!perm)
1067                         return -EPERM;
1068                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1069                 if (i == 0) {
1070                     ud = (struct unimapdesc *) arg;
1071                     ct = get_user(&ud->entry_ct);
1072                     list = get_user(&ud->entries);
1073                     i = verify_area(VERIFY_READ, (void *) list,
1074                                     ct*sizeof(struct unipair));
1075                 }
1076                 if (i)
1077                   return i;
1078                 return con_set_unimap(ct, list);
1079               }
1080 
1081         case GIO_UNIMAP:
1082               { struct unimapdesc *ud;
1083                 u_short ct;
1084                 struct unipair *list;
1085 
1086                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1087                 if (i == 0) {
1088                     ud = (struct unimapdesc *) arg;
1089                     ct = get_user(&ud->entry_ct);
1090                     list = get_user(&ud->entries);
1091                     if (ct)
1092                       i = verify_area(VERIFY_WRITE, (void *) list,
1093                                       ct*sizeof(struct unipair));
1094                 }
1095                 if (i)
1096                   return i;
1097                 return con_get_unimap(ct, &(ud->entry_ct), list);
1098               }
1099         case VT_LOCKSWITCH:
1100                 if (!suser())
1101                    return -EPERM;
1102                 vt_dont_switch = 1;
1103                 return 0;
1104         case VT_UNLOCKSWITCH:
1105                 if (!suser())
1106                    return -EPERM;
1107                 vt_dont_switch = 0;
1108                 return 0;
1109         default:
1110                 return -ENOIOCTLCMD;
1111         }
1112 }

/* [previous][next][first][last][top][bottom][index][help] */