1/* This code is adapted from busybox project
2 *
3 * Licensed under GPLv2
4 */
5#include "libbb.h"
6
7/* From <linux/vt.h> */
8struct vt_stat {
9	unsigned short v_active;	/* active vt */
10	unsigned short v_signal;	/* signal to send */
11	unsigned short v_state;	/* vt bitmask */
12};
13enum { VT_GETSTATE = 0x5603 };	/* get global vt state info */
14
15/* From <linux/serial.h> */
16struct serial_struct {
17	int	type;
18	int	line;
19	unsigned int	port;
20	int	irq;
21	int	flags;
22	int	xmit_fifo_size;
23	int	custom_divisor;
24	int	baud_base;
25	unsigned short	close_delay;
26	char	io_type;
27	char	reserved_char[1];
28	int	hub6;
29	unsigned short	closing_wait; /* time to wait before closing */
30	unsigned short	closing_wait2; /* no longer used... */
31	unsigned char	*iomem_base;
32	unsigned short	iomem_reg_shift;
33	unsigned int	port_high;
34	unsigned long	iomap_base;	/* cookie passed into ioremap */
35	int	reserved[1];
36};
37
38int cttyhack_main(int argc, char **argv) ATTRIBUTE_NORETURN;
39int cttyhack_main(int argc, char **argv)
40{
41	int fd;
42	char console[sizeof(int)*3 + 16];
43	union {
44		struct vt_stat vt;
45		struct serial_struct sr;
46		char paranoia[sizeof(struct serial_struct) * 3];
47	} u;
48
49	if (!*++argv) {
50		bb_show_usage();
51	}
52
53	strcpy(console, "/dev/tty");
54	if (ioctl(0, TIOCGSERIAL, &u.sr) == 0) {
55		/* this is a serial console */
56		sprintf(console + 8, "S%d", u.sr.line);
57	} else if (ioctl(0, VT_GETSTATE, &u.vt) == 0) {
58		/* this is linux virtual tty */
59		sprintf(console + 8, "S%d" + 1, u.vt.v_active);
60	}
61
62	if (console[8]) {
63		fd = xopen(console, O_RDWR);
64		//bb_error_msg("switching to '%s'", console);
65		dup2(fd, 0);
66		dup2(fd, 1);
67		dup2(fd, 2);
68		while (fd > 2) close(fd--);
69	}
70
71	execvp(argv[0], argv);
72	bb_perror_msg_and_die("cannot exec '%s'", argv[0]);
73}
74