blob: 169d8f9096c8e40bf6da46deb3fc6cae0fb202b1 [file] [log] [blame]
Jeremy Kerrd831f962016-01-29 17:18:01 +08001/**
2 * Console server process for OpenBMC
3 *
Jeremy Kerr9326d772016-03-17 17:15:02 +08004 * Copyright © 2016 IBM Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
Jeremy Kerrd831f962016-01-29 17:18:01 +080017 */
18
Jeremy Kerr329a35f2016-03-10 15:36:01 +080019#include <assert.h>
Jeremy Kerr769cee12016-03-15 17:53:56 +080020#include <errno.h>
21#include <signal.h>
Jeremy Kerrd831f962016-01-29 17:18:01 +080022#include <stdint.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <err.h>
Jeremy Kerrd831f962016-01-29 17:18:01 +080029#include <string.h>
30#include <getopt.h>
Jeremy Kerr17217842016-01-29 18:44:21 +080031#include <limits.h>
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -080032#include <time.h>
Jeremy Kerr54e95692016-03-24 17:07:56 +080033#include <termios.h>
Jeremy Kerrd831f962016-01-29 17:18:01 +080034
35#include <sys/types.h>
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -080036#include <sys/time.h>
Joel Stanley87e344c2016-09-01 00:00:51 +093037#include <poll.h>
Jeremy Kerrd831f962016-01-29 17:18:01 +080038
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +080039#include "console-server.h"
Jeremy Kerrd831f962016-01-29 17:18:01 +080040
Ninad Palsule4e718692023-04-26 21:18:35 -050041/* size of the dbus object path length */
42const size_t dbus_obj_path_len = 1024;
43
Andrew Jefferya72711a2023-04-18 18:19:41 +093044#define DBUS_ERR "org.openbmc.error"
Ninad Palsule4e718692023-04-26 21:18:35 -050045#define INTF_NAME "xyz.openbmc_project.console"
46#define DBUS_NAME "xyz.openbmc_project.Console.%s"
47#define OBJ_NAME "/xyz/openbmc_project/console/%s"
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +080048
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +080049struct console {
Andrew Jefferya72711a2023-04-18 18:19:41 +093050 const char *tty_kname;
51 char *tty_sysfs_devnode;
52 char *tty_dev;
Ninad Palsule4e718692023-04-26 21:18:35 -050053 const char *console_id;
Andrew Jefferya72711a2023-04-18 18:19:41 +093054 int tty_sirq;
Andrew Jefferyfd883a82023-04-18 22:18:25 +093055 uint16_t tty_lpc_addr;
Andrew Jefferya72711a2023-04-18 18:19:41 +093056 speed_t tty_baud;
57 int tty_fd;
Jeremy Kerr329a35f2016-03-10 15:36:01 +080058
Andrew Jefferya72711a2023-04-18 18:19:41 +093059 struct ringbuffer *rb;
Jeremy Kerrf733c852017-02-07 18:40:10 +080060
Andrew Jefferya72711a2023-04-18 18:19:41 +093061 struct handler **handlers;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +093062 long n_handlers;
Jeremy Kerr329a35f2016-03-10 15:36:01 +080063
Andrew Jefferya72711a2023-04-18 18:19:41 +093064 struct poller **pollers;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +093065 long n_pollers;
Jeremy Kerr329a35f2016-03-10 15:36:01 +080066
Andrew Jefferya72711a2023-04-18 18:19:41 +093067 struct pollfd *pollfds;
68 struct sd_bus *bus;
Jeremy Kerrd831f962016-01-29 17:18:01 +080069};
70
Jeremy Kerr329a35f2016-03-10 15:36:01 +080071struct poller {
Andrew Jefferya72711a2023-04-18 18:19:41 +093072 struct handler *handler;
73 void *data;
74 poller_event_fn_t event_fn;
75 poller_timeout_fn_t timeout_fn;
76 struct timeval timeout;
77 bool remove;
Jeremy Kerr329a35f2016-03-10 15:36:01 +080078};
79
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +080080/* we have two extra entry in the pollfds array for the VUART tty */
81enum internal_pollfds {
82 POLLFD_HOSTTTY = 0,
83 POLLFD_DBUS = 1,
84 MAX_INTERNAL_POLLFD = 2,
85};
Jeremy Kerr329a35f2016-03-10 15:36:01 +080086
Jeremy Kerrf733c852017-02-07 18:40:10 +080087/* size of the shared backlog ringbuffer */
Andrew Jeffery5db8c792023-04-18 21:48:24 +093088const size_t buffer_size = 128ul * 1024ul;
Jeremy Kerrf733c852017-02-07 18:40:10 +080089
Jeremy Kerr769cee12016-03-15 17:53:56 +080090/* state shared with the signal handler */
91static bool sigint;
Jeremy Kerr329a35f2016-03-10 15:36:01 +080092
Jeremy Kerrd831f962016-01-29 17:18:01 +080093static void usage(const char *progname)
94{
95 fprintf(stderr,
Andrew Jefferya72711a2023-04-18 18:19:41 +093096 "usage: %s [options] <DEVICE>\n"
97 "\n"
98 "Options:\n"
99 " --config <FILE> Use FILE for configuration\n"
100 "",
Jeremy Kerrd831f962016-01-29 17:18:01 +0800101 progname);
102}
103
Jeremy Kerr17217842016-01-29 18:44:21 +0800104/* populates tty_dev and tty_sysfs_devnode, using the tty kernel name */
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800105static int tty_find_device(struct console *console)
Jeremy Kerr17217842016-01-29 18:44:21 +0800106{
107 char *tty_class_device_link;
108 char *tty_device_tty_dir;
109 char *tty_device_reldir;
Yi Li45ad7672016-10-18 23:21:19 +0800110 char *tty_path_input;
111 char *tty_path_input_real;
112 char *tty_kname_real;
Jeremy Kerr17217842016-01-29 18:44:21 +0800113 int rc;
114
Jeremy Kerr17217842016-01-29 18:44:21 +0800115 tty_class_device_link = NULL;
116 tty_device_tty_dir = NULL;
117 tty_device_reldir = NULL;
Yi Li45ad7672016-10-18 23:21:19 +0800118 tty_path_input = NULL;
119 tty_path_input_real = NULL;
120 tty_kname_real = NULL;
Jeremy Kerr17217842016-01-29 18:44:21 +0800121
Yi Li45ad7672016-10-18 23:21:19 +0800122 /* udev may rename the tty name with a symbol link, try to resolve */
123 rc = asprintf(&tty_path_input, "/dev/%s", console->tty_kname);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930124 if (rc < 0) {
Jeremy Kerr17217842016-01-29 18:44:21 +0800125 return -1;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930126 }
Jeremy Kerr17217842016-01-29 18:44:21 +0800127
Yi Li45ad7672016-10-18 23:21:19 +0800128 tty_path_input_real = realpath(tty_path_input, NULL);
129 if (!tty_path_input_real) {
130 warn("Can't find realpath for /dev/%s", console->tty_kname);
Andrew Jeffery15792aa2023-04-18 16:47:33 +0930131 rc = -1;
Yi Li45ad7672016-10-18 23:21:19 +0800132 goto out_free;
133 }
134
135 tty_kname_real = basename(tty_path_input_real);
136 if (!tty_kname_real) {
137 warn("Can't find real name for /dev/%s", console->tty_kname);
Andrew Jeffery15792aa2023-04-18 16:47:33 +0930138 rc = -1;
Yi Li45ad7672016-10-18 23:21:19 +0800139 goto out_free;
140 }
141
Andrew Jefferya72711a2023-04-18 18:19:41 +0930142 rc = asprintf(&tty_class_device_link, "/sys/class/tty/%s",
143 tty_kname_real);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930144 if (rc < 0) {
Yi Li45ad7672016-10-18 23:21:19 +0800145 goto out_free;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930146 }
Yi Li45ad7672016-10-18 23:21:19 +0800147
Jeremy Kerr17217842016-01-29 18:44:21 +0800148 tty_device_tty_dir = realpath(tty_class_device_link, NULL);
Yi Li45ad7672016-10-18 23:21:19 +0800149 if (!tty_device_tty_dir) {
150 warn("Can't query sysfs for device %s", tty_kname_real);
Andrew Jeffery15792aa2023-04-18 16:47:33 +0930151 rc = -1;
Jeremy Kerr17217842016-01-29 18:44:21 +0800152 goto out_free;
153 }
154
155 rc = asprintf(&tty_device_reldir, "%s/../../", tty_device_tty_dir);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930156 if (rc < 0) {
Jeremy Kerr17217842016-01-29 18:44:21 +0800157 goto out_free;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930158 }
Jeremy Kerr17217842016-01-29 18:44:21 +0800159
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800160 console->tty_sysfs_devnode = realpath(tty_device_reldir, NULL);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930161 if (!console->tty_sysfs_devnode) {
Yi Li45ad7672016-10-18 23:21:19 +0800162 warn("Can't find parent device for %s", tty_kname_real);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930163 }
Jeremy Kerr17217842016-01-29 18:44:21 +0800164
Yi Li45ad7672016-10-18 23:21:19 +0800165 rc = asprintf(&console->tty_dev, "/dev/%s", tty_kname_real);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930166 if (rc < 0) {
Jeremy Kerr17217842016-01-29 18:44:21 +0800167 goto out_free;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930168 }
Jeremy Kerr17217842016-01-29 18:44:21 +0800169
170 rc = 0;
171
172out_free:
173 free(tty_class_device_link);
174 free(tty_device_tty_dir);
175 free(tty_device_reldir);
Yi Li45ad7672016-10-18 23:21:19 +0800176 free(tty_path_input);
177 free(tty_path_input_real);
Jeremy Kerr17217842016-01-29 18:44:21 +0800178 return rc;
179}
180
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800181static int tty_set_sysfs_attr(struct console *console, const char *name,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930182 int value)
Jeremy Kerr957818b2016-03-08 14:35:15 +0800183{
184 char *path;
185 FILE *fp;
186 int rc;
187
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800188 rc = asprintf(&path, "%s/%s", console->tty_sysfs_devnode, name);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930189 if (rc < 0) {
Jeremy Kerr957818b2016-03-08 14:35:15 +0800190 return -1;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930191 }
Jeremy Kerr957818b2016-03-08 14:35:15 +0800192
193 fp = fopen(path, "w");
194 if (!fp) {
Andrew Jefferya72711a2023-04-18 18:19:41 +0930195 warn("Can't access attribute %s on device %s", name,
196 console->tty_kname);
Jeremy Kerr957818b2016-03-08 14:35:15 +0800197 rc = -1;
198 goto out_free;
199 }
200 setvbuf(fp, NULL, _IONBF, 0);
201
202 rc = fprintf(fp, "0x%x", value);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930203 if (rc < 0) {
Andrew Jefferya72711a2023-04-18 18:19:41 +0930204 warn("Error writing to %s attribute of device %s", name,
205 console->tty_kname);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930206 }
Jeremy Kerr957818b2016-03-08 14:35:15 +0800207 fclose(fp);
208
Jeremy Kerr957818b2016-03-08 14:35:15 +0800209out_free:
210 free(path);
211 return rc;
212}
213
Jeremy Kerrd831f962016-01-29 17:18:01 +0800214/**
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700215 * Set termios attributes on the console tty.
Jeremy Kerr54e95692016-03-24 17:07:56 +0800216 */
217static void tty_init_termios(struct console *console)
218{
219 struct termios termios;
220 int rc;
221
222 rc = tcgetattr(console->tty_fd, &termios);
223 if (rc) {
224 warn("Can't read tty termios");
225 return;
226 }
227
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700228 if (console->tty_baud) {
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930229 if (cfsetspeed(&termios, console->tty_baud) < 0) {
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700230 warn("Couldn't set speeds for %s", console->tty_kname);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930231 }
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700232 }
233
234 /* Set console to raw mode: we don't want any processing to occur on
235 * the underlying terminal input/output.
236 */
Jeremy Kerr54e95692016-03-24 17:07:56 +0800237 cfmakeraw(&termios);
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700238
Jeremy Kerr54e95692016-03-24 17:07:56 +0800239 rc = tcsetattr(console->tty_fd, TCSANOW, &termios);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930240 if (rc) {
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700241 warn("Can't set terminal options for %s", console->tty_kname);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930242 }
Jeremy Kerr54e95692016-03-24 17:07:56 +0800243}
244
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800245static void tty_change_baudrate(struct console *console)
246{
247 struct handler *handler;
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930248 int i;
249 int rc;
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800250
251 tty_init_termios(console);
252
253 for (i = 0; i < console->n_handlers; i++) {
254 handler = console->handlers[i];
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930255 if (!handler->baudrate) {
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800256 continue;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930257 }
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800258
259 rc = handler->baudrate(handler, console->tty_baud);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930260 if (rc) {
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800261 warnx("Can't set terminal baudrate for handler %s",
Andrew Jefferya72711a2023-04-18 18:19:41 +0930262 handler->name);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930263 }
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800264 }
265}
266
Jeremy Kerr54e95692016-03-24 17:07:56 +0800267/**
Jeremy Kerrd831f962016-01-29 17:18:01 +0800268 * Open and initialise the serial device
269 */
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800270static int tty_init_io(struct console *console)
Jeremy Kerrd831f962016-01-29 17:18:01 +0800271{
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930272 if (console->tty_sirq) {
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800273 tty_set_sysfs_attr(console, "sirq", console->tty_sirq);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930274 }
275 if (console->tty_lpc_addr) {
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800276 tty_set_sysfs_attr(console, "lpc_address",
Andrew Jefferya72711a2023-04-18 18:19:41 +0930277 console->tty_lpc_addr);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930278 }
Jeremy Kerr957818b2016-03-08 14:35:15 +0800279
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800280 console->tty_fd = open(console->tty_dev, O_RDWR);
281 if (console->tty_fd <= 0) {
282 warn("Can't open tty %s", console->tty_dev);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800283 return -1;
284 }
285
286 /* Disable character delay. We may want to later enable this when
287 * we detect larger amounts of data
288 */
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800289 fcntl(console->tty_fd, F_SETFL, FNDELAY);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800290
Jeremy Kerr54e95692016-03-24 17:07:56 +0800291 tty_init_termios(console);
292
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800293 console->pollfds[console->n_pollers].fd = console->tty_fd;
294 console->pollfds[console->n_pollers].events = POLLIN;
295
Jeremy Kerrd831f962016-01-29 17:18:01 +0800296 return 0;
297}
298
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800299static int tty_init(struct console *console, struct config *config)
300{
Andrew Jefferyfd883a82023-04-18 22:18:25 +0930301 unsigned long parsed;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800302 const char *val;
303 char *endp;
304 int rc;
305
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800306 val = config_get_value(config, "lpc-address");
307 if (val) {
Andrew Jefferyfd883a82023-04-18 22:18:25 +0930308 errno = 0;
309 parsed = strtoul(val, &endp, 0);
310 if (parsed == ULONG_MAX && errno == ERANGE) {
311 warn("Cannot interpret 'lpc-address' value as an unsigned long: '%s'",
312 val);
313 return -1;
314 }
315
316 if (parsed > UINT16_MAX) {
317 warn("Invalid LPC address '%s'", val);
318 return -1;
319 }
320
321 console->tty_lpc_addr = (uint16_t)parsed;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800322 if (endp == optarg) {
323 warn("Invalid LPC address: '%s'", val);
324 return -1;
325 }
326 }
327
328 val = config_get_value(config, "sirq");
329 if (val) {
Andrew Jefferyfd883a82023-04-18 22:18:25 +0930330 errno = 0;
331 parsed = strtoul(val, &endp, 0);
332 if (parsed == ULONG_MAX && errno == ERANGE) {
333 warn("Cannot interpret 'sirq' value as an unsigned long: '%s'",
334 val);
335 }
336
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930337 if (parsed > 16) {
Andrew Jefferyfd883a82023-04-18 22:18:25 +0930338 warn("Invalid LPC SERIRQ: '%s'", val);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930339 }
Andrew Jefferyfd883a82023-04-18 22:18:25 +0930340
341 console->tty_sirq = (int)parsed;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930342 if (endp == optarg) {
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800343 warn("Invalid sirq: '%s'", val);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930344 }
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800345 }
346
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700347 val = config_get_value(config, "baud");
348 if (val) {
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930349 if (config_parse_baud(&console->tty_baud, val)) {
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700350 warnx("Invalid baud rate: '%s'", val);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930351 }
Benjamin Fairc7fbcd42018-06-04 14:39:01 -0700352 }
353
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800354 if (!console->tty_kname) {
355 warnx("Error: No TTY device specified");
356 return -1;
357 }
358
359 rc = tty_find_device(console);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930360 if (rc) {
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800361 return rc;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930362 }
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800363
364 rc = tty_init_io(console);
365 return rc;
366}
367
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800368int console_data_out(struct console *console, const uint8_t *data, size_t len)
Jeremy Kerrd831f962016-01-29 17:18:01 +0800369{
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800370 return write_buf_to_fd(console->tty_fd, data, len);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800371}
372
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800373static int method_set_baud_rate(sd_bus_message *msg, void *userdata,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930374 sd_bus_error *err)
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800375{
376 struct console *console = userdata;
377 uint32_t baudrate;
378 speed_t speed;
379 int r;
380
381 if (!console) {
382 sd_bus_error_set_const(err, DBUS_ERR, "Internal error");
383 return sd_bus_reply_method_return(msg, "x", 0);
384 }
385
386 r = sd_bus_message_read(msg, "u", &baudrate);
387 if (r < 0) {
388 sd_bus_error_set_const(err, DBUS_ERR, "Bad message");
389 return sd_bus_reply_method_return(msg, "x", -EINVAL);
390 }
391
392 speed = parse_int_to_baud(baudrate);
393 if (!speed) {
394 warnx("Invalid baud rate: '%u'", baudrate);
395 return sd_bus_reply_method_return(msg, "x", -EINVAL);
396 }
397
398 console->tty_baud = speed;
399 tty_change_baudrate(console);
400
401 return sd_bus_reply_method_return(msg, "x", r);
402}
403
Andrew Jefferyfd048322023-04-18 12:02:01 +0930404static int get_handler(sd_bus *bus __attribute__((unused)),
405 const char *path __attribute__((unused)),
406 const char *interface __attribute__((unused)),
407 const char *property __attribute__((unused)),
408 sd_bus_message *reply, void *userdata,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930409 sd_bus_error *error __attribute__((unused)))
410{
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800411 struct console *console = userdata;
412 uint32_t baudrate;
413 int r;
414
415 baudrate = parse_baud_to_int(console->tty_baud);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930416 if (!baudrate) {
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800417 warnx("Invalid baud rate: '%d'", console->tty_baud);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930418 }
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800419
420 r = sd_bus_message_append(reply, "u", baudrate);
421
422 return r;
423}
424
425static const sd_bus_vtable console_vtable[] = {
426 SD_BUS_VTABLE_START(0),
427 SD_BUS_METHOD("setBaudRate", "u", "x", method_set_baud_rate,
428 SD_BUS_VTABLE_UNPRIVILEGED),
429 SD_BUS_PROPERTY("baudrate", "u", get_handler, 0, 0),
Andrew Jefferya72711a2023-04-18 18:19:41 +0930430 SD_BUS_VTABLE_END,
431};
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800432
Andrew Jefferya72711a2023-04-18 18:19:41 +0930433static void dbus_init(struct console *console,
434 struct config *config __attribute__((unused)))
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800435{
Ninad Palsule4e718692023-04-26 21:18:35 -0500436 char obj_name[dbus_obj_path_len];
437 char dbus_name[dbus_obj_path_len];
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800438 int dbus_poller = 0;
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930439 int fd;
440 int r;
Ninad Palsule4e718692023-04-26 21:18:35 -0500441 size_t bytes;
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800442
443 if (!console) {
444 warnx("Couldn't get valid console");
445 return;
446 }
447
448 r = sd_bus_default_system(&console->bus);
449 if (r < 0) {
450 warnx("Failed to connect to system bus: %s", strerror(-r));
451 return;
452 }
453
Ninad Palsule4e718692023-04-26 21:18:35 -0500454 /* Register support console interface */
455 bytes = snprintf(obj_name, dbus_obj_path_len, OBJ_NAME,
456 console->console_id);
457 if (bytes >= dbus_obj_path_len) {
458 warnx("Console id '%s' is too long. There is no enough space in the buffer.",
459 console->console_id);
460 return;
461 }
462
463 r = sd_bus_add_object_vtable(console->bus, NULL, obj_name, INTF_NAME,
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800464 console_vtable, console);
465 if (r < 0) {
466 warnx("Failed to issue method call: %s", strerror(-r));
467 return;
468 }
469
Ninad Palsule4e718692023-04-26 21:18:35 -0500470 bytes = snprintf(dbus_name, dbus_obj_path_len, DBUS_NAME,
471 console->console_id);
472 if (bytes >= dbus_obj_path_len) {
473 warnx("Console id '%s' is too long. There is no enough space in the buffer.",
474 console->console_id);
475 return;
476 }
477
478 r = sd_bus_request_name(console->bus, dbus_name,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930479 SD_BUS_NAME_ALLOW_REPLACEMENT |
480 SD_BUS_NAME_REPLACE_EXISTING);
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800481 if (r < 0) {
482 warnx("Failed to acquire service name: %s", strerror(-r));
483 return;
484 }
485
486 fd = sd_bus_get_fd(console->bus);
487 if (fd < 0) {
488 warnx("Couldn't get the bus file descriptor");
489 return;
490 }
491
492 dbus_poller = POLLFD_DBUS;
493
494 console->pollfds[dbus_poller].fd = fd;
495 console->pollfds[dbus_poller].events = POLLIN;
496}
497
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800498static void handlers_init(struct console *console, struct config *config)
Jeremy Kerrd831f962016-01-29 17:18:01 +0800499{
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930500 /* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
501 extern struct handler *__start_handlers;
502 extern struct handler *__stop_handlers;
503 /* NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800504 struct handler *handler;
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930505 int i;
506 int rc;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800507
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800508 console->n_handlers = &__stop_handlers - &__start_handlers;
509 console->handlers = &__start_handlers;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800510
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930511 printf("%ld handler%s\n", console->n_handlers,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930512 console->n_handlers == 1 ? "" : "s");
Jeremy Kerrd831f962016-01-29 17:18:01 +0800513
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800514 for (i = 0; i < console->n_handlers; i++) {
515 handler = console->handlers[i];
516
Jeremy Kerr021b91f2016-04-28 11:51:52 +0800517 rc = 0;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930518 if (handler->init) {
Jeremy Kerr021b91f2016-04-28 11:51:52 +0800519 rc = handler->init(handler, console, config);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930520 }
Jeremy Kerr021b91f2016-04-28 11:51:52 +0800521
522 handler->active = rc == 0;
523
524 printf(" %s [%sactive]\n", handler->name,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930525 handler->active ? "" : "in");
Jeremy Kerrd831f962016-01-29 17:18:01 +0800526 }
Jeremy Kerrd831f962016-01-29 17:18:01 +0800527}
528
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800529static void handlers_fini(struct console *console)
Jeremy Kerrd831f962016-01-29 17:18:01 +0800530{
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800531 struct handler *handler;
532 int i;
533
534 for (i = 0; i < console->n_handlers; i++) {
535 handler = console->handlers[i];
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930536 if (handler->fini && handler->active) {
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800537 handler->fini(handler);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930538 }
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800539 }
Jeremy Kerrd831f962016-01-29 17:18:01 +0800540}
541
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800542static int get_current_time(struct timeval *tv)
543{
544 struct timespec t;
545 int rc;
546
547 /*
548 * We use clock_gettime(CLOCK_MONOTONIC) so we're immune to
549 * local time changes. However, a struct timeval is more
550 * convenient for calculations, so convert to that.
551 */
552 rc = clock_gettime(CLOCK_MONOTONIC, &t);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930553 if (rc) {
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800554 return rc;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930555 }
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800556
557 tv->tv_sec = t.tv_sec;
558 tv->tv_usec = t.tv_nsec / 1000;
559
560 return 0;
561}
562
Andrew Jefferya72711a2023-04-18 18:19:41 +0930563struct ringbuffer_consumer *
564console_ringbuffer_consumer_register(struct console *console,
565 ringbuffer_poll_fn_t poll_fn, void *data)
Jeremy Kerrd831f962016-01-29 17:18:01 +0800566{
Jeremy Kerrf733c852017-02-07 18:40:10 +0800567 return ringbuffer_consumer_register(console->rb, poll_fn, data);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800568}
569
Jeremy Kerr55c97122017-02-07 17:06:46 +0800570struct poller *console_poller_register(struct console *console,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930571 struct handler *handler,
572 poller_event_fn_t poller_fn,
573 poller_timeout_fn_t timeout_fn, int fd,
574 int events, void *data)
Jeremy Kerrd831f962016-01-29 17:18:01 +0800575{
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800576 struct poller *poller;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930577 long n;
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800578
579 poller = malloc(sizeof(*poller));
580 poller->remove = false;
581 poller->handler = handler;
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800582 poller->event_fn = poller_fn;
583 poller->timeout_fn = timeout_fn;
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800584 poller->data = data;
585
586 /* add one to our pollers array */
587 n = console->n_pollers++;
Andrew Jeffery91b52172023-04-19 12:42:14 +0930588 /*
589 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
590 * pointer type.
591 */
592 /* NOLINTBEGIN(bugprone-sizeof-expression) */
593 console->pollers = reallocarray(console->pollers, console->n_pollers,
594 sizeof(*console->pollers));
595 /* NOLINTEND(bugprone-sizeof-expression) */
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800596
597 console->pollers[n] = poller;
598
599 /* increase pollfds array too */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930600 console->pollfds =
Andrew Jeffery91b52172023-04-19 12:42:14 +0930601 reallocarray(console->pollfds,
602 (MAX_INTERNAL_POLLFD + console->n_pollers),
603 sizeof(*console->pollfds));
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800604
605 /* shift the end pollfds up by one */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930606 memcpy(&console->pollfds[n + 1], &console->pollfds[n],
607 sizeof(*console->pollfds) * MAX_INTERNAL_POLLFD);
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800608
609 console->pollfds[n].fd = fd;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930610 console->pollfds[n].events = (short)(events & 0x7fff);
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800611
612 return poller;
613}
614
Andrew Jefferya72711a2023-04-18 18:19:41 +0930615void console_poller_unregister(struct console *console, struct poller *poller)
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800616{
617 int i;
618
619 /* find the entry in our pollers array */
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930620 for (i = 0; i < console->n_pollers; i++) {
621 if (console->pollers[i] == poller) {
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800622 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930623 }
624 }
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800625
626 assert(i < console->n_pollers);
627
628 console->n_pollers--;
629
Andrew Jeffery91b52172023-04-19 12:42:14 +0930630 /*
631 * Remove the item from the pollers array...
632 *
633 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
634 * pointer type.
635 */
636 /* NOLINTBEGIN(bugprone-sizeof-expression) */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930637 memmove(&console->pollers[i], &console->pollers[i + 1],
638 sizeof(*console->pollers) * (console->n_pollers - i));
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800639
Andrew Jeffery91b52172023-04-19 12:42:14 +0930640 console->pollers = reallocarray(console->pollers, console->n_pollers,
641 sizeof(*console->pollers));
642 /* NOLINTEND(bugprone-sizeof-expression) */
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800643
644 /* ... and the pollfds array */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930645 memmove(&console->pollfds[i], &console->pollfds[i + 1],
646 sizeof(*console->pollfds) *
647 (MAX_INTERNAL_POLLFD + console->n_pollers - i));
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800648
Andrew Jefferya72711a2023-04-18 18:19:41 +0930649 console->pollfds =
Andrew Jeffery91b52172023-04-19 12:42:14 +0930650 reallocarray(console->pollfds,
651 (MAX_INTERNAL_POLLFD + console->n_pollers),
652 sizeof(*console->pollfds));
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800653
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800654 free(poller);
655}
656
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800657void console_poller_set_events(struct console *console, struct poller *poller,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930658 int events)
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800659{
660 int i;
661
662 /* find the entry in our pollers array */
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930663 for (i = 0; i < console->n_pollers; i++) {
664 if (console->pollers[i] == poller) {
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800665 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930666 }
667 }
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800668
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930669 console->pollfds[i].events = (short)(events & 0x7fff);
Jeremy Kerr6b1fed22017-02-07 21:40:38 +0800670}
671
Andrew Jefferyfd048322023-04-18 12:02:01 +0930672void console_poller_set_timeout(struct console *console __attribute__((unused)),
Andrew Jefferya72711a2023-04-18 18:19:41 +0930673 struct poller *poller, const struct timeval *tv)
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800674{
675 struct timeval now;
676 int rc;
677
678 rc = get_current_time(&now);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930679 if (rc) {
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800680 return;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930681 }
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800682
683 timeradd(&now, tv, &poller->timeout);
684}
685
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930686static long get_poll_timeout(struct console *console, struct timeval *cur_time)
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800687{
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930688 struct timeval *earliest;
689 struct timeval interval;
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800690 struct poller *poller;
691 int i;
692
693 earliest = NULL;
694
695 for (i = 0; i < console->n_pollers; i++) {
696 poller = console->pollers[i];
697
698 if (poller->timeout_fn && timerisset(&poller->timeout) &&
699 (!earliest ||
Andrew Jefferya72711a2023-04-18 18:19:41 +0930700 (earliest && timercmp(&poller->timeout, earliest, <)))) {
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800701 // poller is buffering data and needs the poll
702 // function to timeout.
703 earliest = &poller->timeout;
704 }
705 }
706
707 if (earliest) {
708 if (timercmp(earliest, cur_time, >)) {
709 /* recalculate the timeout period, time period has
710 * not elapsed */
711 timersub(earliest, cur_time, &interval);
712 return ((interval.tv_sec * 1000) +
713 (interval.tv_usec / 1000));
Andrew Jeffery0b7b0472023-04-19 12:48:51 +0930714 } /* return from poll immediately */
715 return 0;
716
717 } /* poll indefinitely */
718 return -1;
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800719}
720
721static int call_pollers(struct console *console, struct timeval *cur_time)
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800722{
723 struct poller *poller;
724 struct pollfd *pollfd;
725 enum poller_ret prc;
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930726 int i;
727 int rc;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800728
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800729 rc = 0;
730
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800731 /*
732 * Process poll events by iterating through the pollers and pollfds
733 * in-step, calling any pollers that we've found revents for.
734 */
735 for (i = 0; i < console->n_pollers; i++) {
736 poller = console->pollers[i];
737 pollfd = &console->pollfds[i];
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800738 prc = POLLER_OK;
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800739
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800740 /* process pending events... */
741 if (pollfd->revents) {
742 prc = poller->event_fn(poller->handler, pollfd->revents,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930743 poller->data);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930744 if (prc == POLLER_EXIT) {
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800745 rc = -1;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930746 } else if (prc == POLLER_REMOVE) {
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800747 poller->remove = true;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930748 }
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800749 }
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800750
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800751 if ((prc == POLLER_OK) && poller->timeout_fn &&
752 timerisset(&poller->timeout) &&
753 timercmp(&poller->timeout, cur_time, <=)) {
754 /* One of the ringbuffer consumers is buffering the
755 data stream. The amount of idle time the consumer
756 desired has expired. Process the buffered data for
757 transmission. */
758 timerclear(&poller->timeout);
759 prc = poller->timeout_fn(poller->handler, poller->data);
760 if (prc == POLLER_EXIT) {
761 rc = -1;
762 } else if (prc == POLLER_REMOVE) {
763 poller->remove = true;
764 }
765 }
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800766 }
767
768 /**
769 * Process deferred removals; restarting each time we unregister, as
770 * the array will have changed
771 */
772 for (;;) {
773 bool removed = false;
774
775 for (i = 0; i < console->n_pollers; i++) {
776 poller = console->pollers[i];
777 if (poller->remove) {
Jeremy Kerr55c97122017-02-07 17:06:46 +0800778 console_poller_unregister(console, poller);
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800779 removed = true;
780 break;
781 }
782 }
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930783 if (!removed) {
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800784 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930785 }
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800786 }
787
788 return rc;
789}
790
Jeremy Kerr769cee12016-03-15 17:53:56 +0800791static void sighandler(int signal)
792{
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930793 if (signal == SIGINT) {
Jeremy Kerr769cee12016-03-15 17:53:56 +0800794 sigint = true;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930795 }
Jeremy Kerr769cee12016-03-15 17:53:56 +0800796}
797
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800798int run_console(struct console *console)
799{
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930800 sighandler_t sighandler_save = signal(SIGINT, sighandler);
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800801 struct timeval tv;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930802 long timeout;
803 ssize_t rc;
Jeremy Kerr769cee12016-03-15 17:53:56 +0800804
805 rc = 0;
806
Jeremy Kerrd831f962016-01-29 17:18:01 +0800807 for (;;) {
808 uint8_t buf[4096];
809
Jeremy Kerr17641452017-02-07 22:09:13 +0800810 BUILD_ASSERT(sizeof(buf) <= buffer_size);
811
Jeremy Kerr769cee12016-03-15 17:53:56 +0800812 if (sigint) {
813 fprintf(stderr, "Received interrupt, exiting\n");
814 break;
815 }
816
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800817 rc = get_current_time(&tv);
818 if (rc) {
819 warn("Failed to read current time");
820 break;
821 }
822
823 timeout = get_poll_timeout(console, &tv);
824
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800825 rc = poll(console->pollfds,
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930826 console->n_pollers + MAX_INTERNAL_POLLFD,
827 (int)timeout);
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800828
Jeremy Kerrd831f962016-01-29 17:18:01 +0800829 if (rc < 0) {
Jeremy Kerr769cee12016-03-15 17:53:56 +0800830 if (errno == EINTR) {
831 continue;
Jeremy Kerr769cee12016-03-15 17:53:56 +0800832 }
Andrew Jeffery0b7b0472023-04-19 12:48:51 +0930833 warn("poll error");
834 break;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800835 }
836
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800837 /* process internal fd first */
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800838 if (console->pollfds[console->n_pollers].revents) {
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800839 rc = read(console->tty_fd, buf, sizeof(buf));
Jeremy Kerrd831f962016-01-29 17:18:01 +0800840 if (rc <= 0) {
841 warn("Error reading from tty device");
Jeremy Kerr769cee12016-03-15 17:53:56 +0800842 rc = -1;
843 break;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800844 }
Jeremy Kerrf733c852017-02-07 18:40:10 +0800845 rc = ringbuffer_queue(console->rb, buf, rc);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930846 if (rc) {
Jeremy Kerr769cee12016-03-15 17:53:56 +0800847 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930848 }
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800849 }
Jeremy Kerrd831f962016-01-29 17:18:01 +0800850
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800851 if (console->pollfds[console->n_pollers + 1].revents) {
852 sd_bus_process(console->bus, NULL);
853 }
854
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800855 /* ... and then the pollers */
Johnathan Mantey1cecc5d2019-02-28 15:01:46 -0800856 rc = call_pollers(console, &tv);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930857 if (rc) {
Jeremy Kerr769cee12016-03-15 17:53:56 +0800858 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930859 }
Jeremy Kerrd831f962016-01-29 17:18:01 +0800860 }
Jeremy Kerr769cee12016-03-15 17:53:56 +0800861
862 signal(SIGINT, sighandler_save);
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800863 sd_bus_unref(console->bus);
Jeremy Kerr769cee12016-03-15 17:53:56 +0800864
865 return rc ? -1 : 0;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800866}
Jeremy Kerrd831f962016-01-29 17:18:01 +0800867static const struct option options[] = {
Andrew Jefferya72711a2023-04-18 18:19:41 +0930868 { "config", required_argument, 0, 'c' },
869 { 0, 0, 0, 0 },
Jeremy Kerrd831f962016-01-29 17:18:01 +0800870};
871
872int main(int argc, char **argv)
873{
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800874 const char *config_filename = NULL;
Vishwanatha Subbanna6221ce92016-07-20 05:35:45 -0500875 const char *config_tty_kname = NULL;
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800876 struct console *console;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800877 struct config *config;
878 int rc;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800879
Jeremy Kerr957818b2016-03-08 14:35:15 +0800880 rc = -1;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800881
882 for (;;) {
Andrew Jefferyb70f8712023-04-19 12:53:34 +0930883 int c;
884 int idx;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800885
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800886 c = getopt_long(argc, argv, "c:", options, &idx);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930887 if (c == -1) {
Jeremy Kerrd831f962016-01-29 17:18:01 +0800888 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930889 }
Jeremy Kerrd831f962016-01-29 17:18:01 +0800890
891 switch (c) {
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800892 case 'c':
893 config_filename = optarg;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800894 break;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800895 case 'h':
896 case '?':
897 usage(argv[0]);
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800898 return EXIT_SUCCESS;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800899 }
900 }
901
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930902 if (optind < argc) {
Andrew Jeffery91dde142020-02-12 22:46:27 +1030903 config_tty_kname = argv[optind];
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930904 }
Vishwanatha Subbanna6221ce92016-07-20 05:35:45 -0500905
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800906 console = malloc(sizeof(struct console));
907 memset(console, 0, sizeof(*console));
Andrew Jefferya72711a2023-04-18 18:19:41 +0930908 console->pollfds =
909 calloc(MAX_INTERNAL_POLLFD, sizeof(*console->pollfds));
Jeremy Kerrf733c852017-02-07 18:40:10 +0800910 console->rb = ringbuffer_init(buffer_size);
Jeremy Kerr329a35f2016-03-10 15:36:01 +0800911
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800912 config = config_init(config_filename);
913 if (!config) {
914 warnx("Can't read configuration, exiting.");
915 goto out_free;
Jeremy Kerrd831f962016-01-29 17:18:01 +0800916 }
917
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930918 if (!config_tty_kname) {
Andrew Jeffery91dde142020-02-12 22:46:27 +1030919 config_tty_kname = config_get_value(config, "upstream-tty");
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930920 }
Andrew Jeffery91dde142020-02-12 22:46:27 +1030921
922 if (!config_tty_kname) {
923 warnx("No TTY device specified");
924 usage(argv[0]);
925 return EXIT_FAILURE;
926 }
927
Vishwanatha Subbanna6221ce92016-07-20 05:35:45 -0500928 console->tty_kname = config_tty_kname;
929
Ninad Palsule4e718692023-04-26 21:18:35 -0500930 console->console_id = config_get_value(config, "socket-id");
931 if (!console->console_id) {
932 warnx("Error: The socket-id is not set in the config file");
933 return EXIT_FAILURE;
934 }
935
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800936 rc = tty_init(console, config);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930937 if (rc) {
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800938 goto out_config_fini;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930939 }
Jeremy Kerrd831f962016-01-29 17:18:01 +0800940
Cheng C Yangf9c8f6c2019-03-04 18:39:52 +0800941 dbus_init(console, config);
942
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800943 handlers_init(console, config);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800944
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800945 rc = run_console(console);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800946
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800947 handlers_fini(console);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800948
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800949out_config_fini:
950 config_fini(config);
951
Jeremy Kerr957818b2016-03-08 14:35:15 +0800952out_free:
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800953 free(console->pollers);
954 free(console->pollfds);
Jeremy Kerr1a0e03b2016-03-08 17:57:11 +0800955 free(console->tty_sysfs_devnode);
956 free(console->tty_dev);
957 free(console);
Jeremy Kerrd831f962016-01-29 17:18:01 +0800958
959 return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
960}