]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/libsmooth/varval.c
libsmooth: Make it its own package.
[ipfire-2.x.git] / src / libsmooth / varval.c
diff --git a/src/libsmooth/varval.c b/src/libsmooth/varval.c
new file mode 100644 (file)
index 0000000..9a64365
--- /dev/null
@@ -0,0 +1,197 @@
+/* SmoothWall libsmooth.
+ *
+ * This program is distributed under the terms of the GNU General Public
+ * Licence.  See the file COPYING for details.
+ *
+ * (c) Lawrence Manning, 2001
+ * Contains functions for manipulation files full of VAR=VAL pairs.
+ * 
+ * 2003-07-27 Robert Kerr - Added cooperative file locking to prevent any
+ * clashes between setuid programs reading configuration and cgi scripts
+ * trying to write it
+ * 
+ */
+#include "libsmooth.h"
+
+/* Sets up the list.  First entry is a dummy one to avoid having to special
+ * case empty lists. */
+struct keyvalue *initkeyvalues(void)
+{
+       struct keyvalue *head = malloc(sizeof(struct keyvalue));
+       
+       strcpy(head->key, "KEY");
+       strcpy(head->value, "VALUE");
+       head->next = NULL;
+       
+       return head;
+}
+
+/* Splats all the entries in a list. */
+void freekeyvalues(struct keyvalue *head)
+{
+       struct keyvalue *cur = head->next;
+       struct keyvalue *next;
+       
+       while (cur)
+       {
+               next = cur->next;
+               free(cur);
+               cur = next;
+       }
+}
+
+/* Reads from a file into a new list.  Uses appendkeyvalue to add entries.
+ * Will bomb out on a error (eg bad format line). */
+int readkeyvalues(struct keyvalue *head, char *filename)
+{
+       FILE *file;
+       char buffer[STRING_SIZE];
+       char *temp;
+       char *key, *value;
+       
+       if (!(file = fopen(filename, "r")))
+               return 0;
+               
+       if (flock(fileno(file), LOCK_SH))
+       {
+               fclose(file);
+               return 0;
+       }
+       
+       while (fgets(buffer, STRING_SIZE, file))
+       {
+               temp = buffer;
+               while (*temp)
+               {
+                       if (*temp =='\n') *temp = '\0';
+                       temp++;
+               }
+               if (!strlen(buffer))
+                       continue;
+               if (!(temp = strchr(buffer, '=')))
+               {
+                       flock(fileno(file), LOCK_UN);
+                       fclose(file);
+                       return 0;
+               }
+               *temp = '\0';
+               key = buffer; value = temp + 1;
+               /* See if string is quoted.  If so, skip first quote, and
+                * nuke the one at the end. */
+               if (value[0] == '\'')
+               {
+                       value++;
+                       if ((temp = strrchr(value, '\'')))
+                               *temp = '\0';
+                       else
+                       {
+                               flock(fileno(file), LOCK_UN);
+                               fclose(file);
+                               return 0;
+                       }
+               }
+               if (strlen(key))
+                       appendkeyvalue(head, key, value);
+       }
+       
+       flock(fileno(file), LOCK_UN);
+       fclose(file);
+
+       return 1;
+}
+
+/* Writes out a list to a file.  Easy. */
+int writekeyvalues(struct keyvalue *head, char *filename)
+{
+       FILE *file;
+       struct keyvalue *cur = head->next;
+       
+       if (!(file = fopen(filename, "w")))
+               return 0;
+               
+       if (flock(fileno(file), LOCK_EX))
+       {
+               fclose(file);
+               return 0;
+       }
+       
+               
+       while (cur)
+       {
+               /* No space in value?  If there is, we need to quote the value
+                * so the shell can read it. */
+               if (!strchr(cur->value, ' '))
+                       fprintf(file, "%s=%s\n", cur->key, cur->value);
+               else
+                       fprintf(file, "%s=\'%s\'\n", cur->key, cur->value);
+               cur = cur->next;
+       }
+       flock(fileno(file), LOCK_UN);
+       fclose(file);
+       
+       return 1;
+}
+
+/* Finds a key and copies the value back.  value must be at least STRING_SIZE
+ * long. Would be nice to have a func that just returns a pointer to the value?
+ */
+int findkey(struct keyvalue *head, char *key, char *value)
+{
+       struct keyvalue *cur = head->next;
+
+       while (cur)
+       {
+               if (strcmp(key, cur->key) == 0)
+               {
+                       strncpy(value, cur->value, STRING_SIZE);
+                       value[STRING_SIZE-1] = '\0';
+                       return 1;
+               }
+               cur = cur->next;
+       }
+
+       return 0;
+}
+
+/* Appends a entry.  Not very efficent because it rescans the list looking
+ * for the end.  Maybe fix this later. */
+void appendkeyvalue(struct keyvalue *head, char *key, char *value)
+{
+       struct keyvalue *new = malloc(sizeof(struct keyvalue));
+       struct keyvalue *cur = head->next;
+       struct keyvalue *tail = head;
+
+       strncpy(new->key, key, STRING_SIZE);
+       strncpy(new->value, value, STRING_SIZE);
+       new->key[STRING_SIZE-1] = '\0';
+       new->value[STRING_SIZE-1] = '\0';
+       new->next = NULL;
+
+       while (cur)
+       {
+               tail = cur;
+               cur = cur->next;
+       }
+       tail->next = new;
+}
+
+/* Otherwrites a key with a new value, or if it dosn't exist, appends it
+ * on the end. */
+void replacekeyvalue(struct keyvalue *head, char *key, char *value)
+{
+       struct keyvalue *cur = head->next;
+
+       while (cur)
+       {
+               if (strcmp(cur->key, key) == 0)
+               {
+                       strncpy(cur->value, value, STRING_SIZE);
+                       cur->value[STRING_SIZE-1] = '\0';
+                       return;
+               }
+               cur = cur->next;
+       }
+
+       appendkeyvalue(head, key, value);
+}