]> git.vomp.tv Git - vompserver.git/blob - config.c
Initial import
[vompserver.git] / config.c
1 /*
2     Copyright 2004-2005 Chris Tallon
3     Copyright 2004-2005 University Of Bradford
4
5     This file is part of VOMP.
6
7     VOMP is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     VOMP is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with VOMP; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21
22 #include "config.h"
23
24 Config::Config()
25 {
26   initted = 0;
27   lastLineLength = 0;
28 }
29
30 int Config::init(char* takeFileName)
31 {
32   if (initted) return 1;
33
34   pthread_mutex_init(&fileLock, NULL);
35
36   if (strlen(takeFileName) > (MAX_FILENAME_LENGTH - 1))
37   {
38     printf("Config error: Config filename too long\n");
39     return 0;
40   }
41
42   strcpy(fileName, takeFileName);
43   file = fopen(fileName, "r");
44   if (!file)
45   {
46     file = fopen(fileName, "w");
47     if (!file)
48     {
49       printf("Config error: Could not access config file\n");
50       return 0;
51     }
52   }
53   fclose(file);
54
55   initted = 1;
56
57   return 1;
58 }
59
60 int Config::shutdown()
61 {
62   if (!initted) return 1;
63
64   pthread_mutex_lock(&fileLock);
65   initted = 0;
66   pthread_mutex_unlock(&fileLock);
67   pthread_mutex_destroy(&fileLock);
68
69   return 1;
70 }
71
72 int Config::openFile()
73 {
74   if (!initted) return 0;
75   if (pthread_mutex_lock(&fileLock))
76   {
77     printf("Config error: Could not get lock\n");
78     return 0;
79   }
80   if (!initted)
81   {
82     printf("Config error: Initted 0 after lock\n");
83     pthread_mutex_unlock(&fileLock);
84     return 0;
85   }
86
87   file = fopen(fileName, "r");
88   if (!file)
89   {
90     printf("Config error: Could not open config file\n");
91     pthread_mutex_unlock(&fileLock);
92     return 0;
93   }
94   return 1;
95 }
96
97 void Config::closeFile()
98 {
99   if (!initted) return;
100
101   fclose(file);
102   file = NULL;
103   pthread_mutex_unlock(&fileLock);
104 }
105
106 int Config::readLine()
107 {
108   if (!initted || !file) { printf("1\n"); return 0; }
109   if (!fgets(buffer, BUFFER_LENGTH-1, file)) { printf("2\n"); return 0; }
110   lastLineLength = strlen(buffer);
111   printf("buffer before trim: '%s'\n", buffer);
112   trim(buffer);
113   printf("buffer after trim: '%s'\n", buffer);
114   return 1;
115 }
116
117 // START HERE
118
119 FILE* Config::copyToHere(long position)
120 {
121   strcpy(fileNameTemp, "/tmp/configXXXXXX");
122   int newFileDes = mkstemp(fileNameTemp);
123   FILE* newFile = fdopen(newFileDes, "w");
124
125   if (!newFile) return NULL;
126
127   long newPos = 0;
128   rewind(file);
129
130   while (newPos < position)
131   {
132     fgets(buffer, BUFFER_LENGTH-1, file);
133     fputs(buffer, newFile);
134     newPos += strlen(buffer);
135   }
136   return newFile;
137 }
138
139 int Config::copyRest(FILE* newFile)
140 {
141   if (newFile)
142   {
143     while(fgets(buffer, BUFFER_LENGTH-1, file))
144     {
145       fputs(buffer, newFile);
146     }
147
148     fclose(newFile);
149   }
150   fclose(file);
151   file = NULL;
152
153   if (newFile) rename(fileNameTemp, fileName);
154
155   pthread_mutex_unlock(&fileLock);
156   return 1;
157 }
158
159 int Config::deleteValue(char* section, char* key)
160 {
161   if (!initted) return 0;
162   if (!openFile()) return 0;
163
164   if (!findSection(section))
165   {
166     closeFile();
167     printf("Config error: Section %s not found\n", section);
168     return 0;
169   }
170   if (!findKey(key))
171   {
172     closeFile();
173     printf("Config error: Key %s not found\n", key);
174     return 0;
175   }
176
177   FILE* newFile = copyToHere(ftell(file) - lastLineLength);
178   fgets(buffer, BUFFER_LENGTH-1, file);
179
180   return copyRest(newFile);
181 }
182
183 int Config::setValueLong(char* section, char* key, long newValue)
184 {
185   char longBuffer[50];
186   sprintf(longBuffer, "%li", newValue);
187   return setValueString(section, key, longBuffer);
188 }
189
190 int Config::setValueLongLong(char* section, char* key, long long newValue)
191 {
192   char longBuffer[50];
193   sprintf(longBuffer, "%lli", newValue);
194   return setValueString(section, key, longBuffer);
195 }
196
197 int Config::setValueDouble(char* section, char* key, double newValue)
198 {
199   char doubleBuffer[50];
200   sprintf(doubleBuffer, "%f", newValue);
201   return setValueString(section, key, doubleBuffer);
202 }
203
204 int Config::setValueString(char* section, char* key, char* newValue)
205 {
206   if (!initted) return 0;
207   if (!openFile()) return 0;
208
209   if (findSection(section))
210   {
211     if (findKey(key))
212     {
213       FILE* newFile = copyToHere(ftell(file) - lastLineLength);
214       if (!newFile)
215       {
216         closeFile();
217         printf("Config error: Could not write temp config file\n");
218         return 0;
219       }
220
221       fgets(buffer, BUFFER_LENGTH-1, file);
222       fprintf(newFile, "%s = %s\n", key, newValue);
223       return copyRest(newFile);
224     }
225     else
226     {
227       rewind(file);
228       findSection(section);
229       FILE* newFile = copyToHere(ftell(file));
230       if (!newFile)
231       {
232         closeFile();
233         printf("Config error: Could not write temp config file\n");
234         return 0;
235       }
236
237       fprintf(newFile, "%s = %s\n", key, newValue);
238       return copyRest(newFile);
239     }
240   }
241   else
242   {
243     // section not found
244     fseek(file, 0, SEEK_END);
245     FILE* newFile = copyToHere(ftell(file));
246     if (!newFile)
247     {
248       closeFile();
249       printf("Config error: Could not write temp config file\n");
250       return 0;
251     }
252
253     fprintf(newFile, "[%s]\n%s = %s\n", section, key, newValue);
254     return copyRest(newFile);
255   }
256 }
257
258 char* Config::getSectionKeyNames(char* section, int& numberOfReturns, int& allKeysSize)
259 {
260   numberOfReturns = 0;
261   allKeysSize = 0;
262   char* allKeys = NULL;
263   int allKeysIndex = 0;
264   int keyLength;
265   char* equalspos;
266
267   if (!initted) return NULL;
268   if (!openFile()) return NULL;
269   if (!findSection(section)) return NULL;
270
271   char foundKey[BUFFER_LENGTH];
272
273   while(readLine())
274   {
275     // Is this line a section header? if so, exit
276     if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) break;
277
278     equalspos = strstr(buffer, "=");
279     if (!equalspos) continue;  // if there is no = then it's not a key
280     memcpy(foundKey, buffer, equalspos-buffer);
281     foundKey[equalspos-buffer] = '\0';
282     trim(foundKey);
283     keyLength = strlen(foundKey);
284     allKeysSize += keyLength + 1;
285     allKeys = (char*)realloc(allKeys, allKeysSize);
286     memcpy(&allKeys[allKeysIndex], foundKey, keyLength);
287     allKeysIndex += keyLength;
288     allKeys[allKeysIndex] = '\0';
289     allKeysIndex++;
290     numberOfReturns++;
291   }
292
293   closeFile();
294   return allKeys;
295 }
296
297
298 // END HERE
299
300 int Config::findSection(char* section)
301 {
302   if (!initted || !file) return 0;
303   if (strlen(section) > (BUFFER_LENGTH-2))
304   {
305     printf("Config error: Section given exceeds max length\n");
306     return 0;
307   }
308
309   char toFind[BUFFER_LENGTH];
310   toFind[0] = '[';
311   toFind[1] = '\0';
312   strcat(toFind, section);
313   strcat(toFind, "]");
314
315   while(readLine())
316   {
317     printf("to find '%s' this line '%s'\n", toFind, buffer);
318     if (!strcmp(toFind, buffer)) return 1;
319   }
320   return 0;
321 }
322
323 int Config::findKey(char* key)
324 {
325   if (!initted || !file) return 0;
326
327   if (strlen(key) > (BUFFER_LENGTH-1))
328   {
329     printf("Config error: Key given exceeds max length\n");
330     return 0;
331   }
332
333   char prepForTest[BUFFER_LENGTH];
334
335   // do a rough search first, this could match substrings that we don't want
336   while(readLine())
337   {
338     // Is this line a section header? if so, exit
339     if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) return 0;
340     if (strstr(buffer, key))
341     {
342       // rough search found match
343       char* equalspos = strstr(buffer, "=");
344       if (!equalspos) continue;
345       memcpy(prepForTest, buffer, equalspos-buffer);
346       prepForTest[equalspos-buffer] = '\0';
347       trim(prepForTest);
348
349       if (!strcmp(key, prepForTest))
350       {
351         // in buffer, set all up to equals to space, then trim!
352         for(char* curPos = buffer; curPos <= equalspos; curPos++)
353         {
354           *curPos = ' ';
355         }
356         trim(buffer);
357         return 1;
358       }
359     }
360   }
361   return 0;
362 }
363
364 char* Config::getValueString(char* section, char* key)
365 {
366   if (!initted) return NULL;
367   if (!openFile()) return NULL;
368
369   if (!findSection(section))
370   {
371     closeFile();
372     printf("Config error: Section %s not found\n", section);
373     return 0;
374   }
375   if (!findKey(key))
376   {
377     closeFile();
378     printf("Config error: Key %s not found\n", key);
379     return 0;
380   }
381
382   char* returnString = new char[strlen(buffer)+1];
383   strcpy(returnString, buffer);
384
385   closeFile();
386
387   return returnString;
388 }
389
390 long Config::getValueLong(char* section, char* key, int* failure)
391 {
392   *failure = 1;
393   if (!initted) return 0;
394   if (!openFile()) return 0;
395
396   if (!findSection(section))
397   {
398     closeFile();
399     printf("Config error: Section %s not found\n", section);
400     return 0;
401   }
402   if (!findKey(key))
403   {
404     closeFile();
405     printf("Config error: Key %s not found\n", key);
406     return 0;
407   }
408   *failure = 0;
409
410   char* check;
411   long retVal = strtol(buffer, &check, 10);
412   if ((retVal == 0) && (check == buffer)) *failure = 1;
413   closeFile();
414
415   return retVal;
416 }
417
418 long long Config::getValueLongLong(char* section, char* key, int* failure)
419 {
420   *failure = 1;
421   if (!initted) return 0;
422   if (!openFile()) return 0;
423
424   if (!findSection(section))
425   {
426     closeFile();
427     printf("Config error: Section %s not found\n", section);
428     return 0;
429   }
430   if (!findKey(key))
431   {
432     closeFile();
433     printf("Config error: Key %s not found\n", key);
434     return 0;
435   }
436   *failure = 0;
437
438   char* check;
439   long long retVal = strtoll(buffer, &check, 10);
440   if ((retVal == 0) && (check == buffer)) *failure = 1;
441   closeFile();
442
443   return retVal;
444 }
445
446 double Config::getValueDouble(char* section, char* key, int* failure)
447 {
448   *failure = 1;
449   if (!initted) return 0;
450   if (!openFile()) return 0;
451
452   if (!findSection(section))
453   {
454     closeFile();
455     printf("Config error: Section %s not found\n", section);
456     return 0;
457   }
458   if (!findKey(key))
459   {
460     closeFile();
461     printf("Config error: Key %s not found\n", key);
462     return 0;
463   }
464
465   *failure = 0;
466
467   char* check;
468   double retVal = strtod(buffer, &check);
469   if ((retVal == 0) && (check == buffer)) *failure = 1;
470
471   closeFile();
472
473   return retVal;
474 }
475
476
477
478 void Config::trim(char* str)
479 {
480   int pos, len, start, end;
481
482   // Kill comments
483   len = strlen(str);
484   for(pos = 0; pos < len; pos++)
485   {
486     if ((str[pos] == '#') || (str[pos] == ';'))
487     {
488       // Mod. If #/; is at start of line ok. Else, if it is after a space, ok.
489
490       if ((pos == 0) || (isspace(str[pos - 1])))
491       {
492         str[pos] = '\0';
493         break;
494       }
495
496     }
497   }
498
499   len = strlen(str);
500   end = len;
501   if (!len) return;
502
503   start = 0;
504   while(isspace(str[start])) start++;
505   while(isspace(str[end-1]))
506   {
507     end--;
508     if (end == 0)
509     {
510       str[0] = '\0';
511       return;
512     }
513   }
514   for(pos = start; pos < end; pos++) str[pos - start] = str[pos];
515   str[end - start] = '\0';
516 }