1/* vi: set sw=4 ts=4: */
2/*
3 * Licensed under GPLv2
4 *
5 * Copyright (c) 2007 Denys Vlasenko <vda.linux@googlemail.com>
6 */
7#include "libbb.h"
8
9/* From <linux/vt.h> */
10struct vt_stat {
11	unsigned short v_active;        /* active vt */
12	unsigned short v_signal;        /* signal to send */
13	unsigned short v_state;         /* vt bitmask */
14};
15enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */
16
17/* From <linux/serial.h> */
18struct serial_struct {
19	int	type;
20	int	line;
21	unsigned int	port;
22	int	irq;
23	int	flags;
24	int	xmit_fifo_size;
25	int	custom_divisor;
26	int	baud_base;
27	unsigned short	close_delay;
28	char	io_type;
29	char	reserved_char[1];
30	int	hub6;
31	unsigned short	closing_wait;   /* time to wait before closing */
32	unsigned short	closing_wait2;  /* no longer used... */
33	unsigned char	*iomem_base;
34	unsigned short	iomem_reg_shift;
35	unsigned int	port_high;
36	unsigned long	iomap_base;	/* cookie passed into ioremap */
37	int	reserved[1];
38};
39
40int cttyhack_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
41int cttyhack_main(int argc UNUSED_PARAM, char **argv)
42{
43	int fd;
44	char console[sizeof(int)*3 + 16];
45	union {
46		struct vt_stat vt;
47		struct serial_struct sr;
48		char paranoia[sizeof(struct serial_struct) * 3];
49	} u;
50
51	if (!*++argv) {
52		bb_show_usage();
53	}
54
55	strcpy(console, "/dev/tty");
56	fd = open(console, O_RDWR);
57	if (fd >= 0) {
58		/* We already have ctty, nothing to do */
59		close(fd);
60	} else {
61		/* We don't have ctty (or don't have "/dev/tty" node...) */
62		if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
63			/* this is a serial console */
64			sprintf(console + 8, "S%d", u.sr.line);
65		} else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
66			/* this is linux virtual tty */
67			sprintf(console + 8, "S%d" + 1, u.vt.v_active);
68		}
69		if (console[8]) {
70			fd = xopen(console, O_RDWR);
71			//bb_error_msg("switching to '%s'", console);
72			dup2(fd, 0);
73			dup2(fd, 1);
74			dup2(fd, 2);
75			while (fd > 2)
76				close(fd--);
77			/* Some other session may have it as ctty,
78			 * steal it from them:
79			 */
80			ioctl(0, TIOCSCTTY, 1);
81		}
82	}
83
84	BB_EXECVP_or_die(argv);
85}
86