Initial import from http://www.droids-corp.org/hg/libcmdline/rev/db316e4289a1
[libcmdline.git] / src / genconf / dotconfig.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <unistd.h>
6 #include <sys/queue.h>
7
8 #include "expression.h"
9 #include "parser_common.h"
10 #include "conf_parser.h"
11 #include "confnode.h"
12 #include "conf_htable.h"
13
14 int dotconfig_parse_line(const char *line)
15 {
16         struct confnode *opt;
17         char buf[BUFSIZ];
18         char *nodename, *s;
19         const char *optval;
20         char wait_char = '=';
21
22         /* copy line in a writable buffer */
23         buf[sizeof(buf) - 1] = '\0';
24         strncpy(buf, line, sizeof(buf) - 1);
25         s = buf;
26
27         while (*s != '\0' && isspace(*s))
28                 s++;
29         /* nothing to do, empty line */
30         if (*s == '\0')
31                 return 0;
32
33         /* skip the first "#", expecting "is not set" */
34         if (*s == '#') {
35                 wait_char = ' ';
36                 s++;
37                 while (*s != '\0' && isspace(*s))
38                         s++;
39                 /* nothing to do, empty line */
40                 if (*s == '\0')
41                         return 0;
42         }
43
44         /* get node name, ignore invalid names */
45         nodename = s;
46         if (strncmp("CONFIG_", nodename, strlen("CONFIG_")))
47                 return 0;
48         nodename += strlen("CONFIG_");
49
50         while (*s != '\0' && *s != wait_char)
51                 s++;
52         /* invalid line */
53         if (*s != wait_char)
54                 return -1;
55
56         *s = '\0';
57
58         /* find the node in the conf htable */
59         opt = conf_htable_lookup(nodename);
60         if (opt == NULL) {
61                 printf("ignore unknown symbol <%s>\n", nodename);
62                 return 0;
63         }
64
65         s++;
66
67         /* "is not set" -> "n" */
68         if (wait_char == ' ') {
69                 if (strcmp(s, "is not set\n"))
70                         return 0;
71                 optval = "n";
72         }
73         else {
74                 if (*s == '"')
75                         s ++;
76                 optval = s;
77                 /* erase the cariage return */
78                 while (*s != '\0' && *s != '\n') {
79                         if (*s == '"' && *(s-1) != '\\') {
80                                 *s = '\0';
81                                 break;
82                         }
83                         s++;
84                 }
85                 *s = '\0';
86         }
87
88         /* set its value in the conf tree */
89         if (confnode_set_user_strvalue(opt, optval) < 0) {
90                 printf("cannot assign value to node <%s>: %s\n", nodename, optval);
91                 return -1;
92         }
93
94         return 0;
95 }
96
97 /* parse .config */
98 int dotconfig_read(const char *filename, struct confnode *conf)
99 {
100         FILE *f;
101         char buf[BUFSIZ];
102         int err = 0;
103
104         f = fopen(filename, "r");
105         if (f == NULL) {
106                 printf("cannot find file <%s>\n", filename);
107                 return -1;
108         }
109         while (fgets(buf, sizeof(buf), f) != NULL) {
110
111                 if (dotconfig_parse_line(buf) < 0) {
112                         err = -1;
113                         break;
114                 }
115         }
116         fclose(f);
117
118         return err;
119 }
120
121 /* write .config */
122 int dotconfig_write(const char *filename, const struct confnode *conf)
123 {
124         FILE *f;
125         const struct confnode *c;
126
127         f = fopen(filename, "w");
128         if (f == NULL) {
129                 printf("cannot open file <%s>\n", filename);
130                 return -1;
131         }
132
133         /* dump all the children of root node */
134         TAILQ_FOREACH(c, &conf->children, next) {
135                 confnode_dotconfig_write(c, f);
136         }
137
138         fclose(f);
139
140         return 0;
141 }
142