pakfire: use correct tree on x86_64.
[ipfire-2.x.git] / src / libsmooth / varval.c
1 /* SmoothWall libsmooth.
2  *
3  * This program is distributed under the terms of the GNU General Public
4  * Licence.  See the file COPYING for details.
5  *
6  * (c) Lawrence Manning, 2001
7  * Contains functions for manipulation files full of VAR=VAL pairs.
8  * 
9  * 2003-07-27 Robert Kerr - Added cooperative file locking to prevent any
10  * clashes between setuid programs reading configuration and cgi scripts
11  * trying to write it
12  * 
13  */
14  
15 #include "libsmooth.h"
16
17 /* Sets up the list.  First entry is a dummy one to avoid having to special
18  * case empty lists. */
19 struct keyvalue *initkeyvalues(void)
20 {
21         struct keyvalue *head = malloc(sizeof(struct keyvalue));
22         
23         strcpy(head->key, "KEY");
24         strcpy(head->value, "VALUE");
25         head->next = NULL;
26         
27         return head;
28 }
29
30 /* Splats all the entries in a list. */
31 void freekeyvalues(struct keyvalue *head)
32 {
33         struct keyvalue *cur = head->next;
34         struct keyvalue *next;
35         
36         while (cur)
37         {
38                 next = cur->next;
39                 free(cur);
40                 cur = next;
41         }
42 }
43
44 /* Reads from a file into a new list.  Uses appendkeyvalue to add entries.
45  * Will bomb out on a error (eg bad format line). */
46 int readkeyvalues(struct keyvalue *head, char *filename)
47 {
48         FILE *file;
49         char buffer[STRING_SIZE];
50         char *temp;
51         char *key, *value;
52         
53         if (!(file = fopen(filename, "r")))
54                 return 0;
55                 
56         if (flock(fileno(file), LOCK_SH))
57         {
58                 fclose(file);
59                 return 0;
60         }
61         
62         while (fgets(buffer, STRING_SIZE, file))
63         {
64                 temp = buffer;
65                 while (*temp)
66                 {
67                         if (*temp =='\n') *temp = '\0';
68                         temp++;
69                 }
70                 if (!strlen(buffer))
71                         continue;
72                 if (!(temp = strchr(buffer, '=')))
73                 {
74                         flock(fileno(file), LOCK_UN);
75                         fclose(file);
76                         return 0;
77                 }
78                 *temp = '\0';
79                 key = buffer; value = temp + 1;
80                 /* See if string is quoted.  If so, skip first quote, and
81                  * nuke the one at the end. */
82                 if (value[0] == '\'')
83                 {
84                         value++;
85                         if ((temp = strrchr(value, '\'')))
86                                 *temp = '\0';
87                         else
88                         {
89                                 flock(fileno(file), LOCK_UN);
90                                 fclose(file);
91                                 return 0;
92                         }
93                 }
94                 if (strlen(key))
95                         appendkeyvalue(head, key, value);
96         }
97         
98         flock(fileno(file), LOCK_UN);
99         fclose(file);
100
101         return 1;
102 }
103
104 /* Writes out a list to a file.  Easy. */
105 int writekeyvalues(struct keyvalue *head, char *filename)
106 {
107         FILE *file;
108         struct keyvalue *cur = head->next;
109         
110         if (!(file = fopen(filename, "w")))
111                 return 0;
112                 
113         if (flock(fileno(file), LOCK_EX))
114         {
115                 fclose(file);
116                 return 0;
117         }
118         
119                 
120         while (cur)
121         {
122                 /* No space in value?  If there is, we need to quote the value
123                  * so the shell can read it. */
124                 if (!strchr(cur->value, ' '))
125                         fprintf(file, "%s=%s\n", cur->key, cur->value);
126                 else
127                         fprintf(file, "%s=\'%s\'\n", cur->key, cur->value);
128                 cur = cur->next;
129         }
130         flock(fileno(file), LOCK_UN);
131         fclose(file);
132         
133         return 1;
134 }
135
136 /* Finds a key and copies the value back.  value must be at least STRING_SIZE
137  * long. Would be nice to have a func that just returns a pointer to the value?
138  */
139 int findkey(struct keyvalue *head, char *key, char *value)
140 {
141         struct keyvalue *cur = head->next;
142
143         while (cur)
144         {
145                 if (strcmp(key, cur->key) == 0)
146                 {
147                         strncpy(value, cur->value, STRING_SIZE);
148                         value[STRING_SIZE-1] = '\0';
149                         return 1;
150                 }
151                 cur = cur->next;
152         }
153
154         return 0;
155 }
156
157 /* Appends a entry.  Not very efficent because it rescans the list looking
158  * for the end.  Maybe fix this later. */
159 void appendkeyvalue(struct keyvalue *head, char *key, char *value)
160 {
161         struct keyvalue *new = malloc(sizeof(struct keyvalue));
162         struct keyvalue *cur = head->next;
163         struct keyvalue *tail = head;
164
165         strncpy(new->key, key, STRING_SIZE);
166         strncpy(new->value, value, STRING_SIZE);
167         new->key[STRING_SIZE-1] = '\0';
168         new->value[STRING_SIZE-1] = '\0';
169         new->next = NULL;
170
171         while (cur)
172         {
173                 tail = cur;
174                 cur = cur->next;
175         }
176         tail->next = new;
177 }
178
179 /* Otherwrites a key with a new value, or if it dosn't exist, appends it
180  * on the end. */
181 void replacekeyvalue(struct keyvalue *head, char *key, char *value)
182 {
183         struct keyvalue *cur = head->next;
184
185         while (cur)
186         {
187                 if (strcmp(cur->key, key) == 0)
188                 {
189                         strncpy(cur->value, value, STRING_SIZE);
190                         cur->value[STRING_SIZE-1] = '\0';
191                         return;
192                 }
193                 cur = cur->next;
194         }
195
196         appendkeyvalue(head, key, value);
197 }