aboutsummaryrefslogtreecommitdiff
path: root/src/conf.c
blob: abb1b92dc1249299858885223acf87daf555bdee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* conf.c - config file parser */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* strchrnul */
#endif
#include "config.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "src/conf.h"

#ifdef TARGET_OS_NETBSD
#include "src/common/android.h" // XXX: Dirty hack - make this more generic later
#endif

#ifdef TARGET_OS_OPENBSD
#include "src/common/android.h" // XXX: Dirty hack - make this more generic later
#endif

#ifdef TARGET_OS_DRAGONFLYBSD
#include "src/common/android.h" // XXX: Dirty hack - make this more generic later
#endif

#ifdef TARGET_OS_HAIKU
#include "src/common/android.h" // XXX: Dirty hack - make this more generic later
#endif

#ifdef TARGET_OS_FREEBSD
#ifndef HAVE_STRCHRNUL
#include "src/common/android.h" // XXX: Dirty hack - make this more generic later
#endif
#endif

#ifdef HAVE_ANDROID
#include "src/common/android.h"
#endif

void strip_newlines (char *line)
{
  *strchrnul (line, '\n') = '\0';
  *strchrnul (line, '\r') = '\0';
}

char *eat_whitespace (char *line)
{
  while (isspace ((int)(unsigned char)*line))
    line++;
  return line;
}

int is_ignored_line (char *line)
{
  return !*line || *line == '#';
}

struct conf_entry *conf_parse (FILE *f)
{
  struct conf_entry *head = NULL;
  struct conf_entry *tail = NULL;
  char buf[CONF_MAX_LINE];

  while (fgets (buf, sizeof (buf), f))
    {
      struct conf_entry *e;
      char *start = buf;
      char *key;
      char *val;
      strip_newlines (start);
      start = eat_whitespace (start);
      if (is_ignored_line (start))
        continue;
      key = strtok (start, " \t");
      val = strtok (NULL, "");
      if (val)
        val = eat_whitespace (val);
      e = malloc (sizeof *e);
      if (!e)
        goto fail;
      e->next = NULL;
      e->key = strdup (key);
      e->value = val ? strdup (val) : NULL;
      if (!e->key || (val && !e->value))
        {
          free (e->key);
          free (e->value);
          goto fail;
        }
      if (!head)
        {
          head = e;
          tail = e;
        }
      else
        {
          tail->next = e;
          tail = e;
        }
    }

  return head;
fail:
  conf_free (head);
  return NULL;
}

void conf_free (struct conf_entry *e)
{
  struct conf_entry *n;
  while (e)
    {
      n = e->next;
      free (e->key);
      free (e->value);
      free (e);
      e = n;
    }
}