Author: Bleep <helveytw@home.com>
authorBleep <twhelvey1@home.com>
Thu, 14 Sep 2000 06:53:38 +0000 (06:53 +0000)
committerBleep <twhelvey1@home.com>
Thu, 14 Sep 2000 06:53:38 +0000 (06:53 +0000)
Log message: rewrite conf parser, fix logic bug, add struct

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@286 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/s_conf.h
ircd/listener.c
ircd/s_conf.c

index b3bf71fc11ec2e9648e5df8d3c3561c8ecc24e69..19d4f03c7e135e76875a34c70f2cbbfbcceded44 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2000-09-14  Thomas Helvey <helveytw@home.com>
+       * ircd/s_conf.c (conf_init): rewrite conf file parser, start to break
+       up conf_init into managable chunks.
+       * ircd/listener.c (set_listener_mask): fix logic bug core dump.
+       * include/s_conf.h: add new data struct for local info (unwinding the mess).
+
 2000-09-13  Thomas Helvey <helveytw@home.com>
        * ircd/list.c: put Clients in free lists, pre-allocate MAXCONNECTIONS
        local clients.
 #
 # ChangeLog for ircu2.10.11
 #
-# $Id: ChangeLog,v 1.160 2000-09-13 07:55:55 bleep Exp $
+# $Id: ChangeLog,v 1.161 2000-09-14 06:53:37 bleep Exp $
 #
 # Insert new changes at beginning of the change list.
 #
index 62a7f39e4e81dbb2e1e95e5ac41cb134d937bd8b..5059efd973cca1af425f0947e4dbdc1985f4196b 100644 (file)
@@ -77,6 +77,19 @@ struct ConfItem {
   struct ConfItem*   next;
 };
 
