blob: 750f8c9a02379075175c027bd53b674314a20bfa [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>
24#include <unistd.h>
25
26#include <sys/mman.h>
27#include <sys/stat.h>
28
Jeremy Kerre440a402016-03-17 16:34:14 +080029static const char *config_default_filename = SYSCONFDIR "/obmc-console.conf";
Jeremy Kerrd66195c2016-03-16 17:24:51 +080030
31struct config_item {
32 char *name;
33 char *value;
34 struct config_item *next;
35};
36
37struct config {
38 struct config_item *items;
39};
40
41const char *config_get_value(struct config *config, const char *name)
42{
43 struct config_item *item;
44
45 for (item = config->items; item; item = item->next)
46 if (!strcasecmp(item->name, name))
47 return item->value;
48
49 return NULL;
50}
51
52static void config_parse(struct config *config, char *buf)
53{
54 struct config_item *item;
55 char *name, *value;
56 char *p, *line;
57 int rc;
58
59 for (p = NULL, line = strtok_r(buf, "\n", &p); line;
60 line = strtok_r(NULL, "\n", &p)) {
61
62 /* trim leading space */
63 for (;*line == ' ' || *line == '\t'; line++)
64 ;
65
66 /* skip comments */
67 if (*line == '#')
68 continue;
69
70 name = value = NULL;
71
72 rc = sscanf(line, "%m[^ =] = %ms ", &name, &value);
73 if (rc != 2 || !strlen(name) || !strlen(value)) {
74 free(name);
75 free(value);
76 continue;
77 }
78
79 /* create a new item and add to our list */
80 item = malloc(sizeof(*item));
81 item->name = name;
82 item->value = value;
83 item->next = config->items;
84 config->items = item;
85 }
86}
87
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080088static struct config *config_init_fd(int fd, const char *filename)
Jeremy Kerrd66195c2016-03-16 17:24:51 +080089{
90 struct config *config;
Jeremy Kerr2eb56f52016-03-17 14:55:14 +080091 size_t size, len;
Jeremy Kerr2eb56f52016-03-17 14:55:14 +080092 char *buf;
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080093 int rc;
Jeremy Kerrd66195c2016-03-16 17:24:51 +080094
Jeremy Kerr2eb56f52016-03-17 14:55:14 +080095 size = 4096;
96 len = 0;
97 buf = malloc(size + 1);
Jeremy Kerr6c8d7812016-03-17 15:05:45 +080098 config = NULL;
Jeremy Kerrd66195c2016-03-16 17:24:51 +080099
Jeremy Kerr2eb56f52016-03-17 14:55:14 +0800100 for (;;) {
101 rc = read(fd, buf + len, size - len);
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800102 if (rc < 0) {
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800103 warn("Can't read from configuration file %s", filename);
104 goto out_free;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800105
106 } else if (!rc) {
107 break;
108 }
Jeremy Kerr2eb56f52016-03-17 14:55:14 +0800109 len += rc;
110 if (len == size) {
111 size <<= 1;
112 buf = realloc(buf, size + 1);
113 }
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800114
115 }
116 buf[len] = '\0';
117
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800118 config = malloc(sizeof(*config));
119 config->items = NULL;
120
121 config_parse(config, buf);
122
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800123out_free:
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800124 free(buf);
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800125 return config;
126}
127
128struct config *config_init(const char *filename)
129{
130 struct config *config;
131 int fd;
132
133 if (!filename)
134 filename = config_default_filename;
135
136 fd = open(filename, O_RDONLY);
137 if (fd < 0) {
138 warn("Can't open configuration file %s", filename);
139 return NULL;
140 }
141
142 config = config_init_fd(fd, filename);
143
144 close(fd);
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800145
146 return config;
Jeremy Kerrd66195c2016-03-16 17:24:51 +0800147}
148
149void config_fini(struct config *config)
150{
151 struct config_item *item, *next;
152
153 for (item = config->items; item; item = next) {
154 next = item->next;
155 free(item->name);
156 free(item->value);
157 free(item);
158 }
159
160 free(config);
161}
Jeremy Kerr6c8d7812016-03-17 15:05:45 +0800162
163#ifdef CONFIG_TEST
164int main(void)
165{
166 struct config_item *item;
167 struct config *config;
168
169 config = config_init_fd(STDIN_FILENO, "<stdin>");
170 if (!config)
171 return EXIT_FAILURE;
172
173 for (item = config->items; item; item = item->next)
174 printf("%s: %s\n", item->name, item->value);
175
176 config_fini(config);
177
178 return EXIT_SUCCESS;
179
180}
181#endif