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

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