#include "X.h"
#include "Xmd.h"
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86_OSlib.h"
#include "lnx.h"
#include <sys/stat.h>
#ifdef USE_DEV_FB
extern char *getenv(const char *);
#include <linux/fb.h>
char *fb_dev_name;
#endif
static Bool KeepTty = FALSE;
static int VTnum = -1;
static int activeVT = -1;
static int vtPermSave[4];
static char vtname[11];
static int
saveVtPerms(void)
{
struct stat svtp;
if (stat("/dev/tty0", &svtp) != 0)
return 0;
vtPermSave[0] = (int)svtp.st_uid;
vtPermSave[1] = (int)svtp.st_gid;
if (stat(vtname, &svtp) != 0)
return 0;
vtPermSave[2] = (int)svtp.st_uid;
vtPermSave[3] = (int)svtp.st_gid;
return 1;
}
static void
restoreVtPerms(void)
{
chown("/dev/tty0", vtPermSave[0], vtPermSave[1]);
chown(vtname, vtPermSave[2], vtPermSave[3]);
}
void
xf86OpenConsole(void)
{
int i, fd = -1;
int result;
struct vt_mode VT;
struct vt_stat vts;
MessageType from = X_PROBED;
#ifdef USE_DEV_FB
struct fb_var_screeninfo var;
int fbfd;
#endif
char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
if (serverGeneration == 1)
{
if (geteuid() != 0)
{
FatalError("xf86OpenConsole: Server must be suid root\n");
}
if (VTnum != -1) {
xf86Info.vtno = VTnum;
from = X_CMDLINE;
} else {
i=0;
while (tty0[i] != NULL)
{
if ((fd = open(tty0[i],O_WRONLY,0)) >= 0)
break;
i++;
}
if (fd < 0)
FatalError(
"xf86OpenConsole: Cannot open /dev/tty0 (%s)\n",
strerror(errno));
if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
(xf86Info.vtno == -1)) {
FatalError("xf86OpenConsole: Cannot find a free VT\n");
}
close(fd);
}
#ifdef USE_DEV_FB
fb_dev_name=getenv("FRAMEBUFFER");
if (!fb_dev_name)
fb_dev_name="/dev/fb0current";
if ((fbfd = open(fb_dev_name, O_RDONLY)) < 0)
FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
fb_dev_name, strerror(errno));
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var))
FatalError("xf86OpenConsole: Unable to get screen info\n");
#endif
xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
if (!KeepTty) {
setpgrp();
}
i=0;
while (vcs[i] != NULL)
{
sprintf(vtname, vcs[i], xf86Info.vtno);
if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) >= 0)
break;
i++;
}
if (xf86Info.consoleFd < 0) {
FatalError("xf86OpenConsole: Cannot open virtual console %d (%s)\n",
xf86Info.vtno, strerror(errno));
}
if (!saveVtPerms()){
xf86Msg(X_WARNING,
"xf86OpenConsole: Could not save ownership of VT\n");
}
chown(vtname, getuid(), getgid());
chown("/dev/tty0", getuid(), getgid());
if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) == 0)
{
activeVT = vts.v_active;
}
if (!KeepTty)
{
if ((i = open("/dev/tty",O_RDWR)) >= 0)
{
ioctl(i, TIOCNOTTY, 0);
close(i);
}
}
SYSCALL(result = ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
if (result != 0)
{
xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
}
SYSCALL(result =
ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
if (result != 0)
{
xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
}
SYSCALL(result = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
if (result < 0)
{
FatalError("xf86OpenConsole: VT_GETMODE failed\n");
}
signal(SIGUSR1, xf86VTRequest);
VT.mode = VT_PROCESS;
VT.relsig = SIGUSR1;
VT.acqsig = SIGUSR1;
if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
{
FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
}
if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
{
FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed\n");
}
#ifdef USE_DEV_FB
var.yoffset=0;
var.xoffset=0;
if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &var))
FatalError("Unable to set screen info\n");
close(fbfd);
#endif
}
else
{
SYSCALL(result = ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
if (result != 0)
{
xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
}
SYSCALL(result =
ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
if (result != 0)
{
xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
}
}
return;
}
void
xf86CloseConsole()
{
struct vt_mode VT;
#if 0
ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno);
ioctl(xf86Info.consoleFd, VT_WAITACTIVE, 0);
#endif
ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT);
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
{
VT.mode = VT_AUTO;
ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
}
if (activeVT >= 0)
{
ioctl(xf86Info.consoleFd, VT_ACTIVATE, activeVT);
activeVT = -1;
}
close(xf86Info.consoleFd);
restoreVtPerms();
return;
}
int
xf86ProcessArgument(int argc, char *argv[], int i)
{
if (!strcmp(argv[i], "-keeptty"))
{
KeepTty = 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);
}
return(1);
}
return(0);
}
void
xf86UseMsg()
{
ErrorF("vtXX use the specified VT number\n");
ErrorF("-keeptty ");
ErrorF("don't detach controlling tty (for debugging only)\n");
return;
}