]> git.ipfire.org Git - ipfire-3.x.git/blob - initscripts/src/console_check.c
Move all packages to root.
[ipfire-3.x.git] / initscripts / src / console_check.c
1
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <termios.h>
7 #include <unistd.h>
8
9 #include <sys/ioctl.h>
10
11 #include <linux/serial.h>
12 #include <linux/serial_core.h>
13
14 struct speeds
15 {
16 speed_t speed;
17 unsigned long value;
18 };
19
20 struct speeds speed_map[] =
21 {
22 {B50, 50},
23 {B75, 75},
24 {B110, 110},
25 {B134, 134},
26 {B150, 150},
27 {B200, 200},
28 {B300, 300},
29 {B600, 600},
30 {B1200, 1200},
31 {B1800, 1800},
32 {B2400, 2400},
33 {B4800, 4800},
34 {B9600, 9600},
35 {B19200, 19200},
36 {B38400, 38400},
37 #ifdef B57600
38 {B57600, 57600},
39 #endif
40 #ifdef B115200
41 {B115200, 115200},
42 #endif
43 #ifdef B230400
44 {B230400, 230400},
45 #endif
46 #ifdef B460800
47 {B460800, 460800},
48 #endif
49 {0, 0}
50 };
51
52 int termcmp(struct termios *a, struct termios *b) {
53 if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag ||
54 a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag ||
55 cfgetispeed(a) != cfgetispeed(b) || cfgetospeed(a) != cfgetospeed(b))
56 return 1;
57 return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc));
58 }
59
60 int get_serial_speed(int fd) {
61 struct termios mode;
62
63 if (!tcgetattr(fd, &mode)) {
64 int i;
65 speed_t speed;
66
67 speed = cfgetospeed(&mode);
68 for (i = 0; speed_map[i].value != 0; i++)
69 if (speed_map[i].speed == speed)
70 return speed_map[i].value;
71 }
72 return 0;
73 }
74
75 int compare_termios_to_console(char *dev, int *speed) {
76 struct termios cmode, mode;
77 int fd, cfd;
78
79 cfd = open ("/dev/console", O_RDONLY);
80 tcgetattr(cfd, &cmode);
81 close(cfd);
82
83 fd = open(dev, O_RDONLY|O_NONBLOCK);
84 tcgetattr(fd, &mode);
85
86 if (!termcmp(&cmode, &mode)) {
87 *speed = get_serial_speed(fd);
88 close(fd);
89 return 1;
90 }
91 close(fd);
92 return 0;
93 }
94
95 char *serial_tty_name(int type) {
96 switch (type) {
97 case PORT_8250...PORT_MAX_8250:
98 return "ttyS";
99 case PORT_PMAC_ZILOG:
100 return "ttyPZ";
101 case PORT_MPSC:
102 return "ttyMM";
103 case PORT_CPM:
104 return "ttyCPM";
105 case PORT_MPC52xx:
106 return "ttyPSC";
107 default:
108 return NULL;
109 }
110 }
111
112 char *check_serial_console(int *speed) {
113 int fd;
114 char *ret = NULL, *device;
115 char twelve = 12;
116 struct serial_struct si, si2;
117 char *tty_name;
118
119 memset(&si, 0, sizeof(si));
120 memset(&si2, 0, sizeof(si));
121
122 fd = open("/dev/console", O_RDWR);
123 if (ioctl (fd, TIOCLINUX, &twelve) >= 0)
124 goto out;
125
126 if (ioctl(fd, TIOCGSERIAL, &si) < 0)
127 goto out;
128 close(fd);
129
130 tty_name = serial_tty_name(si.type);
131 if (!tty_name)
132 goto out;
133
134 asprintf(&device, "%s%d", tty_name, si.line);
135 fd = open(device, O_RDWR|O_NONBLOCK);
136 if (fd == -1)
137 goto out;
138
139 if (ioctl(fd, TIOCGSERIAL, &si2) < 0)
140 goto out;
141
142 if (memcmp(&si,&si2, sizeof(si)))
143 goto out;
144
145 *speed = get_serial_speed(fd);
146 ret = device;
147 out:
148 close(fd);
149 return ret;
150 }
151
152 int emit_console_event(char *dev, int speed) {
153 char *args[] = { "initctl", "emit", "--no-wait", "serial-console-available", NULL, NULL, NULL };
154
155 asprintf(&args[4],"DEV=%s", dev);
156 if (speed)
157 asprintf(&args[5],"SPEED=%d", speed);
158 execv("/sbin/initctl", args);
159 return 1;
160 }
161
162 int main(int argc, char **argv) {
163 char *device;
164 int speed;
165
166 if (argc < 2) {
167 printf("usage: console_check <device>\n");
168 exit(1);
169 }
170 chdir("/dev");
171 device = argv[1];
172 if (!strcmp(device, "console")) {
173 device = check_serial_console(&speed);
174 if (device)
175 return emit_console_event(device, speed);
176 } else if (compare_termios_to_console(device, &speed)) {
177 return emit_console_event(device, speed);
178 }
179 return 0;
180 }