]>
Commit | Line | Data |
---|---|---|
75ae2191 MT |
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. | |
66c36198 | 8 | * |
75ae2191 MT |
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 | |
66c36198 | 12 | * |
75ae2191 | 13 | */ |
66c36198 | 14 | |
75ae2191 MT |
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)); | |
66c36198 | 22 | |
75ae2191 MT |
23 | strcpy(head->key, "KEY"); |
24 | strcpy(head->value, "VALUE"); | |
25 | head->next = NULL; | |
66c36198 | 26 | |
75ae2191 MT |
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; | |
66c36198 | 35 | |
75ae2191 MT |
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; | |
66c36198 | 52 | |
75ae2191 MT |
53 | if (!(file = fopen(filename, "r"))) |
54 | return 0; | |
66c36198 | 55 | |
75ae2191 MT |
56 | if (flock(fileno(file), LOCK_SH)) |
57 | { | |
58 | fclose(file); | |
59 | return 0; | |
60 | } | |
66c36198 | 61 | |
75ae2191 MT |
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 | } | |
66c36198 | 97 | |
75ae2191 MT |
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; | |
66c36198 | 109 | |
75ae2191 MT |
110 | if (!(file = fopen(filename, "w"))) |
111 | return 0; | |
66c36198 | 112 | |
75ae2191 MT |
113 | if (flock(fileno(file), LOCK_EX)) |
114 | { | |
115 | fclose(file); | |
116 | return 0; | |
117 | } | |
66c36198 PM |
118 | |
119 | ||
75ae2191 MT |
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); | |
66c36198 | 132 | |
75ae2191 MT |
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 | } |