+/*
+ * A line: A:<line 1>:<line 2>:<line 3>
+ */
+struct LocalConf {
+  char* server_alias;
+  char* vhost_address;
+  char* description;
+  char* numeric_id;
+  char* admin_line1;
+  char* admin_line2;
+  char* admin_line3;
+};
+
 struct MotdItem {
   char line[82];
   struct MotdItem *next;
index 3366052862e71333182c64614f8d38c899f8654d..dedabc3943f2b187e190262173fc263a63586a18 100644 (file)
@@ -244,7 +244,7 @@ static void set_listener_mask(struct Listener* listener, const char* mask)
 
   assert(0 != listener);
 
-  if (EmptyString(mask) && strcmp(mask,"*")!=0) {
+  if (EmptyString(mask) || 0 != strcmp(mask, "*")) {
     listener->mask.s_addr = 0;
     return;
   }
index a6b7d13299b5ab75c74d0e3178393c22694617bf..024997d828976111fb38e91a4412cf3f46f07100 100644 (file)
@@ -926,6 +926,19 @@ int rehash(struct Client *cptr, int sig)
   return ret;
 }
 
+
+/*
+ * If conf line is a class definition, create a class entry
+ * for it and make the conf_line illegal and delete it.
+ */
+void conf_create_class(const char* const* fields, int count)
+{
+  if (count < 6)
+    return;
+  add_class(atoi(fields[1]), atoi(fields[2]), atoi(fields[3]),
+            atoi(fields[4]), atoi(fields[5]));
+}
+
 /*
  * conf_init
  *
@@ -940,70 +953,123 @@ int rehash(struct Client *cptr, int sig)
 
 int conf_init(void)
 {
-  static char quotes[9][2] = {
-    {'b', '\b'},
-    {'f', '\f'},
-    {'n', '\n'},
-    {'r', '\r'},
-    {'t', '\t'},
-    {'v', '\v'},
-    {'\\', '\\'},
-    {0, 0}
-  };
-  char *tmp, *s;
+  enum { MAX_FIELDS = 15 };
+
+  char* src;
+  char* dest;
+  int quoted;
   FBFILE *file;
-  int i;
   char line[512];
   int ccount = 0;
   struct ConfItem *aconf = 0;
+  
+  int   field_count = 0;
+  const char* field_vector[MAX_FIELDS + 1];
 
   Debug((DEBUG_DEBUG, "conf_init: ircd.conf = %s", configfile));
   if (0 == (file = fbopen(configfile, "r"))) {
     return 0;
   }
+
   while (fbgets(line, sizeof(line) - 1, file)) {
-    if ((tmp = strchr(line, '\n')))
-      *tmp = '\0';
+    if ('#' == *line || IsSpace(*line))
+      continue;
+
+    if ((src = strchr(line, '\n')))
+      *src = '\0';
+    
+    if (':' != line[1]) {
+      Debug((DEBUG_ERROR, "Bad config line: %s", line));
+      sendto_op_mask(SNO_OLDSNO,"Bad Config line");
+      continue;
+    }
+
     /*
-     * Do quoting of characters and # detection.
+     * do escapes, quoting, comments, and field breakup in place
+     * in one pass with a poor mans state machine
      */
-    for (tmp = line; *tmp; tmp++) {
-      if (*tmp == '\\') {
-        for (i = 0; quotes[i][0]; i++) {
-          if (quotes[i][0] == *(tmp + 1)) {
-            *tmp = quotes[i][1];
-            break;
-          }
-        }
-        if (!quotes[i][0])
-          *tmp = *(tmp + 1);
-        if (!*(tmp + 1))
+    field_vector[0] = line;
+    field_count = 1;
+    quoted = 0;
+
+    for (src = line, dest = line; *src; ) {
+      switch (*src) {
+      case '\\':
+        ++src;
+        switch (*src) {
+        case 'b':
+          *dest++ = '\b';
+          ++src;
+          break;
+        case 'f':
+          *dest++ = '\f';
+          ++src;
           break;
+        case 'n':
+          *dest++ = '\n';
+          ++src;
+          break;
+        case 'r':
+          *dest++ = '\r';      
+          ++src;
+          break;
+        case 't':
+          *dest++ = '\t';
+          ++src;
+          break;
+        case 'v':
+          *dest++ = '\v';
+          ++src;
+          break;
+        case '\\':
+          *dest++ = '\\';
+          ++src;
+          break;
+        case '\0':
+          break;
+        default:
+          *dest++ = *src++;
+          break;
+        }
+        break;
+      case '"':
+        if (quoted)
+          quoted = 0;
+        else
+          quoted = 1;
+        *dest++ = *src++;
+        break;
+      case ':':
+        if (quoted)
+          *dest++ = *src++;
         else {
-          for (s = tmp; (*s = *(s + 1)); s++)
-            ;
+          *dest++ = '\0';
+          field_vector[field_count++] = dest;
+          if (field_count > MAX_FIELDS)
+            *src = '\0';
+          else  
+            ++src;
         }
+        break;
+      case '#':
+        *src = '\0';
+        break;
+      default:
+        *dest++ = *src++;
+        break;
       }
-      else if (*tmp == '#')
-        *tmp = '\0';
     }
-    if (!*line || line[0] == '#' || line[0] == '\n' ||
-        line[0] == ' ' || line[0] == '\t')
-      continue;
-    /* Could we test if it's conf line at all?      -Vesa */
-    if (line[1] != ':') {
-      Debug((DEBUG_ERROR, "Bad config line: %s", line));
-      sendto_op_mask(SNO_OLDSNO,"Bad Config line");
+    *dest = '\0';
+
+    if (field_count < 3 || EmptyString(field_vector[0]))
       continue;
-    }
+
     if (aconf)
       free_conf(aconf);
+
     aconf = make_conf();
 
-    tmp = getfield(line, ':');
-    if (!tmp)
-      continue;
-    switch (*tmp) {
+    switch (*field_vector[0]) {
     case 'A':                /* Name, e-mail address of administrator */
     case 'a':                /* of this server. */
       aconf->status = CONF_ADMIN;
@@ -1067,54 +1133,44 @@ int conf_init(void)
       aconf->status = CONF_UWORLD;
       break;
     case 'Y':
-    case 'y':
-      aconf->status = CONF_CLASS;
+    case 'y':      /* CONF_CLASS */
+      conf_create_class(field_vector, field_count);
+      aconf->status = CONF_ILLEGAL;
       break;
     default:
       Debug((DEBUG_ERROR, "Error in config file: %s", line));
-      sendto_op_mask(SNO_OLDSNO,"Unknown prefix in config file: %c",*tmp);
+      sendto_op_mask(SNO_OLDSNO,"Unknown prefix in config file: %c", *field_vector[0]);
+      aconf->status = CONF_ILLEGAL;
       break;
     }
     if (IsIllegal(aconf))
       continue;
 
-    for (;;) {            /* Fake loop, that I can use break here --msa */
-      if ((tmp = getfield(NULL, ':')) == NULL)
-        break;
-      DupString(aconf->host, tmp);
-      if ((tmp = getfield(NULL, (aconf->status == CONF_KILL
-          || aconf->status == CONF_IPKILL) ? '"' : ':')) == NULL)
-        break;
-      DupString(aconf->passwd, tmp);
-      if ((tmp = getfield(NULL, ':')) == NULL)
-        break;
-      DupString(aconf->name, tmp);
-      if ((tmp = getfield(NULL, ':')) == NULL)
-        break;
-      aconf->port = atoi(tmp);
-      tmp = getfield(NULL, ':');
-      if (aconf->status & CONF_ME) {
-        if (!tmp) {
-          Debug((DEBUG_FATAL, "Your M: line must have the Numeric, "
-              "assigned to you by routing-com!\n"));
-          ircd_log(L_WARNING, "Your M: line must have the Numeric, "
-              "assigned to you by routing-com!\n");
-          exit(-1);
-        }
-        SetYXXServerName(&me, atoi(tmp));        /* Our Numeric Nick */
-      }
-      else if (tmp)
-        aconf->confClass = find_class(atoi(tmp));
-      break;
+    if (!EmptyString(field_vector[1]))
+      DupString(aconf->host, field_vector[1]);
+
+    if (!EmptyString(field_vector[2]))
+      DupString(aconf->passwd, field_vector[2]);
+
+    if (field_count > 3 && !EmptyString(field_vector[3]))
+        DupString(aconf->name, field_vector[3]);
+
+    if (field_count > 4 && !EmptyString(field_vector[4]))
+        aconf->port = atoi(field_vector[4]); 
+
+    if (field_count > 5 && !EmptyString(field_vector[5])) {
+      int n = atoi(field_vector[5]);
+      if (CONF_ME == (aconf->status & CONF_ME))
+        SetYXXServerName(&me, n);        /* Our Numeric Nick */
+      else
+        aconf->confClass = find_class(n);
     }
-    /*
-     * If conf line is a class definition, create a class entry
-     * for it and make the conf_line illegal and delete it.
-     */
-    if (aconf->status & CONF_CLASS) {
-      add_class(atoi(aconf->host), atoi(aconf->passwd),
-          atoi(aconf->name), aconf->port, tmp ? atoi(tmp) : 0);
-      continue;
+    else if (CONF_ME == (aconf->status & CONF_ME)) {
+      Debug((DEBUG_FATAL, "Your M: line must have the Numeric, "
+             "assigned to you by routing-com!\n"));
+      ircd_log(L_WARNING, "Your M: line must have the Numeric, "
+              "assigned to you by routing-com!\n");
+      exit(-1);
     }
     /*
      * Associate each conf line with a class by using a pointer
@@ -1267,6 +1323,7 @@ int conf_init(void)
   return 1;
 }
 
+
 /* read_tlines 
  * Read info from T:lines into TRecords which include the file 
  * timestamp, the hostmask, and the contents of the motd file