1deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering/***
2deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  This file is part of avahi.
3a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  avahi is free software; you can redistribute it and/or modify it
5deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  under the terms of the GNU Lesser General Public License as
6deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  published by the Free Software Foundation; either version 2.1 of the
7deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  License, or (at your option) any later version.
8a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
9deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
10deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  Public License for more details.
13a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
14deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  You should have received a copy of the GNU Lesser General Public
15deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  License along with avahi; if not, write to the Free Software
16deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering  USA.
18deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering***/
19deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
2015f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering#ifdef HAVE_CONFIG_H
2115f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering#include <config.h>
2215f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering#endif
2315f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering
24deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <stdio.h>
25deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <string.h>
26deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <errno.h>
27e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering#include <ctype.h>
28deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
298e46e738cae449bf44232c66e973c8e9e15fbcb5Robert Ginda#include "avahi-common/avahi-malloc.h"
30deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <avahi-core/log.h>
31deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
32deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include "ini-file-parser.h"
33deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
34deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart PoetteringAvahiIniFile* avahi_ini_file_load(const char *fname) {
35deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    AvahiIniFile *f;
36deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    FILE *fo;
37deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    AvahiIniFileGroup *group = NULL;
38deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    unsigned line;
39a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
40deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    assert(fname);
41deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
42deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    if (!(fo = fopen(fname, "r"))) {
43deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        avahi_log_error("Failed to open file '%s': %s", fname, strerror(errno));
44deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        return NULL;
45deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    }
46a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
47deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    f = avahi_new(AvahiIniFile, 1);
48deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    AVAHI_LLIST_HEAD_INIT(AvahiIniFileGroup, f->groups);
49deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    f->n_groups = 0;
50deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
51deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    line = 0;
52deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    while (!feof(fo)) {
53deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        char ln[256], *s, *e;
54deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        AvahiIniFilePair *pair;
55a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
56deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        if (!(fgets(ln, sizeof(ln), fo)))
57deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            break;
58deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
59deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        line++;
60a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
61deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        s = ln + strspn(ln, " \t");
62deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        s[strcspn(s, "\r\n")] = 0;
63deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
64deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        /* Skip comments and empty lines */
65deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        if (*s == '#' || *s == '%' || *s == 0)
66deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            continue;
67deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
68deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        if (*s == '[') {
69deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            /* new group */
70a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
71deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            if (!(e = strchr(s, ']'))) {
72deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering                avahi_log_error("Unclosed group header in %s:%u: <%s>", fname, line, s);
73deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering                goto fail;
74deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            }
75deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
76deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            *e = 0;
77a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
78deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            group = avahi_new(AvahiIniFileGroup, 1);
79deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            group->name = avahi_strdup(s+1);
80deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            group->n_pairs = 0;
81deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            AVAHI_LLIST_HEAD_INIT(AvahiIniFilePair, group->pairs);
82a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
83deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            AVAHI_LLIST_PREPEND(AvahiIniFileGroup, groups, f->groups, group);
84deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            f->n_groups++;
85deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        } else {
86deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
87deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            /* Normal assignment */
88deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            if (!(e = strchr(s, '='))) {
89deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering                avahi_log_error("Missing assignment in %s:%u: <%s>", fname, line, s);
90deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering                goto fail;
91deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            }
92a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
93deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            if (!group) {
94deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering                avahi_log_error("Assignment outside group in %s:%u <%s>", fname, line, s);
95deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering                goto fail;
96deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            }
97a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
98deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            /* Split the key and the value */
99deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            *(e++) = 0;
100a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
101deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            pair = avahi_new(AvahiIniFilePair, 1);
102deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            pair->key = avahi_strdup(s);
103deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            pair->value = avahi_strdup(e);
104a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
105deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            AVAHI_LLIST_PREPEND(AvahiIniFilePair, pairs, group->pairs, pair);
106deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            group->n_pairs++;
107deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        }
108deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    }
109a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
110deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    fclose(fo);
111a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
112deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    return f;
113deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
114deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringfail:
115deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
116deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    if (fo)
117deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        fclose(fo);
118deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
119deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    if (f)
120deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        avahi_ini_file_free(f);
121deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
122deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    return NULL;
123deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering}
124deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
125deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringvoid avahi_ini_file_free(AvahiIniFile *f) {
126deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    AvahiIniFileGroup *g;
127deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    assert(f);
128deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
129deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    while ((g = f->groups)) {
130deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        AvahiIniFilePair *p;
131a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
132deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        while ((p = g->pairs)) {
133deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            avahi_free(p->key);
134deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            avahi_free(p->value);
135deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
136deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            AVAHI_LLIST_REMOVE(AvahiIniFilePair, pairs, g->pairs, p);
137deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            avahi_free(p);
138deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        }
139deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
140deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        avahi_free(g->name);
141deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
142deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        AVAHI_LLIST_REMOVE(AvahiIniFileGroup, groups, f->groups, g);
143deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        avahi_free(g);
144deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    }
145deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
146deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    avahi_free(f);
147deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering}
148deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
149deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringchar** avahi_split_csv(const char *t) {
150deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    unsigned n_comma = 0;
151deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    const char *p;
152deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    char **r, **i;
153deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
154deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    for (p = t; *p; p++)
155deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        if (*p == ',')
156deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            n_comma++;
157deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
158deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    i = r = avahi_new(char*, n_comma+2);
159deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
160deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    for (;;) {
161e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        size_t n, l = strcspn(t, ",");
162e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        const char *c;
163deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
164e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        /* Ignore leading blanks */
165e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        for (c = t, n = l; isblank(*c); c++, n--);
166e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering
167e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        /* Ignore trailing blanks */
168e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        for (; n > 0 && isblank(c[n-1]); n--);
169e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering
170e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering        *(i++) = avahi_strndup(c, n);
171deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
172deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        t += l;
173deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
174deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        if (*t == 0)
175deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering            break;
176deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
177deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        assert(*t == ',');
178deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        t++;
179deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    }
180deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
181deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    *i = NULL;
182deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
183deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    return r;
184deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering}
185deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
186deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringvoid avahi_strfreev(char **p) {
187deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    char **i;
188deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
189deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    if (!p)
190deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        return;
191a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
192deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    for (i = p; *i; i++)
193deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering        avahi_free(*i);
194deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering
195deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering    avahi_free(p);
196deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering}
197