2 * Copyright (C) 2013-2014 Intel Corporation.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * José Bollo <jose.bollo@open.eurogiciel.org>
20 * Stéphane Desneux <stephane.desneux@open.eurogiciel.org>
21 * Jean-Benoit Martin <jean-benoit.martin@open.eurogiciel.org>
35 #include <sys/types.h>
44 #ifndef NOT_MULTI_THREAD_SAFE
49 #define CONFIGPATH "/etc/tizen-platform.conf"
52 #include "tzplatform_variables.h"
53 #include "tzplatform_config.h"
64 #define _HAS_IDS_ (_FOREIGN_HAS_(UID) \
65 || _FOREIGN_HAS_(EUID) \
66 || _FOREIGN_HAS_(GID))
68 #define _HAS_PWS_ (_FOREIGN_HAS_(HOME) \
69 || _FOREIGN_HAS_(USER) \
70 || _FOREIGN_HAS_(EHOME) \
71 || _FOREIGN_HAS_(EUSER))
73 /* local and static variables */
74 static const char metafilepath[] = CONFIGPATH;
75 static const char emptystring[] = "";
77 /* structure for reading config files */
80 struct tzplatform_context *context;
81 size_t dynvars[_FOREIGN_COUNT_];
82 size_t offsets[_TZPLATFORM_VARIABLES_COUNT_];
85 /* write the error message */
86 static void writerror(const char *format, ...)
89 fprintf(stderr, "tzplatform_config ERROR: ");
91 vfprintf(stderr, format, ap);
93 fprintf(stderr, "\n");
97 /* fill the foreign variables for ids */
98 static void foreignid(struct reading *reading)
103 #if _FOREIGN_HAS_(UID)
105 if (reading->dynvars[UID] == HNULL) {
106 n = snprintf(buffer, sizeof buffer, "%d", (int)get_uid(reading->context));
107 if (0 < n && n < (int)(sizeof buffer))
108 reading->dynvars[UID] = heap_strndup(&reading->context->heap, buffer, (size_t)n);
112 #if _FOREIGN_HAS_(EUID)
114 if (reading->dynvars[EUID] == HNULL) {
115 n = snprintf(buffer, sizeof buffer, "%d", (int)get_euid(reading->context));
116 if (0 < n && n < (int)(sizeof buffer))
117 reading->dynvars[EUID] = heap_strndup(&reading->context->heap, buffer, (size_t)n);
121 #if _FOREIGN_HAS_(GID)
123 if (reading->dynvars[GID] == HNULL) {
124 n = snprintf(buffer, sizeof buffer, "%d", (int)get_gid(reading->context));
125 if (0 < n && n < (int)(sizeof buffer))
126 reading->dynvars[GID] = heap_strndup(&reading->context->heap, buffer, (size_t)n);
133 /* fill the foreign variables for home and user */
134 static void foreignpw(struct reading *reading)
137 struct pwget *array[3];
138 #if _FOREIGN_HAS_(HOME) || _FOREIGN_HAS_(USER)
142 #if _FOREIGN_HAS_(EHOME) || _FOREIGN_HAS_(EUSER)
147 #if _FOREIGN_HAS_(HOME) || _FOREIGN_HAS_(USER)
149 #if _FOREIGN_HAS_(HOME)
150 reading->dynvars[HOME] == HNULL
152 #if _FOREIGN_HAS_(HOME) && _FOREIGN_HAS_(USER)
155 #if _FOREIGN_HAS_(USER)
156 reading->dynvars[USER] == HNULL
159 snprintf(suid, sizeof suid, "%u", (unsigned)get_uid(reading->context));
167 #if _FOREIGN_HAS_(EHOME) || _FOREIGN_HAS_(EUSER)
169 #if _FOREIGN_HAS_(EHOME)
170 reading->dynvars[EHOME] == HNULL
172 #if _FOREIGN_HAS_(EHOME) && _FOREIGN_HAS_(USER)
175 #if _FOREIGN_HAS_(EUSER)
176 reading->dynvars[EUSER] == HNULL
179 snprintf(seuid, sizeof seuid, "%u", (unsigned)get_euid(reading->context));
189 if (pw_get(&reading->context->heap, array) == 0) {
190 #if _FOREIGN_HAS_(HOME)
192 reading->dynvars[HOME] = uid.home;
194 #if _FOREIGN_HAS_(USER)
196 reading->dynvars[USER] = uid.user;
198 #if _FOREIGN_HAS_(EHOME)
200 reading->dynvars[EHOME] = euid.home;
202 #if _FOREIGN_HAS_(EUSER)
204 reading->dynvars[EUSER] = euid.user;
211 /* get the foreign variable */
212 static const char *foreignvar(struct reading *reading,
213 const char *name, size_t length)
215 enum fkey key = foreign(name, length);
220 #if _FOREIGN_HAS_(HOME)
223 #if _FOREIGN_HAS_(USER)
226 #if _FOREIGN_HAS_(EHOME)
229 #if _FOREIGN_HAS_(EUSER)
237 #if _FOREIGN_HAS_(UID)
240 #if _FOREIGN_HAS_(GID)
243 #if _FOREIGN_HAS_(EUID)
253 offset = reading->dynvars[key];
254 return (offset == HNULL) ? NULL : heap_address(&reading->context->heap, offset);
257 /* callback for parsing errors */
258 static int errcb(struct parsing *parsing,
259 size_t position, const char *message)
261 struct parsinfo info;
262 struct reading *reading = parsing->data;
264 /* count the error */
267 /* print the error */
268 parse_utf8_info(parsing, &info, position);
269 writerror("%s (file %s line %d)", message, metafilepath, info.lino);
271 /* continue to parse */
275 /* callback for solving variables */
276 static const char *getcb(struct parsing *parsing,
277 const char *key, size_t length,
278 size_t begin_pos, size_t end_pos)
280 struct parsinfo info;
283 struct reading *reading = parsing->data;
286 /* try to find a tzplatform variable */
287 id = hashid(key, length);
289 /* found: try to use it */
290 offset = reading->offsets[id];
292 result = heap_address(&reading->context->heap, offset);
296 /* that is a foreign variable */
297 result = foreignvar(reading, key, length);
300 /* emit the error and then return */
301 if (result == NULL) {
303 parse_utf8_info(parsing, &info, begin_pos);
304 writerror("undefined value for %.*s (file %s line %d)",
305 length, key, metafilepath, info.lino);
306 result = emptystring; /* avoid error of the parser */
311 /* callback to define variables */
312 static int putcb(struct parsing *parsing,
313 const char *key, size_t key_length,
314 const char *value, size_t value_length,
315 size_t begin_pos, size_t end_pos)
317 struct parsinfo info;
320 struct reading *reading = parsing->data;
323 /* try to find a tzplatform variable */
324 id = hashid(key, key_length);
326 /* check that the variable isn't already defined */
327 offset = reading->offsets[id];
328 if (offset != HNULL) {
330 parse_utf8_info(parsing, &info, begin_pos);
331 writerror("redefinition of variable %.*s (file %s line %d)",
332 key_length, key, metafilepath, info.lino);
335 /* allocate the variable value */
336 offset = heap_alloc(&reading->context->heap, value_length+1);
337 if (offset == HNULL) {
338 /* error of allocation */
340 writerror("out of memory");
342 /* record the variable value */
343 reading->offsets[id] = offset;
344 string = heap_address(&reading->context->heap, offset);
345 memcpy(string, value, value_length);
346 string[value_length] = 0;
349 /* forbidden variable */
350 parse_utf8_info(parsing, &info, begin_pos);
351 writerror("forbidden variable name %.*s (file %s line %d)",
352 key_length, key, metafilepath, info.lino);
355 /* continue to parse */
359 /* initialize the environment */
360 void initialize(struct tzplatform_context *context)
362 struct buffer buffer;
363 struct parsing parsing;
364 struct reading reading;
368 /* clear the variables */
369 reading.errcount = 0;
370 reading.context = context;
371 for (i = 0 ; i < (int)_FOREIGN_COUNT_ ; i++)
372 reading.dynvars[i] = HNULL;
374 for (i = 0 ; i < (int)_TZPLATFORM_VARIABLES_COUNT_ ; i++) {
375 context->values[i] = NULL;
376 reading.offsets[i] = HNULL;
379 /* read the configuration file */
380 result = buffer_create(&buffer, metafilepath);
382 writerror("can't read file %s", metafilepath);
383 context->state = ERROR;
387 /* create the heap */
388 result = heap_create(&context->heap, 1);
390 buffer_destroy(&buffer);
391 writerror("out of memory");
392 context->state = ERROR;
397 parsing.buffer = buffer.buffer;
398 parsing.length = buffer.length;
399 parsing.maximum_data_size = 0;
400 parsing.should_escape = 0;
401 parsing.data = &reading;
404 parsing.error = errcb;
405 result = parse_utf8_config(&parsing);
406 buffer_destroy(&buffer);
407 if (result != 0 || reading.errcount != 0) {
408 writerror("%d errors while parsing file %s",
409 reading.errcount, metafilepath);
412 /* set the variables */
413 heap_read_only(&context->heap);
414 for (i = 0 ; i < (int)_TZPLATFORM_VARIABLES_COUNT_ ; i++) {
415 offset = reading.offsets[i];
417 context->values[i] = heap_address(&context->heap, offset);
419 writerror("the variable %s isn't defined in file %s",
420 keyname(i), metafilepath);
421 /* TODO undefined variable */;
423 context->state = VALID;