#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;
if (geteuid() != 0) {
FatalError("xf86OpenConsole: Server must be suid root\n");
}
OsSignal (SIGTTOU, SIG_IGN);
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);
}
}
if (VTnum == -1) {
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;
}
if (ioctl (0, KIOCINFO, 0) >= 0)
consdev = 1 + isconsole;
if ((!CRTSpecified) && (isconsole || (!consdev))) {
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);
}
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;
chown(vtdevice, getuid(), getgid());
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 {
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 (!xf86Screens[0]->vtSema)
sleep(5);
}
return;
}
void
xf86CloseConsole(void)
{
struct vt_mode VT;
struct sigaction sigvtsw;
ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT);
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);
}
close(xf86Info.consoleFd);
return;
}
int
xf86ProcessArgument(int argc, char *argv[], int i)
{
if (!strcmp(argv[i], "-keeptty")) {
KeepTty = TRUE;
return(1);
}
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);
}
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";
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);
}
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;
}