📄 vt.c
字号:
return i; get_user(ll, &vtsizes->v_rows); get_user(cc, &vtsizes->v_cols); return vc_resize_all(ll, cc); } case VT_RESIZEX: { struct vt_consize *vtconsize = (struct vt_consize *) arg; ushort ll,cc,vlin,clin,vcol,ccol; if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize)); if (i) return i; get_user(ll, &vtconsize->v_rows); get_user(cc, &vtconsize->v_cols); get_user(vlin, &vtconsize->v_vlin); get_user(clin, &vtconsize->v_clin); get_user(vcol, &vtconsize->v_vcol); get_user(ccol, &vtconsize->v_ccol); vlin = vlin ? vlin : video_scan_lines; if ( clin ) { if ( ll ) { if ( ll != vlin/clin ) return -EINVAL; /* Parameters don't add up */ } else ll = vlin/clin; } if ( vcol && ccol ) { if ( cc ) { if ( cc != vcol/ccol ) return -EINVAL; } else cc = vcol/ccol; } if ( clin > 32 ) return -EINVAL; if ( vlin ) video_scan_lines = vlin; if ( clin ) video_font_height = clin; return vc_resize_all(ll, cc); } case PIO_FONT: { struct console_font_op op; if (!perm) return -EPERM; op.op = KD_FONT_OP_SET; op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ op.width = 8; op.height = 0; op.charcount = 256; op.data = (char *) arg; return con_font_op(fg_console, &op); } case GIO_FONT: { struct console_font_op op; op.op = KD_FONT_OP_GET; op.flags = KD_FONT_FLAG_OLD; op.width = 8; op.height = 32; op.charcount = 256; op.data = (char *) arg; return con_font_op(fg_console, &op); } case PIO_CMAP: if (!perm) return -EPERM; return con_set_cmap((char *)arg); case GIO_CMAP: return con_get_cmap((char *)arg); case PIO_FONTX: case GIO_FONTX: return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm); case PIO_FONTRESET: { if (!perm) return -EPERM;#ifdef BROKEN_GRAPHICS_PROGRAMS /* With BROKEN_GRAPHICS_PROGRAMS defined, the default font is not saved. */ return -ENOSYS;#else { struct console_font_op op; op.op = KD_FONT_OP_SET_DEFAULT; op.data = NULL; i = con_font_op(fg_console, &op); if (i) return i; con_set_default_unimap(fg_console); return 0; }#endif } case KDFONTOP: { struct console_font_op op; if (copy_from_user(&op, (void *) arg, sizeof(op))) return -EFAULT; if (!perm && op.op != KD_FONT_OP_GET) return -EPERM; i = con_font_op(console, &op); if (i) return i; if (copy_to_user((void *) arg, &op, sizeof(op))) return -EFAULT; return 0; } case PIO_SCRNMAP: if (!perm) return -EPERM; return con_set_trans_old((unsigned char *)arg); case GIO_SCRNMAP: return con_get_trans_old((unsigned char *)arg); case PIO_UNISCRNMAP: if (!perm) return -EPERM; return con_set_trans_new((unsigned short *)arg); case GIO_UNISCRNMAP: return con_get_trans_new((unsigned short *)arg); case PIO_UNIMAPCLR: { struct unimapinit ui; if (!perm) return -EPERM; i = copy_from_user(&ui, (void *)arg, sizeof(struct unimapinit)); if (i) return -EFAULT; con_clear_unimap(fg_console, &ui); return 0; } case PIO_UNIMAP: case GIO_UNIMAP: return do_unimap_ioctl(cmd, (struct unimapdesc *)arg, perm); case VT_LOCKSWITCH: if (!suser()) return -EPERM; vt_dont_switch = 1; return 0; case VT_UNLOCKSWITCH: if (!suser()) return -EPERM; vt_dont_switch = 0; return 0;#ifdef CONFIG_FB_COMPAT_XPMAC case VC_GETMODE: { struct vc_mode mode; i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct vc_mode)); if (i == 0) i = console_getmode(&mode); if (i) return i; if (copy_to_user((void *) arg, &mode, sizeof(mode))) return -EFAULT; return 0; } case VC_SETMODE: case VC_INQMODE: { struct vc_mode mode; if (!perm) return -EPERM; i = verify_area(VERIFY_READ, (void *) arg, sizeof(struct vc_mode)); if (i) return i; if (copy_from_user(&mode, (void *) arg, sizeof(mode))) return -EFAULT; return console_setmode(&mode, cmd == VC_SETMODE); } case VC_SETCMAP: { unsigned char cmap[3][256], *p; int n_entries, cmap_size, i, j; if (!perm) return -EPERM; if (arg == (unsigned long) VC_POWERMODE_INQUIRY || arg <= VESA_POWERDOWN) { /* compatibility hack: VC_POWERMODE was changed from 0x766a to 0x766c */ return console_powermode((int) arg); } i = verify_area(VERIFY_READ, (void *) arg, sizeof(int)); if (i) return i; if (get_user(cmap_size, (int *) arg)) return -EFAULT; if (cmap_size % 3) return -EINVAL; n_entries = cmap_size / 3; if ((unsigned) n_entries > 256) return -EINVAL; p = (unsigned char *) (arg + sizeof(int)); for (j = 0; j < n_entries; ++j) for (i = 0; i < 3; ++i) if (get_user(cmap[i][j], p++)) return -EFAULT; return console_setcmap(n_entries, cmap[0], cmap[1], cmap[2]); } case VC_GETCMAP: /* not implemented yet */ return -ENOIOCTLCMD; case VC_POWERMODE: if (!perm) return -EPERM; return console_powermode((int) arg);#endif /* CONFIG_FB_COMPAT_XPMAC */ default: return -ENOIOCTLCMD; }}/* * Sometimes we want to wait until a particular VT has been activated. We * do it in a very simple manner. Everybody waits on a single queue and * get woken up at once. Those that are satisfied go on with their business, * while those not ready go back to sleep. Seems overkill to add a wait * to each vt just for this - usually this does nothing! */static struct wait_queue *vt_activate_queue = NULL;/* * Sleeps until a vt is activated, or the task is interrupted. Returns * 0 if activation, -EINTR if interrupted. */int vt_waitactive(int vt){ int retval; struct wait_queue wait = { current, NULL }; add_wait_queue(&vt_activate_queue, &wait); for (;;) { current->state = TASK_INTERRUPTIBLE; retval = 0; if (vt == fg_console) break; retval = -EINTR; if (signal_pending(current)) break; schedule(); } remove_wait_queue(&vt_activate_queue, &wait); current->state = TASK_RUNNING; return retval;}#define vt_wake_waitactive() wake_up(&vt_activate_queue)void reset_vc(unsigned int new_console){ vt_cons[new_console]->vc_mode = KD_TEXT; kbd_table[new_console].kbdmode = VC_XLATE; vt_cons[new_console]->vt_mode.mode = VT_AUTO; vt_cons[new_console]->vt_mode.waitv = 0; vt_cons[new_console]->vt_mode.relsig = 0; vt_cons[new_console]->vt_mode.acqsig = 0; vt_cons[new_console]->vt_mode.frsig = 0; vt_cons[new_console]->vt_pid = -1; vt_cons[new_console]->vt_newvt = -1; reset_palette (new_console) ;}/* * Performs the back end of a vt switch */void complete_change_console(unsigned int new_console){ unsigned char old_vc_mode; last_console = fg_console; /* * If we're switching, we could be going from KD_GRAPHICS to * KD_TEXT mode or vice versa, which means we need to blank or * unblank the screen later. */ old_vc_mode = vt_cons[fg_console]->vc_mode; switch_screen(new_console); /* * If this new console is under process control, send it a signal * telling it that it has acquired. Also check if it has died and * clean up (similar to logic employed in change_console()) */ if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ if (kill_proc(vt_cons[new_console]->vt_pid, vt_cons[new_console]->vt_mode.acqsig, 1) != 0) { /* * The controlling process has died, so we revert back to * normal operation. In this case, we'll also change back * to KD_TEXT mode. I'm not sure if this is strictly correct * but it saves the agony when the X server dies and the screen * remains blanked due to KD_GRAPHICS! It would be nice to do * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ reset_vc(new_console); } } /* * We do this here because the controlling process above may have * gone, and so there is now a new vc_mode */ if (old_vc_mode != vt_cons[new_console]->vc_mode) { if (vt_cons[new_console]->vc_mode == KD_TEXT) unblank_screen(); else do_blank_screen(1); } /* * Wake anyone waiting for their VT to activate */ vt_wake_waitactive(); return;}/* * Performs the front-end of a vt switch */void change_console(unsigned int new_console){ if ((new_console == fg_console) || (vt_dont_switch)) return; if (!vc_cons_allocated(new_console)) return; /* * If this vt is in process mode, then we need to handshake with * that process before switching. Essentially, we store where that * vt wants to switch to and wait for it to tell us when it's done * (via VT_RELDISP ioctl). * * We also check to see if the controlling process still exists. * If it doesn't, we reset this vt to auto mode and continue. * This is a cheap way to track process control. The worst thing * that can happen is: we send a signal to a process, it dies, and * the switch gets "lost" waiting for a response; hopefully, the * user will try again, we'll detect the process is gone (unless * the user waits just the right amount of time :-) and revert the * vt to auto control. */ if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ if (kill_proc(vt_cons[fg_console]->vt_pid, vt_cons[fg_console]->vt_mode.relsig, 1) == 0) { /* * It worked. Mark the vt to switch to and * return. The process needs to send us a * VT_RELDISP ioctl to complete the switch. */ vt_cons[fg_console]->vt_newvt = new_console; return; } /* * The controlling process has died, so we revert back to * normal operation. In this case, we'll also change back * to KD_TEXT mode. I'm not sure if this is strictly correct * but it saves the agony when the X server dies and the screen * remains blanked due to KD_GRAPHICS! It would be nice to do * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ reset_vc(fg_console); /* * Fall through to normal (VT_AUTO) handling of the switch... */ } /* * Ignore all switches in KD_GRAPHICS+VT_AUTO mode */ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; complete_change_console(new_console);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -