Importing all of DRL, including ulogd and all of its files.
[distributedratelimiting.git] / conffile / conffile.c
diff --git a/conffile/conffile.c b/conffile/conffile.c
new file mode 100644 (file)
index 0000000..bf8b74c
--- /dev/null
@@ -0,0 +1,241 @@
+/* config file parser functions
+ *
+ * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+ *
+ * $Id: conffile.c 4946 2003-09-28 15:19:25Z laforge $
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 
+ *  as published by the Free Software Foundation
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "conffile.h"
+
+#ifdef DEBUG_CONF
+#define DEBUGC(format, args...) fprintf(stderr, format, ## args)
+#else
+#define DEBUGC(format, args...)
+#endif
+
+/* points to config entry with error */
+config_entry_t *config_errce = NULL;
+
+/* Filename of the config file */
+static char *fname = NULL;
+
+/* get_word() - Function to parse a line into words.
+ * Arguments:  line    line to parse
+ *             delim   possible word delimiters
+ *             buf     pointer to buffer where word is returned
+ * Return value:       pointer to first char after word
+ * This function can deal with "" quotes 
+ */
+static char *get_word(char *line, char *not, char *buf)
+{
+       char *p, *start = NULL, *stop = NULL;
+       int inquote = 0;
+
+       for (p = line; *p; p++) {
+               if (*p == '"') {
+                       start  = p + 1;
+                       inquote = 1;
+                       break;
+               }
+               if (!strchr(not, *p)) {
+                       start = p;
+                       break;
+               }
+       }
+       if (!start)
+               return NULL;
+
+       /* determine pointer to one char after word */
+       for (p = start; *p; p++) {
+               if (inquote) {
+                       if (*p == '"') {
+                               stop = p;
+                               break;
+                       }
+               } else {
+                       if (strchr(not, *p)) {
+                               stop = p;
+                               break;
+                       }
+               }
+       }
+       if (!stop)
+               return NULL;
+
+       strncpy(buf, start, (size_t) (stop-start));
+       *(buf + (stop-start)) = '\0';
+
+       /* skip quote character */
+       if (inquote)
+               /* yes, we can return stop + 1. If " was the last 
+                * character in string, it now points to NULL-term */
+               return (stop + 1);
+
+       return stop;
+}
+
+#if 0
+/* do we have a config directive for this name */
+static int config_iskey(char *name)
+{
+       config_entry_t *ce;
+
+       for (ce = config; ce; ce = ce->next) {
+               if (!strcmp(name, ce->key))
+                       return 0;
+       }
+
+       return 1;
+}
+#endif
+
+/***********************************************************************
+ * PUBLIC INTERFACE
+ ***********************************************************************/
+
+/* register config file with us */
+int config_register_file(const char *file)
+{
+       /* FIXME: stat of file */
+       if (fname)
+               return 1;
+
+       fname = (char *) malloc(strlen(file)+1);
+       if (!fname)
+               return -ERROOM;
+
+       strcpy(fname, file);
+
+       return 0;
+}
+
+/* parse config file */
+int config_parse_file(const char *section, config_entry_t *keys)
+{
+       FILE *cfile;
+       char *args;
+       config_entry_t *ce;
+       int err = 0;
+       int found = 0;
+       char linebuf[LINE_LEN+1];
+       char *line = linebuf;
+
+       cfile = fopen(fname, "r");
+       if (!cfile)
+               return -ERROPEN;
+
+       DEBUGC("prasing section [%s]\n", section);
+
+       /* Search for correct section */
+       while (fgets(line, LINE_LEN, cfile)) {
+               char wordbuf[LINE_LEN];
+               char *wordend;
+
+               if (*line == '#')
+                       continue;
+
+               if (!(wordend = get_word(line, " \t\n[]", (char *) wordbuf)))
+                       continue;
+               DEBUGC("word: \"%s\"\n", wordbuf);
+               if (!strcmp(wordbuf, section)) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               fclose(cfile);
+               return -ERRSECTION;
+       }
+
+       /* Parse this section until next section */
+       while (fgets(line, LINE_LEN, cfile))
+       {
+               char wordbuf[LINE_LEN];
+               char *wordend;
+               
+               DEBUGC("line read: %s\n", line);
+               if (*line == '#')
+                       continue;
+
+               if (!(wordend = get_word(line, " =\t\n", (char *) &wordbuf)))
+                       continue;
+
+               if (wordbuf[0] == '[' ) {
+                       DEBUGC("Next section '%s' encountered\n", wordbuf);
+                       break;
+               }
+
+               DEBUGC("parse_file: entering main loop\n");
+               for (ce = keys; ce; ce = ce->next) {
+                       DEBUGC("parse main loop, key: %s\n", ce->key);
+                       if (strcmp(ce->key, (char *) &wordbuf)) {
+                               continue;
+                       }
+
+                       wordend = get_word(wordend, " =\t\n", (char *) &wordbuf);
+                       args = (char *)&wordbuf;
+
+                       if (ce->hit && !(ce->options & CONFIG_OPT_MULTI))
+                       {
+                               DEBUGC("->ce-hit and option not multi!\n");
+                               config_errce = ce;
+                               err = -ERRMULT;
+                               goto cpf_error;
+                       }
+                       ce->hit++;
+
+                       switch (ce->type) {
+                               case CONFIG_TYPE_STRING:
+                                       if (strlen(args) < 
+                                           CONFIG_VAL_STRING_LEN ) {
+                                               strcpy(ce->u.string, args);
+                                               /* FIXME: what if not ? */
+                                       }
+                                       break;
+                               case CONFIG_TYPE_INT:
+                                       ce->u.value = atoi(args);
+                                       break;
+                               case CONFIG_TYPE_CALLBACK:
+                                       (ce->u.parser)(args);
+                                       break;
+                       }
+                       break;
+               }
+               DEBUGC("parse_file: exiting main loop\n");
+       }
+
+
+       for (ce = keys; ce; ce = ce->next) {
+               DEBUGC("ce post loop, ce=%s\n", ce->key);
+               if ((ce->options & CONFIG_OPT_MANDATORY) && (ce->hit == 0)) {
+                       DEBUGC("Mandatory config directive \"%s\" not found\n",
+                               ce->key);
+                       config_errce = ce;
+                       err = -ERRMAND;
+                       goto cpf_error;
+               }
+
+       }
+
+cpf_error:
+       fclose(cfile);
+       return err;
+}
+