void vt_event_post(unsignedint event, unsignedint old, unsignedintnew)
{ struct list_head *pos, *head; unsignedlong flags; int wake = 0;
spin_lock_irqsave(&vt_event_lock, flags);
head = &vt_events;
list_for_each(pos, head) { struct vt_event_wait *ve = list_entry(pos, struct vt_event_wait, list); if (!(ve->event.event & event)) continue;
ve->event.event = event; /* kernel view is consoles 0..n-1, user space view is
console 1..n with 0 meaning current, so we must bias */
ve->event.oldev = old + 1;
ve->event.newev = new + 1;
wake = 1;
ve->done = 1;
}
spin_unlock_irqrestore(&vt_event_lock, flags); if (wake)
wake_up_interruptible(&vt_event_waitqueue);
}
if (copy_from_user(&vw.event, event, sizeof(struct vt_event))) return -EFAULT; /* Highest supported event for now */ if (vw.event.event & ~VT_MAX_EVENT) return -EINVAL;
vt_event_wait(&vw); /* If it occurred report it */ if (vw.done) { if (copy_to_user(event, &vw.event, sizeof(struct vt_event))) return -EFAULT; return0;
} return -EINTR;
}
case KDENABIO: case KDDISABIO: return ksys_ioperm(GPFIRST, GPNUM,
(cmd == KDENABIO)) ? -ENXIO : 0; #endif
/* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
case KDKBDREP:
{ struct kbd_repeat kbrep;
if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM;
if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) return -EFAULT;
ret = kbd_rate(&kbrep); if (ret) return ret; if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) return -EFAULT; break;
}
case KDSETMODE: if (!perm) return -EPERM;
console_lock();
ret = vt_kdsetmode(vc, arg);
console_unlock(); return ret;
case KDGETMODE: return put_user(vc->vc_mode, (int __user *)arg);
case KDMAPDISP: case KDUNMAPDISP: /* *theseworklikeacombinationofmmapandKDENABIO. *thiscouldbeeasilyfinished.
*/ return -EINVAL;
case KDSKBMODE: if (!perm) return -EPERM;
ret = vt_do_kdskbmode(console, arg); if (ret) return ret;
tty_ldisc_flush(tty); break;
case KDGKBMODE: return put_user(vt_do_kdgkbmode(console), (int __user *)arg);
/* this could be folded into KDSKBMODE, but for compatibility
reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ case KDSKBMETA: return vt_do_kdskbmeta(console, arg);
case KDGKBMETA: /* FIXME: should review whether this is worth locking */ return put_user(vt_do_kdgkbmeta(console), (int __user *)arg);
case KDGETKEYCODE: case KDSETKEYCODE: if(!capable(CAP_SYS_TTY_CONFIG))
perm = 0; return vt_do_kbkeycode_ioctl(cmd, up, perm);
case KDGKBENT: case KDSKBENT: return vt_do_kdsk_ioctl(cmd, up, perm, console);
case KDGKBSENT: case KDSKBSENT: return vt_do_kdgkb_ioctl(cmd, up, perm);
/* Diacritical processing. Handled in keyboard.c as it has
to operate on the keyboard locks and structures */ case KDGKBDIACR: case KDGKBDIACRUC: case KDSKBDIACR: case KDSKBDIACRUC: return vt_do_diacrit(cmd, up, perm);
/* the ioctls below read/set the flags usually shown in the leds */ /* don't use them - they will go away without warning */ case KDGKBLED: case KDSKBLED: case KDGETLED: case KDSETLED: return vt_do_kdskled(console, cmd, arg, perm);
/* *Aprocesscanindicateitswillingnesstoacceptsignals *generatedbypressinganappropriatekeycombination. *Thus,onecanhaveadaemonthate.g.spawnsanewconsole *uponakeypressandthenchangestoit. *Seealsothekbrequestfieldofinittab(5).
*/ case KDSIGACCEPT: if (!perm || !capable(CAP_KILL)) return -EPERM; if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) return -EINVAL;
case PIO_SCRNMAP: if (!perm) return -EPERM; return con_set_trans_old(up);
case GIO_SCRNMAP: return con_get_trans_old(up);
case PIO_UNISCRNMAP: if (!perm) return -EPERM; return con_set_trans_new(up);
case GIO_UNISCRNMAP: return con_get_trans_new(up);
case PIO_UNIMAPCLR: if (!perm) return -EPERM;
con_clear_unimap(vc); break;
case PIO_UNIMAP: case GIO_UNIMAP: return do_unimap_ioctl(cmd, up, perm, vc);
default: return -ENOIOCTLCMD;
}
return0;
}
staticint vt_reldisp(struct vc_data *vc, unsignedint swtch)
{ int newvt, ret;
if (vc->vt_mode.mode != VT_PROCESS) return -EINVAL;
/* Switched-to response */ if (vc->vt_newvt < 0) { /* If it's just an ACK, ignore it */ return swtch == VT_ACKACQ ? 0 : -EINVAL;
}
/* Switching-from response */ if (swtch == 0) { /* Switch disallowed, so forget we were trying to do it. */
vc->vt_newvt = -1; return0;
}
/* The current vt has been released, so complete the switch. */
newvt = vc->vt_newvt;
vc->vt_newvt = -1;
ret = vc_allocate(newvt); if (ret) return ret;
if (copy_from_user(&v, cs, sizeof(struct vt_consize))) return -EFAULT;
/* FIXME: Should check the copies properly */ if (!v.v_vlin)
v.v_vlin = vc->vc_scan_lines;
if (v.v_clin) { int rows = v.v_vlin / v.v_clin; if (v.v_rows != rows) { if (v.v_rows) /* Parameters don't add up */ return -EINVAL;
v.v_rows = rows;
}
}
if (v.v_vcol && v.v_ccol) { int cols = v.v_vcol / v.v_ccol; if (v.v_cols != cols) { if (v.v_cols) return -EINVAL;
v.v_cols = cols;
}
}
if (v.v_clin > 32) return -EINVAL;
for (i = 0; i < MAX_NR_CONSOLES; i++) { struct vc_data *vcp;
if (!vc_cons[i].d) continue;
console_lock();
vcp = vc_cons[i].d; if (vcp) { int ret; int save_scan_lines = vcp->vc_scan_lines; int save_cell_height = vcp->vc_cell_height;
if (v.v_vlin)
vcp->vc_scan_lines = v.v_vlin; if (v.v_clin)
vcp->vc_cell_height = v.v_clin;
ret = __vc_resize(vcp, v.v_cols, v.v_rows, true); if (ret) {
vcp->vc_scan_lines = save_scan_lines;
vcp->vc_cell_height = save_cell_height;
console_unlock(); return ret;
}
}
console_unlock();
}
return0;
}
/* *Wehandletheconsole-specificioctl'shere.Weallowthe *capabilitytomodifyanyconsole,notjustthefg_console.
*/ int vt_ioctl(struct tty_struct *tty, unsignedint cmd, unsignedlong arg)
{ struct vc_data *vc = tty->driver_data; void __user *up = (void __user *)arg; int i, perm; int ret;
ret = vt_k_ioctl(tty, cmd, arg, perm); if (ret != -ENOIOCTLCMD) return ret;
ret = vt_io_ioctl(vc, cmd, up, perm); if (ret != -ENOIOCTLCMD) return ret;
switch (cmd) { case TIOCLINUX: return tioclinux(tty, arg); case VT_SETMODE:
{ struct vt_mode tmp;
if (!perm) return -EPERM; if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) return -EFAULT; if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) return -EINVAL;
console_lock();
vc->vt_mode = tmp; /* the frsig is ignored, so we set it to 0 */
vc->vt_mode.frsig = 0;
put_pid(vc->vt_pid);
vc->vt_pid = get_pid(task_pid(current)); /* no switch is required -- saw@shade.msu.ru */
vc->vt_newvt = -1;
console_unlock(); break;
}
if (put_user(fg_console + 1, &vtstat->v_active)) return -EFAULT;
state = 1; /* /dev/tty0 is always open */
console_lock(); /* required by vt_in_use() */ for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
++i, mask <<= 1) if (vt_in_use(i))
state |= mask;
console_unlock(); return put_user(state, &vtstat->v_state);
}
/* *Returnsthefirstavailable(non-opened)console.
*/ case VT_OPENQRY:
console_lock(); /* required by vt_in_use() */ for (i = 0; i < MAX_NR_CONSOLES; ++i) if (!vt_in_use(i)) break;
console_unlock();
i = i < MAX_NR_CONSOLES ? (i+1) : -1; return put_user(i, (int __user *)arg);
/* *ioctl(fd,VT_ACTIVATE,num)willcauseustoswitchtovt#num, *withnum>=1(switchestovt0,ourconsole,arenotallowed,just *topreservesanity).
*/ case VT_ACTIVATE: if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO;
arg--;
arg = array_index_nospec(arg, MAX_NR_CONSOLES);
console_lock();
ret = vc_allocate(arg);
console_unlock(); if (ret) return ret;
set_console(arg); break;
case VT_SETACTIVATE: if (!perm) return -EPERM;
return vt_setactivate(up);
/* *waituntilthespecifiedVThasbeenactivated
*/ case VT_WAITACTIVE: if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; return vt_waitactive(arg);
/* *Ifavtisunderprocesscontrol,thekernelwillnotswitchtoit *immediately,butpostponetheoperationuntiltheprocesscallsthis *ioctl,allowingtheswitchtocomplete. * *AccordingtotheXsourcesthisisthebehavior: *0:pendingswitch-fromnotOK *1:pendingswitch-fromOK *2:completedswitch-toOK
*/ case VT_RELDISP: if (!perm) return -EPERM;
console_lock();
ret = vt_reldisp(vc, arg);
console_unlock();
return ret;
/* *DisallocatememoryassociatedtoVT(butleaveVT1)
*/ case VT_DISALLOCATE: if (arg > MAX_NR_CONSOLES) return -ENXIO;
case KDFONTOP: return compat_kdfontop_ioctl(up, perm, &op, vc);
case PIO_UNIMAP: case GIO_UNIMAP: return compat_unimap_ioctl(cmd, up, perm, vc);
/* *allthesetreat'arg'asaninteger
*/ case KIOCSOUND: case KDMKTONE: #ifdef CONFIG_X86 case KDADDIO: case KDDELIO: #endif case KDSETMODE: case KDMAPDISP: case KDUNMAPDISP: case KDSKBMODE: case KDSKBMETA: case KDSKBLED: case KDSETLED: case KDSIGACCEPT: case VT_ACTIVATE: case VT_WAITACTIVE: case VT_RELDISP: case VT_DISALLOCATE: return vt_ioctl(tty, cmd, arg);
/* *IgnoreallswitchesinKD_GRAPHICS+VT_AUTOmode
*/ if (vc->vc_mode == KD_GRAPHICS) return;
complete_change_console(new_vc);
}
/* Perform a kernel triggered VT switch for suspend/resume */
staticint disable_vt_switch;
int vt_move_to_console(unsignedint vt, int alloc)
{ int prev;
console_lock(); /* Graphics mode - up to X */ if (disable_vt_switch) {
console_unlock(); return0;
}
prev = fg_console;
if (alloc && vc_allocate(vt)) { /* we can't have a free VC for now. Too bad,
* we don't want to mess the screen for now. */
console_unlock(); return -ENOSPC;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.