util-vserver-0.30.208
[util-vserver.git] / vserver-start / configuration.c
diff --git a/vserver-start/configuration.c b/vserver-start/configuration.c
new file mode 100644 (file)
index 0000000..b09c31c
--- /dev/null
@@ -0,0 +1,164 @@
+// $Id: configuration.c,v 1.3 2004/10/19 21:11:10 ensc Exp $    --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//  
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//  
+// 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.
+
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "configuration.h"
+#include "interface.h"
+
+#include <lib_internal/util.h>
+#include <lib_internal/filecfg.h>
+#include <ensc_vector/vector.h>
+#include <lib/internal.h>
+
+#include <dirent.h>
+#include <string.h>
+
+static inline bool
+getSingleInterface(struct Interface *res,
+                  struct Interface const *tmpl,
+                  PathInfo const *basedir, char const *d_entry)
+{
+  PathInfo     ent  = { .d = d_entry, .l = strlen(d_entry) };
+  PathInfo     path = *basedir;
+  char         path_buf[ENSC_PI_APPSZ(path, ent)];
+
+  PathInfo_append(&path, &ent, path_buf);
+  if (!utilvserver_isDirectory(path.d, true))
+    return true;       // skip non-directories
+
+  return Iface_read(res, &path, tmpl);
+}
+
+static inline bool
+getInterfaces(struct Configuration *cfg)
+{
+  ENSC_PI_DECLARE(iface_subdir, "interfaces");
+  PathInfo             ifacepath = cfg->cfgdir;
+  char                 path_buf[ENSC_PI_APPSZ(ifacepath, iface_subdir)];
+  struct Interface     iface_default;
+  DIR                  *dir;
+  bool                 rc = true;
+
+  PathInfo_append(&ifacepath, &iface_subdir, path_buf);
+
+  if (!utilvserver_isDirectory(ifacepath.d, true))
+    return true;       // no interface configuration -> ok
+  
+  Iface_init(&iface_default);
+  if (!Iface_read(&iface_default, &ifacepath, 0))
+    return false;
+
+    // iterate through dir-entries...
+  dir = opendir(ifacepath.d);
+  while (dir!=0) {
+    struct dirent      *ent = readdir(dir);
+    struct Interface   iface;
+    
+    if (ent==0)                 break;
+    if (isDotfile(ent->d_name)) continue;      // skip dot-files
+
+    Iface_init(&iface);
+    if (!getSingleInterface(&iface, &iface_default, &ifacepath, ent->d_name))
+      rc = false;
+    else if (iface.addr.ipv4.ip!=0) {  // HACK: non-directory entries would return true also
+      struct Interface *new_iface = Vector_pushback(&cfg->interfaces);
+      *new_iface = iface;
+    }
+  }
+
+  if (dir!=0)
+    closedir(dir);
+
+  return rc;
+}
+
+static bool
+initVdir(char const **vdir, PathInfo const *cfgdir)
+{
+  *vdir = vc_getVserverVdir(cfgdir->d, vcCFG_RECENT_FULL, true);
+  if (*vdir==0) {
+    WRITE_MSG(2, "Can not find root-directory of the vserver\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool
+setFlag(void *flags_v, char const *str, size_t len)
+{
+  struct vc_ctx_flags  *flags = flags_v;
+  int                  rc = vc_list2cflag(str,len, 0,flags);
+
+  return rc!=-1;
+}
+
+static bool
+setCCap(void *caps_v, char const *str, size_t len)
+{
+  struct vc_ctx_caps   *caps = caps_v;
+  int                  rc = vc_list2ccap(str,len, 0,caps);
+
+  return rc!=-1;
+}
+
+static bool
+setBCap(void *caps_v, char const *str, size_t len)
+{
+  struct vc_ctx_caps   *caps = caps_v;
+  int                  rc = vc_list2bcap(str,len, 0,caps);
+
+  return rc!=-1;
+}
+
+static bool
+readSomething(void *dest, PathInfo const *cfgdir, char const *item,
+             FileCfg_MultiLineHandler handler)
+{
+  char const   *data = FileCfg_readEntryStr(cfgdir, item, true, 0);
+  bool         res   = false;
+
+  if (!data) return true;
+  if (!FileCfg_iterateOverMultiLine(data, handler, dest)) {
+    WRITE_MSG(2, "Failed to parse '");
+    WRITE_STR(2, item);
+    WRITE_MSG(2, "' configuration\n");
+    goto finish;
+  }
+
+  res = true;
+  finish:
+  free(const_cast(char *)(data));
+  return res;
+}
+
+bool
+getConfiguration(struct Configuration *cfg, PathInfo const *cfgdir)
+{
+  cfg->cfgdir = *cfgdir;
+  cfg->nice   = FileCfg_readEntryStr(cfgdir, "nice", false, 0);
+  
+  return (initVdir(&cfg->vdir, cfgdir) &&
+         readSomething(&cfg->ctx_flags, cfgdir, "flags", setFlag) &&
+         readSomething(&cfg->ctx_caps,  cfgdir, "ccapabilities", setCCap) &&
+         readSomething(&cfg->ctx_caps,  cfgdir, "bcapabilities", setBCap) &&
+         getInterfaces(cfg));
+}