360 lines
9.3 KiB
C
360 lines
9.3 KiB
C
/* $XdotOrg$ */
|
|
/*
|
|
* Copyright 2001-2005 by Kean Johnston <jkj@sco.com>
|
|
* Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
|
|
* Copyright 1993 by David Wexelblat <dwex@goblin.org>
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the names of Thomas Roell, David Wexelblat
|
|
* and Kean Johnston not be used in advertising or publicity pertaining to
|
|
* distribution of the software without specific, written prior permission.
|
|
* Thomas Roell, David Wexelblat and Kean Johnston make no representations
|
|
* about the suitability of this software for any purpose. It is provided
|
|
* "as is" without express or implied warranty.
|
|
*
|
|
* THOMAS ROELL, DAVID WEXELBLAT AND KEAN JOHNSTON DISCLAIM ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THOMAS ROELLm DAVID WEXELBLAT
|
|
* OR KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
* THIS SOFTWARE.
|
|
*
|
|
*/
|
|
/* $XConsortium$ */
|
|
|
|
#include "X.h"
|
|
#include "Xmd.h"
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "xf86.h"
|
|
#include "xf86Priv.h"
|
|
#include "xf86_OSlib.h"
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
static Bool KeepTty = FALSE;
|
|
static Bool Protect0 = FALSE;
|
|
static Bool CRTSpecified = FALSE;
|
|
static int VTnum = -1;
|
|
static char vtdevice[48];
|
|
|
|
int usl_is_osr6 = -1;
|
|
|
|
static Bool
|
|
IsConsoleDevice(const char *dev)
|
|
{
|
|
if ((!strcmp (dev, "/dev/console")) ||
|
|
(!strcmp (dev, "/dev/syscon")) ||
|
|
(!strcmp (dev, "/dev/systty")))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int
|
|
is_osr6 (void)
|
|
{
|
|
struct utsname uts;
|
|
|
|
if (usl_is_osr6 == -1) {
|
|
if (uname (&uts) < 0) {
|
|
FatalError ("get_usl_ver: Failed to determine UNIX name (%s)\n",
|
|
strerror (errno));
|
|
}
|
|
|
|
if (uts.version[0] == '6')
|
|
usl_is_osr6 = 1;
|
|
else
|
|
usl_is_osr6 = 0;
|
|
}
|
|
|
|
return usl_is_osr6;
|
|
}
|
|
|
|
|
|
void
|
|
xf86OpenConsole(void)
|
|
{
|
|
int fd, i, ioctl_ret;
|
|
struct vt_mode VT;
|
|
struct vt_stat vts;
|
|
MessageType from = X_PROBED;
|
|
struct sigaction sigvtsw;
|
|
char *ttn;
|
|
|
|
if (serverGeneration == 1) {
|
|
int isconsole = 0, consdev = 0;
|
|
|
|
/* check if we're run with euid==0 */
|
|
if (geteuid() != 0) {
|
|
FatalError("xf86OpenConsole: Server must be suid root\n");
|
|
}
|
|
|
|
/* If we are run in the background we will get SIGTTOU. Ignore it. */
|
|
OsSignal (SIGTTOU, SIG_IGN);
|
|
|
|
/* Protect page 0 to help find NULL dereferencing */
|
|
/* mprotect() doesn't seem to work */
|
|
if (Protect0) {
|
|
int fd = -1;
|
|
|
|
if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0) {
|
|
xf86Msg(X_WARNING, "xf86OpenConsole: cannot open /dev/zero (%s)\n",
|
|
strerror(errno));
|
|
} else {
|
|
if ((int)mmap(0, 0x1000, PROT_NONE,
|
|
MAP_FIXED | MAP_SHARED, fd, 0) == -1) {
|
|
xf86Msg(X_WARNING, "xf86OpenConsole: failed to protect page 0 (%s)\n",
|
|
strerror(errno));
|
|
}
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* setup the virtual terminal manager
|
|
*/
|
|
if (VTnum == -1) {
|
|
/*
|
|
* No device was specified. We need to query the kernel to see which
|
|
* console device we are on (and in fact if we are on a console at all).
|
|
*/
|
|
if (ioctl (0, VT_GETSTATE, &vts) < 0) {
|
|
FatalError("xf86OpenConsole: Could not query active VT: %s\n",
|
|
strerror(errno));
|
|
}
|
|
VTnum = vts.v_active;
|
|
if (is_osr6())
|
|
snprintf (vtdevice, sizeof(vtdevice), "/dev/tty%02d", VTnum + 1);
|
|
else
|
|
snprintf (vtdevice, sizeof(vtdevice), "/dev/vt%02d", VTnum);
|
|
} else {
|
|
from = X_CMDLINE;
|
|
if (is_osr6())
|
|
snprintf (vtdevice, sizeof(vtdevice), "/dev/tty%02d", VTnum + 1);
|
|
else
|
|
snprintf (vtdevice, sizeof(vtdevice), "/dev/vt%02d", VTnum);
|
|
}
|
|
|
|
if (IsConsoleDevice(vtdevice)) {
|
|
isconsole = 1;
|
|
CRTSpecified = FALSE; /* Dont honour -crt /dev/console */
|
|
}
|
|
|
|
if (ioctl (0, KIOCINFO, 0) >= 0)
|
|
consdev = 1 + isconsole;
|
|
|
|
if ((!CRTSpecified) && (isconsole || (!consdev))) {
|
|
/*
|
|
* Need to find a free VT
|
|
*/
|
|
if ((fd = open ("/dev/console", O_WRONLY | O_NOCTTY)) < 0) {
|
|
FatalError ("xf86OpenConsole: Could not open /dev/console: %s\n",
|
|
strerror (errno));
|
|
}
|
|
|
|
if (ioctl (fd, VT_OPENQRY, &VTnum) < 0) {
|
|
FatalError ("xf86OpenConsole: Cannot find a free VT: %s\n",
|
|
strerror(errno));
|
|
}
|
|
close (fd);
|
|
if (usl_is_osr6)
|
|
snprintf (vtdevice, sizeof(vtdevice), "/dev/tty%02d", VTnum + 1);
|
|
else
|
|
snprintf (vtdevice, sizeof(vtdevice), "/dev/vt%02d", VTnum);
|
|
}
|
|
|
|
/*
|
|
* Now we can dispose of stdin/stdout
|
|
*/
|
|
fclose (stdin);
|
|
fclose (stdout);
|
|
|
|
if (CRTSpecified || isconsole || consdev != 1) {
|
|
if (!KeepTty) {
|
|
setpgrp();
|
|
}
|
|
}
|
|
|
|
if ((xf86Info.consoleFd = open(vtdevice, O_RDWR | O_NONBLOCK, 0)) < 0) {
|
|
FatalError("xf86OpenConsole: Cannot open %s: %s\n", vtdevice,
|
|
strerror(errno));
|
|
}
|
|
|
|
xf86Msg (from, "using VT number %d (%s)\n\n", VTnum, vtdevice);
|
|
xf86Info.vtno = VTnum;
|
|
|
|
/* change ownership of the vt */
|
|
chown(vtdevice, getuid(), getgid());
|
|
|
|
/*
|
|
* now get the VT
|
|
*/
|
|
if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) {
|
|
FatalError("xf86OpenConsole: VT_ACTIVATE failed: %s\n",
|
|
strerror(errno));
|
|
}
|
|
if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) {
|
|
FatalError("xf86OpenConsole: VT_WAITACTIVE failed: %s\n",strerror(errno));
|
|
}
|
|
|
|
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) {
|
|
FatalError("xf86OpenConsole: VT_GETMODE failed: %s\n", strerror(errno));
|
|
}
|
|
|
|
sigvtsw.sa_handler = xf86VTRequest;
|
|
sigfillset(&sigvtsw.sa_mask);
|
|
sigvtsw.sa_flags = 0;
|
|
sigaction(SIGUSR1, &sigvtsw, NULL);
|
|
|
|
VT.mode = VT_PROCESS;
|
|
VT.relsig = SIGUSR1;
|
|
VT.acqsig = SIGUSR1;
|
|
|
|
ioctl_ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
|
|
if (ioctl_ret < 0) {
|
|
FatalError("xf86OpenConsole: VT_SETMODE failed: %s\n", strerror(errno));
|
|
}
|
|
|
|
if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) {
|
|
FatalError("xf86OpenConsole: KD_GRAPHICS failed: %s\n", strerror(errno));
|
|
}
|
|
} else { /* serverGeneration != 1 */
|
|
/*
|
|
* now get the VT
|
|
*/
|
|
if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) {
|
|
FatalError("xf86OpenConsole: VT_ACTIVATE failed: %s\n", strerror(errno));
|
|
}
|
|
if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0) {
|
|
FatalError("xf86OpenConsole: VT_WAITACTIVE failed: %s\n",strerror(errno));
|
|
}
|
|
/*
|
|
* If the server doesn't have the VT when the reset occurs,
|
|
* this is to make sure we don't continue until the activate
|
|
* signal is received.
|
|
*/
|
|
if (!xf86Screens[0]->vtSema)
|
|
sleep(5);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
xf86CloseConsole(void)
|
|
{
|
|
struct vt_mode VT;
|
|
struct sigaction sigvtsw;
|
|
|
|
ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */
|
|
|
|
sigvtsw.sa_handler = SIG_DFL;
|
|
sigfillset(&sigvtsw.sa_mask);
|
|
sigvtsw.sa_flags = 0;
|
|
sigaction(SIGUSR1, &sigvtsw, NULL);
|
|
|
|
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) {
|
|
VT.mode = VT_AUTO;
|
|
VT.waitv = 0;
|
|
ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */
|
|
}
|
|
close(xf86Info.consoleFd); /* make the vt-manager happy */
|
|
return;
|
|
}
|
|
|
|
int
|
|
xf86ProcessArgument(int argc, char *argv[], int i)
|
|
{
|
|
/*
|
|
* Keep server from detaching from controlling tty. This is useful
|
|
* when debugging (so the server can receive keyboard signals.
|
|
*/
|
|
if (!strcmp(argv[i], "-keeptty")) {
|
|
KeepTty = TRUE;
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* Undocumented flag to protect page 0 from read/write to help
|
|
* catch NULL pointer dereferences. This is purely a debugging
|
|
* flag.
|
|
*/
|
|
if (!strcmp(argv[i], "-protect0")) {
|
|
Protect0 = TRUE;
|
|
return(1);
|
|
}
|
|
|
|
if ((argv[i][0] == 'v') && (argv[i][1] == 't')) {
|
|
if (sscanf(argv[i], "vt%2d", &VTnum) == 0) {
|
|
UseMsg();
|
|
VTnum = -1;
|
|
return(0);
|
|
}
|
|
VTnum -= is_osr6();
|
|
CRTSpecified = TRUE;
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* Use a device the user specifies.
|
|
*/
|
|
if (!strcmp(argv[i], "-crt")) {
|
|
if (++i > argc) {
|
|
UseMsg();
|
|
VTnum = -1;
|
|
return(0);
|
|
} else {
|
|
char *mytty = ttyname(0);
|
|
char *arg = argv[i];
|
|
|
|
if (!mytty)
|
|
mytty = "\1";
|
|
if (!arg[0])
|
|
arg = "\2"; /* Prevent idiots from using -crt "" */
|
|
|
|
if (strcmp (mytty, arg) != 0) {
|
|
char *fmt;
|
|
|
|
if (is_osr6())
|
|
fmt = "/dev/tty%02d";
|
|
else
|
|
fmt = "/dev/vt%02d";
|
|
|
|
if (sscanf(arg, fmt, &VTnum) == 0) {
|
|
UseMsg();
|
|
VTnum = -1;
|
|
return(0);
|
|
}
|
|
|
|
/* OSR6 devices start names at 1, UW7 starts at 0 */
|
|
VTnum -= is_osr6();
|
|
CRTSpecified = TRUE;
|
|
}
|
|
return(2);
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void
|
|
xf86UseMsg(void)
|
|
{
|
|
if (is_osr6()) {
|
|
ErrorF("-crt /dev/ttyXX use the specified VT device\n");
|
|
ErrorF("vtXX use the specified VT number (01-16)\n");
|
|
} else {
|
|
ErrorF("-crt /dev/vtXX use the specified VT device\n");
|
|
ErrorF("vtXX use the specified VT number (00-15)\n");
|
|
}
|
|
|
|
ErrorF("-keeptty ");
|
|
ErrorF("don't detach controlling tty (for debugging only)\n");
|
|
return;
|
|
}
|