blob: b68cfcd76d8bde2764de814451a59c5ce43f9b4c [file] [log] [blame]
Jeremy Kerr9326d772016-03-17 17:15:02 +08001/**
2 * Copyright © 2016 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jeremy Kerrd66195c2016-03-16 17:24:51 +080016
17#include <err.h>
18#include <fcntl.h>
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <strings.h>
Benjamin Fairfcbdea92018-06-04 14:19:25 -070024#include <termios.h> /* for speed_t */
Jeremy Kerrd66195c2016-03-16 17:24:51 +080025#include <unistd.h>
26
27#include <sys/mman.h>
28#include <sys/stat.h>
29
Jeremy Kerre440a402016-03-17 16:34:14 +080030static const char *config_default_filename = SYSCONFDIR "/obmc-console.conf";
Jeremy Kerrd66195c2016-03-16 17:24:51 +080031
32struct config_item {
33 char *name;
34 char *value;
35 struct config_item *next;
36};
37
38struct config {
39 struct config_item *items;
40};
41
42const char *config_get_value(struct config *config, const char *name)
43{
44 struct config_item *item;
45
46 for (item = config->items; item; item = item->next)
47 if (!strcasecmp(item->name, name))
48 return item->value;
49
50 return NULL;
51}
52
53static void config_parse(struct config *config, char *buf)
54{
55 struct config_item *item;
56 char *name, *value;
57 char *p, *line;
58 int rc;
59
60 for (p = NULL, line = strtok_r(buf, "\n", &p); line;
61 line = strtok_r(NULL, "\n", &p)) {
62
63 /* trim leading space */
64 for (;*line == ' ' || *line == '\t'; line++)
65 ;
66
67 /* skip comments */
68 if (*line == '#')
69 continue;
70
71 name = value = NULL;
72
73 rc = sscanf(line, "%m[^ =] = %ms ", &name, &value);
74 if (rc != 2 || !strlen(name) || !strlen(value)) {
75 free(name);
76 free(value);
77 continue;
78 }
79
80 /* create a new item and add to our list */
81 item = malloc(sizeof(*item));
82 item->name = name;
83 item->value = value;
84 item->next = config->items;
85 config->items = item;
86 }
87}
88
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080089static struct config *config_init_fd(int fd, const char *filename)
Jeremy Kerrd66195c2016-03-16 17:24:51 +080090{
91 struct config *config;
Jeremy Kerr2eb56f52016-03-17 14:55:14 +080092 size_t size, len;
Jeremy Kerr2eb56f52016-03-17 14:55:14 +080093 char *buf;
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080094 int rc;
Jeremy Kerrd66195c2016-03-16 17:24:51 +080095
Jeremy Kerr2eb56f52016-03-17 14:55:14 +080096 size = 4096;
97 len = 0;
98 buf = malloc(size + 1);
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080099 config = NULL;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800100
Jeremy Kerr2eb56f52016-03-17 14:55:14 +0800101 for (;;) {
102 rc = read(fd, buf + len, size - len);
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800103 if (rc < 0) {
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800104 warn("Can't read from configuration file %s", filename);
105 goto out_free;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800106
107 } else if (!rc) {
108 break;
109 }
Jeremy Kerr2eb56f52016-03-17 14:55:14 +0800110 len += rc;
111 if (len == size) {
112 size <<= 1;
113 buf = realloc(buf, size + 1);
114 }
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800115
116 }
117 buf[len] = '\0';
118
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800119 config = malloc(sizeof(*config));
120 config->items = NULL;
121
122 config_parse(config, buf);
123
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800124out_free:
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800125 free(buf);
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800126 return config;
127}
128
129struct config *config_init(const char *filename)
130{
131 struct config *config;
132 int fd;
133
134 if (!filename)
135 filename = config_default_filename;
136
137 fd = open(filename, O_RDONLY);
138 if (fd < 0) {
139 warn("Can't open configuration file %s", filename);
140 return NULL;
141 }
142
143 config = config_init_fd(fd, filename);
144
145 close(fd);
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800146
147 return config;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800148}
149
150void config_fini(struct config *config)
151{
152 struct config_item *item, *next;
153
154 for (item = config->items; item; item = next) {
155 next = item->next;
156 free(item->name);
157 free(item->value);
158 free(item);
159 }
160
161 free(config);
162}
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800163
Benjamin Fairfcbdea92018-06-04 14:19:25 -0700164struct terminal_speed_name {
165 speed_t speed;
166 const char *name;
167};
168
169int config_parse_baud(speed_t *speed, const char *baud_string) {
170 const struct terminal_speed_name terminal_speeds[] = {
171 { B50, "50" },
172 { B75, "75" },
173 { B110, "110" },
174 { B134, "134" },
175 { B150, "150" },
176 { B200, "200" },
177 { B300, "300" },
178 { B600, "600" },
179 { B1200, "1200" },
180 { B1800, "1800" },
181 { B2400, "2400" },
182 { B4800, "4800" },
183 { B9600, "9600" },
184 { B19200, "19200" },
185 { B38400, "38400" },
186 { B57600, "57600" },
187 { B115200, "115200" },
188 { B230400, "230400" },
189 { B460800, "460800" },
190 { B500000, "500000" },
191 { B576000, "576000" },
192 { B921600, "921600" },
193 { B1000000, "1000000" },
194 { B1152000, "1152000" },
195 { B1500000, "1500000" },
196 { B2000000, "2000000" },
197 { B2500000, "2500000" },
198 { B3000000, "3000000" },
199 { B3500000, "3500000" },
200 { B4000000, "4000000" },
201 };
202 const size_t num_terminal_speeds = sizeof(terminal_speeds) /
203 sizeof(struct terminal_speed_name);
204 size_t i;
205
206 for (i = 0; i < num_terminal_speeds; i++) {
207 if (strcmp(baud_string, terminal_speeds[i].name) == 0) {
208 *speed = terminal_speeds[i].speed;
209 return 0;
210 }
211 }
212 return -1;
213}
214
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800215#ifdef CONFIG_TEST
216int main(void)
217{
218 struct config_item *item;
219 struct config *config;
220
221 config = config_init_fd(STDIN_FILENO, "<stdin>");
222 if (!config)
223 return EXIT_FAILURE;
224
225 for (item = config->items; item; item = item->next)
226 printf("%s: %s\n", item->name, item->value);
227
228 config_fini(config);
229
230 return EXIT_SUCCESS;
231
232}
233#endif