/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/sysmacros.h>
#include <sys/vtdaemon.h>
#include <sys/strredir.h>
#include <sys/polled_io.h>
#include <sys/ddi_impldefs.h>
#include <sys/consconfig_dacf.h>
/*
* This file belongs to wc STREAMS module which has a D_MTPERMODE
* inner perimeter. See "Locking Policy" comment in wscons.c for
* more information.
*/
/*
* Minor name device file Hotkeys
*
*
* ......
*
* which is not available to end users.
*
*/
extern boolean_t consconfig_console_is_tipline(void);
/*
* not being used.
* For other VT, if it is opened and tty is initialized, consider it
* as being used.
*/
(id != 0 || !consconfig_console_is_tipline()))
/*
* the vt switching message is encoded as:
*
* -------------------------------------------------------------
* | \033 | 'Q' | vtno + 'A' | opcode | 'z' | '\0' |
* -------------------------------------------------------------
*/
static void
{
int len;
/*
* Get the default termios settings (cflag).
* These are stored as a property in the
* "options" node.
*/
ddi_root_node(), 0, "ttymodes",
else
"wc: Couldn't get ttymodes property!");
} else {
/*
* Gack! Whine about it.
*/
"wc: Couldn't get ttymodes property!");
}
}
static int
{
return (ENOTSUP);
/* one for system console, one for vtdaemon */
if (count < 2)
return (ENXIO);
/*
* Shouldn't allow to shrink the max vt minor to be smaller than
* the max in used minor.
*/
if (count <= vc_inuse_max_minor)
return (EBUSY);
return (0);
}
void
{
if (pvc->vc_bufcallid != 0) {
pvc->vc_bufcallid = 0;
}
if (pvc->vc_timeoutid != 0) {
pvc->vc_timeoutid = 0;
}
}
/*
* Reply the VT_WAITACTIVE ioctl.
* Argument 'close' usage:
* B_TRUE: the vt designated by argument 'minor' is being closed.
* B_FALSE: the vt designated by argument 'minor' has been activated just now.
*/
static void
{
if (close)
else
}
}
}
void
{
if (index == vc_inuse_max_minor) {
;
}
}
static void
{
}
/*
* ......
*
*
* The system console (minor 0), is opened firstly and used during console
* configuration. It also acts as the system hard console even when all
* virtual consoles go off.
*
* And the system console is redirected to the tipline. During normal cases,
* we can switch from virtual consoles to it by pressing 'Alt + F1'.
*
* not available to end users.
*
* During early console configuration, consconfig_dacf opens wscons and then
* issue a WC_OPEN_FB ioctl to kick off terminal init process. So during
* consconfig_dacf first opening of wscons, tems (of type tem_state_t) is
* not initialized. We do not initialize the tem_vt_state_t instance returned
* by tem_init() for this open, since we do not have enough info to handle
* normal terminal operation at this moment. This tem_vt_state_t instance
* will get initialized when handling WC_OPEN_FB.
*/
int
{
if (!vt_minor_valid(minor))
return (ENXIO);
return (ENXIO);
/*
* vc_tem might not be intialized if !tems.ts_initialized,
* and this only happens during console configuration.
*/
}
/*
* In normal case, the first screen is the system console;
* In tipline case, the first screen is the first VT that gets started.
*/
if (minor != 0) {
/*
* If we are not opening the system console
* as the first console, clear the phyical
* screen.
*/
}
}
(secpolicy_excl_open(crp) != 0)) {
return (EBUSY);
}
if (minor > vc_inuse_max_minor)
return (0);
}
static minor_t
{
if (!VT_IS_DAEMON(t) && VT_IS_INUSE(t))
return (t);
return (VT_MINOR_INVALID);
}
static minor_t
{
if (!VT_IS_DAEMON(t) && VT_IS_INUSE(t))
return (t);
return (VT_MINOR_INVALID);
}
/* ARGSUSED */
void
{
int error = 0;
int retries = 0;
/* only available in kernel context or user context */
vt_pending_vtno = -1;
return;
}
/*
* Make door upcall
*/
retries++;
else
break;
vt_pending_vtno = -1;
}
static boolean_t
{
/*
* minor should not succeed the existing minor numbers range.
*/
if (!vt_minor_valid(minor))
return (B_FALSE);
/*
*/
return (B_TRUE);
return (B_FALSE);
}
static void
{
if (vt_pending_vtno != -1) {
return;
}
}
/*
* return value:
* 0: non msg of vt hotkeys
* 1: msg of vt hotkeys
*/
int
{
int vtno = 0;
/* LINTED E_PTRDIFF_OVERFLOW */
if (!VT_MSG_SWITCH(mp))
return (0);
switch (VT_MSG_OPCODE(mp)) {
case 'B':
/* find out the previous vt */
if (vc_active_console == VT_MINOR_INVALID)
return (1);
if (VT_IS_DAEMON(vc_active_console)) {
break;
}
break;
case 'F':
/* find out the next vt */
if (vc_active_console == VT_MINOR_INVALID)
return (1);
if (VT_IS_DAEMON(vc_active_console)) {
break;
}
break;
case 'H':
/* find out the specified vt */
/* check for system console, Alt + F1 */
if (minor == 1)
minor = 0;
break;
case 'L':
/* find out the last vt */
return (1);
break;
default:
return (1);
}
if (!vt_validate_hotkeys(minor))
return (1);
/*
* for system console, the argument of vtno for
* vt_activate is 1, though its minor is 0
*/
if (minor == 0)
else
return (1);
}
static void
{
register proc_t *p;
if (pid <= 0)
return;
return;
}
}
static int
{
register proc_t *p;
if (pid <= 0)
return (EINVAL);
return (ESRCH);
}
return (0);
}
static int
{
return (EINVAL);
return (EINVAL);
} else {
pvc->vc_dispnum = 0;
}
return (0);
}
static void
{
pvc->vc_dispnum = 0;
}
/*
* switch to vt_no from vc_active_console
*/
static int
{
/* sanity test for the target VT and the active VT */
return (EINVAL);
return (EINVAL);
if (!VT_IS_DAEMON(vc_active_console))
else
/* send it an acquired signal */
}
if (!VT_IS_DAEMON(vt_no)) {
/*
* Applications that open the virtual console device may request
* asynchronous notification of VT switching from a previous VT
* to another one by setting the S_MSG flag in an I_SETSIG
* STREAMS ioctl. Such processes receive a SIGPOLL signal when
* a VT switching succeeds.
*/
}
}
}
return (0);
}
/*
* vt_no from 0 to n
*
* 0 for the vtdaemon sepcial console (only vtdaemon will use it)
* 1 for the system console (Alt + F1, or Alt + Ctrl + F1),
* aka Virtual Console #1
*
* 2 for Virtual Console #2
* n for Virtual Console #n
*/
static minor_t
{
if (arg == 0)
return (1);
if (arg == 1)
return (0);
return (arg);
}
static uint_t
{
if (minor == 0)
return (1);
if (VT_IS_DAEMON(minor)) {
/* here it should be the real console */
return (vc_target_console);
}
return (minor);
}
static int
{
if (!vt_minor_valid(minor))
return (ENXIO);
if (minor == vc_active_console) {
if (VT_IS_DAEMON(minor)) {
/*
* vtdaemon is reactivating itself to do locking
* on behalf of another console, so record current
* target console as the last console.
*/
}
return (0);
}
/*
* In tipline case, the system console is redirected to tipline
* and thus is always available.
*/
if (minor == 0 && consconfig_console_is_tipline())
return (0);
if (!VT_IS_INUSE(minor))
return (ENXIO);
return (ENXIO);
return (ENXIO);
return (ENXIO);
/*
* Validate the process, reset the
* vt to auto mode if failed.
*/
/*
* Xserver has not started up yet,
* or it dose not exist.
*/
return (0);
}
/*
* Send the release signal to the process,
* and wait VT_RELDISP ioctl from Xserver
* after its leaving VT.
*/
/*
* We don't need a timeout here, for if Xserver refuses
* or fails to respond to release signal using VT_RELDISP,
* we cannot successfully switch to our text mode. Actually
* users can try again. At present we don't support force
* switch.
*/
return (0);
}
static int
{
return (EACCES);
if (target_vtno == VT_MINOR_INVALID)
return (EINVAL);
return (0);
if (arg == 0)
return (0); /* refuse to release */
/* Xserver has left VT */
}
void
{
int minor;
int arg;
int error = 0;
return;
}
case VT_ENABLED:
break;
}
return;
case KDSETMODE:
break;
}
break;
break;
case KDGETMODE:
break;
}
return;
case VT_OPENQRY: /* return number of first free VT */
break;
}
/* minors of 0 and 1 are not available to end users */
if (!VT_IS_INUSE(minor))
break;
if (!vt_minor_valid(minor))
minor = -1;
return;
case VT_GETMODE:
break;
}
return;
case VT_SETMODE:
return;
case VT_SETDISPINFO:
/* always enforce sys_devices privilege for setdispinfo */
break;
break;
case VT_SETDISPLOGIN:
break;
case VT_GETDISPINFO:
break;
}
return;
case VT_RELDISP:
break;
case VT_CONFIG:
/* always enforce sys_devices privilege for config */
break;
break;
case VT_ACTIVATE:
/* always enforce sys_devices privilege for secure switch */
break;
break;
case VT_WAITACTIVE:
if (!vt_minor_valid(arg)) {
break;
}
if (arg == vc_active_console)
break;
break;
}
return;
case VT_GETSTATE:
/*
* Here v_active is the argument for vt_activate,
* not minor.
*/
/* we only support 16 vt states since the v_state is short */
break;
if (VT_IS_INUSE(minor))
}
break;
}
return;
case VT_SET_TARGET:
/* always enforce sys_devices privilege */
break;
/* vtdaemon is doing authentication for this target console */
break;
case VT_GETACTIVE: /* get real active console (minor) */
break;
}
return;
case VT_GET_CONSUSER:
break;
}
if (vc_cons_user == VT_MINOR_INVALID) {
/*
* Return -1 if console user link points to
*/
} else {
}
return;
case VT_RESET_CONSUSER:
/* always enforce sys_devices privilege */
break;
break;
}
break;
case VT_SET_CONSUSER:
/* always enforce sys_devices privilege */
break;
break;
default:
break;
}
if (error != 0)
else
}
void
{
int error = 0;
return;
}
case VT_SETMODE:
break;
case KDGETMODE:
case VT_OPENQRY:
case VT_GETMODE:
case VT_GETDISPINFO:
case VT_GETSTATE:
case VT_ENABLED:
case VT_GETACTIVE:
break;
default:
break;
}
if (error != 0)
else
}
static void
{
}
}
static void
{
}
}
static void
{
}
static void
{
}
/*
* Get vc state from minor.
* Once a caller gets a vc_state_t from this function,
* the vc_state_t is guaranteed not being freed before
* the caller leaves this STREAMS module by the D_MTPERMOD
* perimeter.
*/
{
}
if (vc_active_console == VT_MINOR_INVALID)
else
}
static void
{
vcptr->vc_dispnum = 0;
vcptr->vc_bufcallid = 0;
vcptr->vc_timeoutid = 0;
}
void
{
return;
KM_SLEEP);
vt_state_init(vcptr, i);
}
return;
}
}
}
static int
{
return (-1);
return (0);
return (1);
}
/*
* Only called from wc init().
*/
void
vt_init(void)
{
#ifdef __lock_lint
#endif
}