root/drivers/char/vt.c

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

DEFINITIONS

This source file includes following definitions.
  1. kd_nosound
  2. kd_mksound
  3. 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  */
   9 
  10 #include <linux/types.h>
  11 #include <linux/errno.h>
  12 #include <linux/sched.h>
  13 #include <linux/tty.h>
  14 #include <linux/timer.h>
  15 #include <linux/kernel.h>
  16 #include <linux/kd.h>
  17 #include <linux/vt.h>
  18 #include <linux/string.h>
  19 #include <linux/malloc.h>
  20 
  21 #include <asm/io.h>
  22 #include <asm/segment.h>
  23 
  24 #include "kbd_kern.h"
  25 #include "vt_kern.h"
  26 #include "diacr.h"
  27 
  28 extern struct tty_driver console_driver;
  29 
  30 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
  31 
  32 /*
  33  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  34  * experimentation and study of X386 SYSV handling.
  35  *
  36  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  37  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  38  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
  39  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
  40  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  41  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  42  * to the current console is done by the main ioctl code.
  43  */
  44 
  45 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
  46 
  47 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
  48 
  49 extern int getkeycode(unsigned int scancode);
  50 extern int setkeycode(unsigned int scancode, unsigned int keycode);
  51 extern void compute_shiftstate(void);
  52 extern void change_console(unsigned int new_console);
  53 extern void complete_change_console(unsigned int new_console);
  54 extern int vt_waitactive(void);
  55 extern void do_blank_screen(int nopowersave);
  56 extern void do_unblank_screen(void);
  57 
  58 extern unsigned int keymap_count;
  59 
  60 /*
  61  * routines to load custom translation table and EGA/VGA font from console.c
  62  */
  63 extern int con_set_trans(char * table);
  64 extern int con_get_trans(char * table);
  65 extern int con_set_font(char * fontmap);
  66 extern int con_get_font(char * fontmap);
  67 
  68 /*
  69  * these are the valid i/o ports we're allowed to change. they map all the
  70  * video ports
  71  */
  72 #define GPFIRST 0x3b4
  73 #define GPLAST 0x3df
  74 #define GPNUM (GPLAST - GPFIRST + 1)
  75 
  76 /*
  77  * Generates sound of some count for some number of clock ticks
  78  * [count = 1193180 / frequency]
  79  *
  80  * If freq is 0, will turn off sound, else will turn it on for that time.
  81  * If msec is 0, will return immediately, else will sleep for msec time, then
  82  * turn sound off.
  83  *
  84  * We use the BEEP_TIMER vector since we're using the same method to
  85  * generate sound, and we'll overwrite any beep in progress. That may
  86  * be something to fix later, if we like.
  87  *
  88  * We also return immediately, which is what was implied within the X
  89  * comments - KDMKTONE doesn't put the process to sleep.
  90  */
  91 static void
  92 kd_nosound(unsigned long ignored)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         /* disable counter 2 */
  95         outb(inb_p(0x61)&0xFC, 0x61);
  96         return;
  97 }
  98 
  99 void
 100 kd_mksound(unsigned int count, unsigned int ticks)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
 103 
 104         cli();
 105         del_timer(&sound_timer);
 106         if (count) {
 107                 /* enable counter 2 */
 108                 outb_p(inb_p(0x61)|3, 0x61);
 109                 /* set command for counter 2, 2 byte write */
 110                 outb_p(0xB6, 0x43);
 111                 /* select desired HZ */
 112                 outb_p(count & 0xff, 0x42);
 113                 outb((count >> 8) & 0xff, 0x42);
 114 
 115                 if (ticks) {
 116                         sound_timer.expires = ticks;
 117                         add_timer(&sound_timer);
 118                 }
 119         } else
 120                 kd_nosound(0);
 121         sti();
 122         return;
 123 }
 124 
 125 /*
 126  * We handle the console-specific ioctl's here.  We allow the
 127  * capability to modify any console, not just the fg_console. 
 128  */
 129 int vt_ioctl(struct tty_struct *tty, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 130              unsigned int cmd, unsigned long arg)
 131 {
 132         int i;
 133         unsigned int console;
 134         unsigned char ucval;
 135         struct kbd_struct * kbd;
 136         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 137 
 138         console = vt->vc_num;
 139 
 140         if (!vc_cons_allocated(console))        /* impossible? */
 141                 return -ENOIOCTLCMD;
 142 
 143         kbd = kbd_table + console;
 144         switch (cmd) {
 145         case KIOCSOUND:
 146                 kd_mksound((unsigned int)arg, 0);
 147                 return 0;
 148 
 149         case KDMKTONE:
 150         {
 151                 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
 152 
 153                 /*
 154                  * Generate the tone for the appropriate number of ticks.
 155                  * If the time is zero, turn off sound ourselves.
 156                  */
 157                 kd_mksound(arg & 0xffff, ticks);
 158                 if (ticks == 0)
 159                         kd_nosound(0);
 160                 return 0;
 161         }
 162 
 163         case KDGKBTYPE:
 164                 /*
 165                  * this is naive.
 166                  */
 167                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 168                 if (!i)
 169                         put_fs_byte(KB_101, (char *) arg);
 170                 return i;
 171 
 172         case KDADDIO:
 173         case KDDELIO:
 174                 /*
 175                  * KDADDIO and KDDELIO may be able to add ports beyond what
 176                  * we reject here, but to be safe...
 177                  */
 178                 if (arg < GPFIRST || arg > GPLAST)
 179                         return -EINVAL;
 180                 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
 181 
 182         case KDENABIO:
 183         case KDDISABIO:
 184                 return sys_ioperm(GPFIRST, GPNUM,
 185                                   (cmd == KDENABIO)) ? -ENXIO : 0;
 186 
 187         case KDSETMODE:
 188                 /*
 189                  * currently, setting the mode from KD_TEXT to KD_GRAPHICS
 190                  * doesn't do a whole lot. i'm not sure if it should do any
 191                  * restoration of modes or what...
 192                  */
 193                 if (!suser())
 194                         return -EPERM;
 195                 switch (arg) {
 196                 case KD_GRAPHICS:
 197                         break;
 198                 case KD_TEXT0:
 199                 case KD_TEXT1:
 200                         arg = KD_TEXT;
 201                 case KD_TEXT:
 202                         break;
 203                 default:
 204                         return -EINVAL;
 205                 }
 206                 if (vt_cons[console]->vc_mode == (unsigned char) arg)
 207                         return 0;
 208                 vt_cons[console]->vc_mode = (unsigned char) arg;
 209                 if (console != fg_console)
 210                         return 0;
 211                 /*
 212                  * explicitly blank/unblank the screen if switching modes
 213                  */
 214                 if (arg == KD_TEXT)
 215                         do_unblank_screen();
 216                 else
 217                         do_blank_screen(1);
 218                 return 0;
 219 
 220         case KDGETMODE:
 221                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 222                 if (!i)
 223                         put_fs_long(vt_cons[console]->vc_mode, (unsigned long *) arg);
 224                 return i;
 225 
 226         case KDMAPDISP:
 227         case KDUNMAPDISP:
 228                 /*
 229                  * these work like a combination of mmap and KDENABIO.
 230                  * this could be easily finished.
 231                  */
 232                 return -EINVAL;
 233 
 234         case KDSKBMODE:
 235                 if (!suser())
 236                         return -EPERM;
 237                 switch(arg) {
 238                   case K_RAW:
 239                         kbd->kbdmode = VC_RAW;
 240                         break;
 241                   case K_MEDIUMRAW:
 242                         kbd->kbdmode = VC_MEDIUMRAW;
 243                         break;
 244                   case K_XLATE:
 245                         kbd->kbdmode = VC_XLATE;
 246                         compute_shiftstate();
 247                         break;
 248                   case K_UNICODE:
 249                         kbd->kbdmode = VC_UNICODE;
 250                         compute_shiftstate();
 251                         break;
 252                   default:
 253                         return -EINVAL;
 254                 }
 255                 if (tty->ldisc.flush_buffer)
 256                         tty->ldisc.flush_buffer(tty);
 257                 return 0;
 258 
 259         case KDGKBMODE:
 260                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 261                 if (!i) {
 262                         ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
 263                                  (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
 264                                  (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 265                                  K_XLATE);
 266                         put_fs_long(ucval, (unsigned long *) arg);
 267                 }
 268                 return i;
 269 
 270         /* this could be folded into KDSKBMODE, but for compatibility
 271            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
 272         case KDSKBMETA:
 273                 switch(arg) {
 274                   case K_METABIT:
 275                         clr_vc_kbd_mode(kbd, VC_META);
 276                         break;
 277                   case K_ESCPREFIX:
 278                         set_vc_kbd_mode(kbd, VC_META);
 279                         break;
 280                   default:
 281                         return -EINVAL;
 282                 }
 283                 return 0;
 284 
 285         case KDGKBMETA:
 286                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
 287                 if (!i) {
 288                         ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
 289                                  K_METABIT);
 290                         put_fs_long(ucval, (unsigned long *) arg);
 291                 }
 292                 return i;
 293 
 294         case KDGETKEYCODE:
 295         {
 296                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 297                 unsigned int sc;
 298                 int kc;
 299 
 300                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
 301                 if (i)
 302                         return i;
 303                 sc = get_fs_long((int *) &a->scancode);
 304                 kc = getkeycode(sc);
 305                 if (kc < 0)
 306                         return kc;
 307                 put_fs_long(kc, (int *) &a->keycode);
 308                 return 0;
 309         }
 310 
 311         case KDSETKEYCODE:
 312         {
 313                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 314                 unsigned int sc, kc;
 315 
 316                 if (!suser())
 317                         return -EPERM;
 318                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
 319                 if (i)
 320                         return i;
 321                 sc = get_fs_long((int *) &a->scancode);
 322                 kc = get_fs_long((int *) &a->keycode);
 323                 return setkeycode(sc, kc);
 324         }
 325 
 326         case KDGKBENT:
 327         {
 328                 struct kbentry * const a = (struct kbentry *)arg;
 329                 ushort *key_map, val;
 330                 u_char s;
 331 
 332                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
 333                 if (i)
 334                         return i;
 335                 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
 336                         return -EINVAL;
 337                 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
 338                         return -EINVAL;
 339                 key_map = key_maps[s];
 340                 if (key_map) {
 341                     val = U(key_map[i]);
 342                     if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
 343                         val = K_HOLE;
 344                 } else
 345                     val = (i ? K_HOLE : K_NOSUCHMAP);
 346                 put_fs_word(val, (short *) &a->kb_value);
 347                 return 0;
 348         }
 349 
 350         case KDSKBENT:
 351         {
 352                 const struct kbentry * a = (struct kbentry *)arg;
 353                 ushort *key_map;
 354                 u_char s;
 355                 u_short v;
 356 
 357                 if (!suser())
 358                         return -EPERM;
 359                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
 360                 if (i)
 361                         return i;
 362                 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
 363                         return -EINVAL;
 364                 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
 365                         return -EINVAL;
 366                 v = get_fs_word(&a->kb_value);
 367                 if (!i && v == K_NOSUCHMAP) {
 368                         /* disallocate map */
 369                         key_map = key_maps[s];
 370                         if (key_map) {
 371                             key_maps[s] = 0;
 372                             if (key_map[0] == U(K_ALLOCATED)) {
 373                                 kfree_s(key_map, sizeof(plain_map));
 374                                 keymap_count--;
 375                             }
 376                         }
 377                         return 0;
 378                 }
 379 
 380                 if (KTYP(v) < NR_TYPES) {
 381                     if (KVAL(v) > max_vals[KTYP(v)])
 382                         return -EINVAL;
 383                 } else
 384                     if (kbd->kbdmode != VC_UNICODE)
 385                         return -EINVAL;
 386 
 387                 /* assignment to entry 0 only tests validity of args */
 388                 if (!i)
 389                         return 0;
 390 
 391                 if (!(key_map = key_maps[s])) {
 392                         if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
 393                                 return -EPERM;
 394 
 395                         key_map = (ushort *) kmalloc(sizeof(plain_map),
 396                                                      GFP_KERNEL);
 397                         if (!key_map)
 398                                 return -ENOMEM;
 399                         key_maps[s] = key_map;
 400                         key_map[0] = U(K_ALLOCATED);
 401                         for (s = 1; s < NR_KEYS; s++)
 402                                 key_map[s] = U(K_HOLE);
 403                         keymap_count++;
 404                 }
 405                 /*
 406                  * Only the Superuser can set or unset the Secure
 407                  * Attention Key.
 408                  */
 409                 if (((key_map[i] == U(K_SAK)) || (v == K_SAK)) &&
 410                     !suser())
 411                         return -EPERM;
 412                 key_map[i] = U(v);
 413                 return 0;
 414         }
 415 
 416         case KDGKBSENT:
 417         {
 418                 struct kbsentry *a = (struct kbsentry *)arg;
 419                 char *p;
 420                 u_char *q;
 421                 int sz;
 422 
 423                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 424                 if (i)
 425                         return i;
 426                 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
 427                         return -EINVAL;
 428                 sz = sizeof(a->kb_string) - 1; /* sz should have been
 429                                                   a struct member */
 430                 q = a->kb_string;
 431                 p = func_table[i];
 432                 if(p)
 433                         for ( ; *p && sz; p++, sz--)
 434                                 put_fs_byte(*p, q++);
 435                 put_fs_byte(0, q);
 436                 return ((p && *p) ? -EOVERFLOW : 0);
 437         }
 438 
 439         case KDSKBSENT:
 440         {
 441                 struct kbsentry * const a = (struct kbsentry *)arg;
 442                 int delta;
 443                 char *first_free, *fj, *fnw;
 444                 int j, k, sz;
 445                 u_char *p;
 446                 char *q;
 447 
 448                 if (!suser())
 449                         return -EPERM;
 450                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 451                 if (i)
 452                         return i;
 453                 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC)
 454                         return -EINVAL;
 455                 q = func_table[i];
 456 
 457                 first_free = funcbufptr + (funcbufsize - funcbufleft);
 458                 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
 459                 if (j < MAX_NR_FUNC)
 460                         fj = func_table[j];
 461                 else
 462                         fj = first_free;
 463 
 464                 delta = (q ? -strlen(q) : 1);
 465                 sz = sizeof(a->kb_string);      /* sz should have been
 466                                                    a struct member */
 467                 for (p = a->kb_string; get_fs_byte(p) && sz; p++,sz--)
 468                         delta++;
 469                 if (!sz)
 470                         return -EOVERFLOW;
 471                 if (delta <= funcbufleft) {     /* it fits in current buf */
 472                     if (j < MAX_NR_FUNC) {
 473                         memmove(fj + delta, fj, first_free - fj);
 474                         for (k = j; k < MAX_NR_FUNC; k++)
 475                             if (func_table[k])
 476                                 func_table[k] += delta;
 477                     }
 478                     if (!q)
 479                       func_table[i] = fj;
 480                     funcbufleft -= delta;
 481                 } else {                        /* allocate a larger buffer */
 482                     sz = 256;
 483                     while (sz < funcbufsize - funcbufleft + delta)
 484                       sz <<= 1;
 485                     fnw = (char *) kmalloc(sz, GFP_KERNEL);
 486                     if(!fnw)
 487                       return -ENOMEM;
 488 
 489                     if (!q)
 490                       func_table[i] = fj;
 491                     if (fj > funcbufptr)
 492                         memmove(fnw, funcbufptr, fj - funcbufptr);
 493                     for (k = 0; k < j; k++)
 494                       if (func_table[k])
 495                         func_table[k] = fnw + (func_table[k] - funcbufptr);
 496 
 497                     if (first_free > fj) {
 498                         memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
 499                         for (k = j; k < MAX_NR_FUNC; k++)
 500                           if (func_table[k])
 501                             func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
 502                     }
 503                     if (funcbufptr != func_buf)
 504                       kfree_s(funcbufptr, funcbufsize);
 505                     funcbufptr = fnw;
 506                     funcbufleft = funcbufleft - delta + sz - funcbufsize;
 507                     funcbufsize = sz;
 508                 }
 509                 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
 510                         if (!(*q = get_fs_byte(p)))
 511                                 break;
 512                 return 0;
 513         }
 514 
 515         case KDGKBDIACR:
 516         {
 517                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 518 
 519                 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
 520                 if (i)
 521                         return i;
 522                 put_fs_long(accent_table_size, &a->kb_cnt);
 523                 memcpy_tofs(a->kbdiacr, accent_table,
 524                             accent_table_size*sizeof(struct kbdiacr));
 525                 return 0;
 526         }
 527 
 528         case KDSKBDIACR:
 529         {
 530                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 531                 unsigned int ct;
 532 
 533                 if (!suser())
 534                         return -EPERM;
 535                 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 536                 if (i)
 537                         return i;
 538                 ct = get_fs_long(&a->kb_cnt);
 539                 if (ct >= MAX_DIACR)
 540                         return -EINVAL;
 541                 accent_table_size = ct;
 542                 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 543                 return 0;
 544         }
 545 
 546         /* the ioctls below read/set the flags usually shown in the leds */
 547         /* don't use them - they will go away without warning */
 548         case KDGKBLED:
 549                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 550                 if (i)
 551                         return i;
 552                 put_fs_byte(kbd->ledflagstate |
 553                             (kbd->default_ledflagstate << 4), (char *) arg);
 554                 return 0;
 555 
 556         case KDSKBLED:
 557                 if (!suser())
 558                         return -EPERM;
 559                 if (arg & ~0x77)
 560                         return -EINVAL;
 561                 kbd->ledflagstate = (arg & 7);
 562                 kbd->default_ledflagstate = ((arg >> 4) & 7);
 563                 set_leds();
 564                 return 0;
 565 
 566         /* the ioctls below only set the lights, not the functions */
 567         /* for those, see KDGKBLED and KDSKBLED above */
 568         case KDGETLED:
 569                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 570                 if (i)
 571                         return i;
 572                 put_fs_byte(getledstate(), (char *) arg);
 573                 return 0;
 574 
 575         case KDSETLED:
 576                 /* OK, I'll let ordinary users run blinkenlights - zblaxell */
 577                 setledstate(kbd, arg);
 578                 return 0;
 579 
 580         case VT_SETMODE:
 581         {
 582                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 583                 char mode;
 584 
 585                 if (!suser())
 586                         return -EPERM;
 587                 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
 588                 if (i)
 589                         return i;
 590                 mode = get_fs_byte(&vtmode->mode);
 591                 if (mode != VT_AUTO && mode != VT_PROCESS)
 592                         return -EINVAL;
 593                 vt_cons[console]->vt_mode.mode = mode;
 594                 vt_cons[console]->vt_mode.waitv = get_fs_byte(&vtmode->waitv);
 595                 vt_cons[console]->vt_mode.relsig = get_fs_word(&vtmode->relsig);
 596                 vt_cons[console]->vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
 597                 /* the frsig is ignored, so we set it to 0 */
 598                 vt_cons[console]->vt_mode.frsig = 0;
 599                 vt_cons[console]->vt_pid = current->pid;
 600                 vt_cons[console]->vt_newvt = 0;
 601                 return 0;
 602         }
 603 
 604         case VT_GETMODE:
 605         {
 606                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 607 
 608                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 609                 if (i)
 610                         return i;
 611                 put_fs_byte(vt_cons[console]->vt_mode.mode, &vtmode->mode);
 612                 put_fs_byte(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
 613                 put_fs_word(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
 614                 put_fs_word(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 615                 put_fs_word(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 616                 return 0;
 617         }
 618 
 619         /*
 620          * Returns global vt state. Note that VT 0 is always open, since
 621          * it's an alias for the current VT, and people can't use it here.
 622          * We cannot return state for more than 16 VTs, since v_state is short.
 623          */
 624         case VT_GETSTATE:
 625         {
 626                 struct vt_stat *vtstat = (struct vt_stat *)arg;
 627                 unsigned short state, mask;
 628 
 629                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 630                 if (i)
 631                         return i;
 632                 put_fs_word(fg_console + 1, &vtstat->v_active);
 633                 state = 1;      /* /dev/tty0 is always open */
 634                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 635                         if (console_driver.table[i] &&
 636                             console_driver.table[i]->count > 0)
 637                                 state |= mask;
 638                 put_fs_word(state, &vtstat->v_state);
 639                 return 0;
 640         }
 641 
 642         /*
 643          * Returns the first available (non-opened) console.
 644          */
 645         case VT_OPENQRY:
 646                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
 647                 if (i)
 648                         return i;
 649                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
 650                         if (! VT_IS_IN_USE(i))
 651                                 break;
 652                 put_fs_long(i < MAX_NR_CONSOLES ? (i+1) : -1,
 653                             (unsigned long *)arg);
 654                 return 0;
 655 
 656         /*
 657          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
 658          * with num >= 1 (switches to vt 0, our console, are not allowed, just
 659          * to preserve sanity).
 660          */
 661         case VT_ACTIVATE:
 662                 if (!suser())
 663                         return -EPERM;
 664                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 665                         return -ENXIO;
 666                 arg--;
 667                 i = vc_allocate(arg);
 668                 if (i)
 669                         return i;
 670                 change_console(arg);
 671                 return 0;
 672 
 673         /*
 674          * wait until the specified VT has been activated
 675          */
 676         case VT_WAITACTIVE:
 677                 if (!suser())
 678                         return -EPERM;
 679                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 680                         return -ENXIO;
 681                 arg--;
 682                 while (fg_console != arg)
 683                 {
 684                         if (vt_waitactive() < 0)
 685                                 return -EINTR;
 686                 }
 687                 return 0;
 688 
 689         /*
 690          * If a vt is under process control, the kernel will not switch to it
 691          * immediately, but postpone the operation until the process calls this
 692          * ioctl, allowing the switch to complete.
 693          *
 694          * According to the X sources this is the behavior:
 695          *      0:      pending switch-from not OK
 696          *      1:      pending switch-from OK
 697          *      2:      completed switch-to OK
 698          */
 699         case VT_RELDISP:
 700                 if (!suser())
 701                         return -EPERM;
 702                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 703                         return -EINVAL;
 704 
 705                 /*
 706                  * Switching-from response
 707                  */
 708                 if (vt_cons[console]->vt_newvt >= 0)
 709                 {
 710                         if (arg == 0)
 711                                 /*
 712                                  * Switch disallowed, so forget we were trying
 713                                  * to do it.
 714                                  */
 715                                 vt_cons[console]->vt_newvt = -1;
 716 
 717                         else
 718                         {
 719                                 /*
 720                                  * The current vt has been released, so
 721                                  * complete the switch.
 722                                  */
 723                                 int newvt = vt_cons[console]->vt_newvt;
 724                                 vt_cons[console]->vt_newvt = -1;
 725                                 i = vc_allocate(newvt);
 726                                 if (i)
 727                                         return i;
 728                                 complete_change_console(newvt);
 729                         }
 730                 }
 731 
 732                 /*
 733                  * Switched-to response
 734                  */
 735                 else
 736                 {
 737                         /*
 738                          * If it's just an ACK, ignore it
 739                          */
 740                         if (arg != VT_ACKACQ)
 741                                 return -EINVAL;
 742                 }
 743 
 744                 return 0;
 745 
 746          /*
 747           * Disallocate memory associated to VT (but leave VT1)
 748           */
 749          case VT_DISALLOCATE:
 750                 if (!suser())
 751                         return -EPERM;
 752                 if (arg > MAX_NR_CONSOLES)
 753                         return -ENXIO;
 754                 if (arg == 0) {
 755                     /* disallocate all unused consoles, but leave 0 */
 756                     for (i=1; i<MAX_NR_CONSOLES; i++)
 757                       if (! VT_IS_IN_USE(i)) {
 758                           if (i == fg_console)
 759                             change_console(0);
 760                           vc_disallocate(i);
 761                       }
 762                 } else {
 763                     /* disallocate a single console, if possible */
 764                     arg--;
 765                     if (VT_IS_IN_USE(arg))
 766                       return -EBUSY;
 767                     if (arg) {                        /* leave 0 */
 768                         if (arg == fg_console)
 769                           change_console(0);
 770                         vc_disallocate(arg);
 771                     }
 772                 }
 773                 return 0;
 774 
 775         case VT_RESIZE:
 776         {
 777                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
 778                 ushort ll,cc;
 779                 if (!suser())
 780                         return -EPERM;
 781                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 782                 if (i)
 783                         return i;
 784                 ll = get_fs_word(&vtsizes->v_rows);
 785                 cc = get_fs_word(&vtsizes->v_cols);
 786                 return vc_resize(ll, cc);
 787         }
 788 
 789         case PIO_FONT:
 790                 if (!suser())
 791                         return -EPERM;
 792                 return con_set_font((char *)arg);
 793                 /* con_set_font() defined in console.c */
 794 
 795         case GIO_FONT:
 796                 return con_get_font((char *)arg);
 797                 /* con_get_font() defined in console.c */
 798 
 799         case PIO_SCRNMAP:
 800                 if (!suser())
 801                         return -EPERM;
 802                 return con_set_trans((char *)arg);
 803                 /* con_set_trans() defined in console.c */
 804 
 805         case GIO_SCRNMAP:
 806                 return con_get_trans((char *)arg);
 807                 /* con_get_trans() defined in console.c */
 808 
 809         default:
 810                 return -ENOIOCTLCMD;
 811         }
 812 }

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