initial checkin
authorEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Sat, 3 Jul 2004 00:07:42 +0000 (00:07 +0000)
committerEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Sat, 3 Jul 2004 00:07:42 +0000 (00:07 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1628 94cd875c-1c1d-0410-91d2-eb244daf1a30

14 files changed:
util-vserver/vserver-start/configuration-init.c [new file with mode: 0644]
util-vserver/vserver-start/configuration.c [new file with mode: 0644]
util-vserver/vserver-start/configuration.h [new file with mode: 0644]
util-vserver/vserver-start/interface-add.c [new file with mode: 0644]
util-vserver/vserver-start/interface-free.hc [new file with mode: 0644]
util-vserver/vserver-start/interface-init.hc [new file with mode: 0644]
util-vserver/vserver-start/interface-read.c [new file with mode: 0644]
util-vserver/vserver-start/interface.c [new file with mode: 0644]
util-vserver/vserver-start/interface.h [new file with mode: 0644]
util-vserver/vserver-start/main.c [new file with mode: 0644]
util-vserver/vserver-start/scriptlets.c [new file with mode: 0644]
util-vserver/vserver-start/vserver-start.h [new file with mode: 0644]
util-vserver/vserver-start/vshelper.c [new file with mode: 0644]
util-vserver/vserver-start/vshelper.h [new file with mode: 0644]

diff --git a/util-vserver/vserver-start/configuration-init.c b/util-vserver/vserver-start/configuration-init.c
new file mode 100644 (file)
index 0000000..55be6a0
--- /dev/null
@@ -0,0 +1,30 @@
+// $Id$    --*- 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"
+void
+Cfg_init(struct Configuration *cfg)
+{
+  Vector_init(&cfg->interfaces, sizeof(struct Interface));
+  cfg->broadcast = 0;
+}
diff --git a/util-vserver/vserver-start/configuration.c b/util-vserver/vserver-start/configuration.c
new file mode 100644 (file)
index 0000000..435c9ea
--- /dev/null
@@ -0,0 +1,96 @@
+// $Id$    --*- 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 <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 *c, PathInfo const *cfgdir)
+{
+  ENSC_PI_DECLARE(iface_subdir, "interfaces");
+  PathInfo             ifacepath = *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(&c->interfaces);
+      *new_iface = iface;
+    }
+  }
+
+  if (dir!=0)
+    closedir(dir);
+
+  return rc;
+}
+
+bool
+getConfiguration(struct Configuration *c, PathInfo const *cfgdir)
+{
+  return getInterfaces(c, cfgdir);
+}
diff --git a/util-vserver/vserver-start/configuration.h b/util-vserver/vserver-start/configuration.h
new file mode 100644 (file)
index 0000000..d32fc42
--- /dev/null
@@ -0,0 +1,38 @@
+// $Id$    --*- 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.
+
+
+#ifndef H_UTIL_VSERVER_VSERVER_START_CONFIGURATION_H
+#define H_UTIL_VSERVER_VSERVER_START_CONFIGURATION_H
+
+#include <ensc_vector/vector.h>
+#include <lib_internal/pathinfo.h>
+
+#include <stdbool.h>
+
+struct Configuration {
+    uint32_t           broadcast;
+    struct Vector      interfaces;
+};
+
+extern struct Configuration            cfg;
+
+void           Cfg_init(struct Configuration *);
+bool           getConfiguration(struct Configuration *, PathInfo const *cfgdir);
+
+
+#endif //  H_UTIL_VSERVER_VSERVER_START_CONFIGURATION_H
diff --git a/util-vserver/vserver-start/interface-add.c b/util-vserver/vserver-start/interface-add.c
new file mode 100644 (file)
index 0000000..6c03825
--- /dev/null
@@ -0,0 +1,127 @@
+// $Id$    --*- 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 "interface.h"
+#include "pathconfig.h"
+
+#include <lib_internal/command.h>
+#include <lib_internal/util.h>
+#include <ensc_fmt/fmt.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+unsigned int
+Iface_getIPv4Prefix(struct Interface const *iface)
+{
+  uint32_t     mask = iface->addr.ipv4.mask;
+  unsigned int res  = 0;
+  while (mask!=0) {
+    res += mask & 1;
+    mask >>= 1;
+  }
+
+  return res;
+}
+
+static bool
+invokeIpAddr(struct Interface const *iface)
+{
+  struct Command               cmd;
+  unsigned int                 prefix = Iface_getIPv4Prefix(iface);
+  char                         buf[sizeof("255.255.255.255/") + sizeof(unsigned int)*3 + 1];
+  char *                       tmp = inet_ntoa(*reinterpret_cast(struct in_addr *)(&iface->addr.ipv4.ip));
+  size_t                       l   = strlen(tmp);
+  char *                       ptr;
+
+  if (l>=sizeof("255.255.255.255")) {
+    abort();
+    return false;
+  }
+  ptr    = Xmemcpy(buf, tmp, l);
+  *ptr++ = '/';
+  l      = utilvserver_fmt_uint(ptr, prefix);
+  ptr[l] = '\0';
+
+  Command_init(&cmd, 5);
+  Command_appendParameter(&cmd, "/bin/echo");
+  Command_appendParameter(&cmd, PROG_IP);
+  Command_appendParameter(&cmd, buf);
+  Command_appendParameter(&cmd, "broadcast");
+  if (iface->addr.ipv4.bcast!=0)
+    Command_appendParameter(&cmd, inet_ntoa(*reinterpret_cast(struct in_addr *)(&iface->addr.ipv4.bcast)));
+  else
+    Command_appendParameter(&cmd, "+");
+
+  size_t                       l1 = strlen(iface->dev);
+  size_t                       l2 = iface->name ? strlen(iface->name) : 0;
+  char                         devlabel[l1 + l2 + sizeof(":")];
+  
+  if (iface->name) {
+    ptr    = Xmemcpy(devlabel, iface->dev,  l1);
+    *ptr++ = ':';
+    ptr    = Xmemcpy(ptr,      iface->name, l2);
+    *ptr   = '\0';
+    
+    Command_appendParameter(&cmd, "label");
+    Command_appendParameter(&cmd, devlabel);
+  }
+
+  Command_appendParameter(&cmd, "dev");
+  Command_appendParameter(&cmd, iface->dev);
+
+  if (!Command_exec(&cmd, true) ||
+      !Command_wait(&cmd, true))
+    return false;
+
+  Command_free(&cmd);
+  
+  return true;
+}
+
+static bool
+addVLAN(struct Interface const *iface)
+{
+  abort();     // TODO: implement me
+}
+
+static bool
+addIndirect(struct Interface const *iface)
+{
+  abort();     // TODO: implement me
+}
+
+static bool
+addIP(struct Interface const *iface)
+{
+  return invokeIpAddr(iface);
+    //invokeIpLink(iface);
+}
+
+bool
+Iface_add(struct Interface const *iface)
+{
+  if (iface->nodev)               return true;
+  if (strchr(iface->dev, '.')!=0) return addVLAN(iface);
+  if (!iface->direct)             return addIndirect(iface);
+  return addIP(iface);
+}
diff --git a/util-vserver/vserver-start/interface-free.hc b/util-vserver/vserver-start/interface-free.hc
new file mode 100644 (file)
index 0000000..f7f5eab
--- /dev/null
@@ -0,0 +1,25 @@
+// $Id$    --*- 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.
+
+static inline UNUSED void
+Iface_free(struct Interface *iface)
+{
+  free(const_cast(char *)(iface->name));
+  free(const_cast(char *)(iface->scope));
+  free(const_cast(char *)(iface->dev));
+  free(const_cast(char *)(iface->mac));
+}
diff --git a/util-vserver/vserver-start/interface-init.hc b/util-vserver/vserver-start/interface-init.hc
new file mode 100644 (file)
index 0000000..cde6d94
--- /dev/null
@@ -0,0 +1,31 @@
+// $Id$    --*- 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.
+
+#include <string.h>
+
+static inline UNUSED void
+Iface_init(struct Interface *iface)
+{
+  memset(&iface->addr, 0, sizeof (iface->addr));
+  iface->name      = 0;
+  iface->scope     = 0;
+  iface->dev       = 0;
+  iface->mac       = 0;
+  iface->nodev     = false;
+  iface->direct    = false;
+  iface->up        = true;
+}
diff --git a/util-vserver/vserver-start/interface-read.c b/util-vserver/vserver-start/interface-read.c
new file mode 100644 (file)
index 0000000..1d72518
--- /dev/null
@@ -0,0 +1,131 @@
+// $Id$    --*- 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 "interface.h"
+
+#include <lib_internal/filecfg.h>
+#include <lib_internal/util.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+static inline char *
+readEntryStr(PathInfo const *cfgdir, char const *file, char const *dflt)
+{
+  return FileCfg_readEntryStr(cfgdir, file, false, dflt);
+}
+
+static inline bool
+readEntryFlag(PathInfo const *cfgdir, char const *file, bool dflt)
+{
+  return FileCfg_readEntryFlag(cfgdir, file, dflt);
+}
+
+static int
+assumeNonNull(PathInfo const *cfgdir, char const *file, char const *val)
+{
+  if (val!=0) return 0;
+
+  WRITE_MSG(2, "vserver-start: no value configured for '");
+  write(2, cfgdir->d, cfgdir->l);
+  WRITE_MSG(2, "/");
+  WRITE_STR(2, file);
+  WRITE_STR(2, "'\n");
+  return 1;
+}
+
+bool
+Iface_read(struct Interface *res, PathInfo *cfgdir,
+          struct Interface const *dflt)
+{
+  char const * extip;
+  char const * ip;
+  char const * mask;
+  char const * prefix;
+  char const * bcast;
+  bool         rc = false;
+
+  ip          =  readEntryStr (cfgdir, "ip",       0);
+  mask        =  readEntryStr (cfgdir, "mask",     0);
+  prefix      =  readEntryStr (cfgdir, "prefix",   0);
+  extip       =  readEntryStr (cfgdir, "extip",    0);
+  bcast       =  readEntryStr (cfgdir, "bcast",    0);
+  res->mac    =  readEntryStr (cfgdir, "mac",      0);
+  res->name   =  readEntryStr (cfgdir, "name",     0);
+  res->dev    =  readEntryStr (cfgdir, "dev",      dflt ? dflt->dev   : 0);
+  res->scope  =  readEntryStr (cfgdir, "scope",    dflt ? dflt->scope : 0);
+  res->nodev  =  readEntryFlag(cfgdir, "nodev",    false);
+  res->direct = !readEntryFlag(cfgdir, "indirect", false);
+  res->up     = !readEntryFlag(cfgdir, "down",     false);
+
+  if (dflt && (
+       assumeNonNull(cfgdir, "ip",  ip) +
+       assumeNonNull(cfgdir, "dev", res->dev) +
+       (dflt->addr.ipv4.mask>0) ? 0 : (
+         (mask   ? 0 : assumeNonNull(cfgdir, "prefix", prefix)) +
+         (prefix ? 0 : assumeNonNull(cfgdir, "mask",   mask))
+         )))
+    goto err;
+
+  if (mask && prefix) {
+    WRITE_MSG(2, "vserver-start: both 'prefix' and 'mask' specified in '");
+    write(2, cfgdir->d, cfgdir->l);
+    WRITE_MSG(2, "'\n");
+    goto err;
+  }
+
+  if (bcast)
+    res->addr.ipv4.bcast = inet_addr(bcast);
+
+  if (ip)
+    res->addr.ipv4.ip    = inet_addr(ip);
+  
+  if (extip)
+    res->addr.ipv4.extip = inet_addr(extip);
+
+  if (prefix) {
+    int                p = atoi(prefix);
+    if (p==0) {
+      WRITE_MSG(2, "vserver-start: invalid 'prefix' specified in '");
+      write(2, cfgdir->d, cfgdir->l);
+      WRITE_MSG(2, "'\n");
+      goto err;
+    }
+      
+    res->addr.ipv4.mask = htonl(-1u << (32-p));
+  }
+  else if (mask)
+    res->addr.ipv4.mask = inet_addr(mask);
+  else if (dflt)
+    res->addr.ipv4.mask = dflt->addr.ipv4.mask;
+
+  rc = true;
+
+  err:
+  free(const_cast(void *)(bcast));
+  free(const_cast(void *)(extip));
+  free(const_cast(void *)(ip));
+  free(const_cast(void *)(mask));
+  free(const_cast(void *)(prefix));
+
+  return rc;
+}
diff --git a/util-vserver/vserver-start/interface.c b/util-vserver/vserver-start/interface.c
new file mode 100644 (file)
index 0000000..6afbbe4
--- /dev/null
@@ -0,0 +1,39 @@
+// $Id$    --*- 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 "interface.h"
+
+#include "vserver-start.h"
+#include "configuration.h"
+
+#include <lib_internal/util.h>
+
+void
+activateInterfaces()
+{
+  struct Interface const *     iface;
+
+  for (iface=Vector_begin(&cfg.interfaces);
+       iface!=Vector_end(&cfg.interfaces);
+       ++iface)
+    Iface_add(iface);
+}
diff --git a/util-vserver/vserver-start/interface.h b/util-vserver/vserver-start/interface.h
new file mode 100644 (file)
index 0000000..2277950
--- /dev/null
@@ -0,0 +1,60 @@
+// $Id$    --*- 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.
+
+
+#ifndef H_UTIL_VSERVER_VSERVER_START_INTERFACE_H
+#define H_UTIL_VSERVER_VSERVER_START_INTERFACE_H
+
+#include <lib_internal/util-cast.h>
+
+#include <lib/vserver.h>
+#include <lib_internal/pathinfo.h>
+#include <stdbool.h>
+
+struct Interface {
+    union {
+       struct {
+           uint32_t            ip;
+           uint32_t            mask;
+           uint32_t            extip;
+           uint32_t            bcast;
+       }                       ipv4;
+    }                          addr;
+       
+    char const *               name;
+    char const *               scope;
+    char const *               dev;
+    char const *               mac;
+    bool                       nodev;
+    bool                       direct;
+    bool                       up;
+};
+
+void           activateInterfaces();
+void           deactivateInterfaces();
+
+static void    Iface_init(struct Interface *);
+static void    Iface_free(struct Interface *);
+bool           Iface_read(struct Interface *, PathInfo *cfgdir,
+                          struct Interface const *dflt);
+bool           Iface_add(struct Interface const *);
+bool           Iface_del(struct Interface const *);
+
+#include "interface-init.hc"
+#include "interface-free.hc"
+
+#endif //  H_UTIL_VSERVER_VSERVER_START_INTERFACE_H
diff --git a/util-vserver/vserver-start/main.c b/util-vserver/vserver-start/main.c
new file mode 100644 (file)
index 0000000..5896281
--- /dev/null
@@ -0,0 +1,128 @@
+// $Id$    --*- 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 "vserver-start.h"
+#include "vshelper.h"
+#include "pathconfig.h"
+#include "interface.h"
+#include "configuration.h"
+
+#include "lib_internal/util.h"
+#include "lib_internal/errinfo.h"
+#include "lib/vserver.h"
+
+#include <sys/file.h>
+
+struct Options                 opts;
+struct Configuration           cfg;
+int                            wrapper_exit_code;
+
+static void
+env2Str(char const **var, char const *env, bool req)
+{
+  char const *         tmp = getenv(env);
+  if (req && tmp==0) {
+    WRITE_MSG(2, "vserver.start: required environment variable $");
+    WRITE_STR(2, env);
+    WRITE_STR(2, " not set; aborting...\n");
+    exit(1);
+  }
+
+  *var = tmp;
+  unsetenv(env);
+}
+
+static void
+env2Bool(bool *var, char const *env, bool req)
+{
+  char const * tmp;
+  env2Str(&tmp, env, req);
+  *var = !(tmp==0 || atoi(tmp)==0);
+}
+
+static void
+initGlobals()
+{
+  env2Str (&opts.VSERVER_DIR,       "VSERVER_DIR",       true);
+  env2Str (&opts.VSERVER_NAME,      "VSERVER_NAME",      true);
+  env2Bool(&opts.OPTION_DEBUG,      "OPTION_DEBUG",      false);
+  env2Bool(&opts.OPTION_DEFAULTTTY, "OPTION_DEFAULTTTY", false);  
+}
+
+static void
+initLock()
+{
+  size_t                       l   = strlen(opts.VSERVER_DIR);
+  char                                 tmp[sizeof(LOCKDIR "/vserver..startup") + l];
+  char *                       ptr = tmp;
+  struct ErrorInformation      err = { .app = 0 };
+  int                          fd;
+
+  ptr  = Xmemcpy(ptr, LOCKDIR "/vserver.", sizeof(LOCKDIR "/vserver.")-1);
+  ((char *)(Xmemcpy(ptr, opts.VSERVER_DIR, l)))[0] = '\0';
+  ptr += canonifyVserverName(ptr);
+  ptr  = Xmemcpy(ptr, ".startup",  sizeof(".startup"));
+  *ptr = '\0';
+
+  if (!lockfile(&fd, tmp, LOCK_EX, 30, &err)) {
+    WRITE_MSG(2, "vserver.start: failed to lock '");
+    WRITE_STR(2, tmp);
+    WRITE_MSG(2, "': ");
+    ErrInfo_writeErrno(&err);
+    exit(1);
+  }
+}
+
+static void
+checkConstraints()
+{
+  xid_t                        xid;
+  bool                 is_running;
+  struct vc_vx_info    info;
+
+  xid = vc_getVserverCtx(opts.VSERVER_DIR, vcCFG_RECENT_FULL,
+                        true, &is_running);
+
+  if (xid!=VC_NOCTX && vc_get_vx_info(xid, &info)!=-1) {
+    WRITE_MSG(2, "vserver.start: vserver '");
+    WRITE_STR(2, opts.VSERVER_NAME);
+    WRITE_MSG(2, "' already running; aborting...\n");
+    exit(1);
+  }
+
+  Vshelper_doSanityCheck();
+}
+
+int main(int argc, char *argv[])
+{
+  Cfg_init(&cfg);
+  
+  initGlobals();
+  initLock();
+  checkConstraints();
+
+  PathInfo     cfgdir = { .d = opts.VSERVER_DIR, .l = strlen(opts.VSERVER_DIR) };
+
+  getConfiguration(&cfg, &cfgdir);
+  execScriptlets(&cfgdir, opts.VSERVER_NAME, "prepre-start");
+  activateInterfaces();
+}
diff --git a/util-vserver/vserver-start/scriptlets.c b/util-vserver/vserver-start/scriptlets.c
new file mode 100644 (file)
index 0000000..30874ca
--- /dev/null
@@ -0,0 +1,172 @@
+// $Id$    --*- 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 "vserver-start.h"
+
+#include <pathconfig.h>
+#include <lib_internal/command.h>
+#include <lib_internal/util.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#define HAS_SUFFIX(STR, LEN, SUF) \
+  (LEN>sizeof(SUF) && strcmp(STR+LEN-sizeof(SUF), SUF)==0)
+
+static bool
+visitFile(char const *fname, char const *vname, char const *style)
+{
+  struct stat          st;
+  struct Command       cmd;
+
+  if (stat(fname, &st)==-1 ||
+      !S_ISREG(st.st_mode))
+    return false;
+
+  if ((st.st_mode & 0111)==0) {
+    WRITE_MSG(2,
+             "!!!LEGACY ALERT!!!\n"
+             "The special handling of non-executable scriptlets which allows to\n"
+             "override environment variables is not supported anymore. This change\n"
+             "was needed as 'vserver ... start' is a done by a native C program\n"
+             "now. If you need the old functionality please fill a bugreport so\n"
+             "that workarounds can be found/implemented.\n"
+             "The file triggering this message was\n"
+             "    '");
+    WRITE_STR(2, fname);
+    WRITE_MSG(2, "'\n");
+
+    return false;
+  }
+
+  Command_init(&cmd, 4);
+  Command_appendParameter(&cmd, fname);
+  Command_appendParameter(&cmd, style);
+  Command_appendParameter(&cmd, vname);
+
+  if (!Command_exec(&cmd, true) ||
+      !Command_wait(&cmd, true)) {
+    WRITE_MSG(2, "vserver-start: exec('");
+    WRITE_STR(2, fname);
+    WRITE_MSG(2, "'): ");
+    WRITE_STR(2, strerror(cmd.err));
+    WRITE_MSG(2, "; aborting...\n");
+
+    exit(1);
+  }
+
+  if (cmd.rc!=0) {
+    WRITE_MSG(2, "vserver-start: scriptlet '");
+    WRITE_STR(2, fname);
+    WRITE_MSG(2, "' failed; aborting...\n");
+    
+    exit (1);
+  }
+
+  Command_free(&cmd);
+
+  return true;
+}
+
+static bool
+visitDirentry(PathInfo const *basepath, char const *d_name,
+             char const *vname,
+             char const *style)
+{
+  size_t               l = strlen(d_name);
+  char                 path[basepath->l + l + 1];
+  char *               ptr;
+
+  if (isDotfile(d_name) ||
+      HAS_SUFFIX(d_name, l, ".rpmnew") ||
+      HAS_SUFFIX(d_name, l, ".rpmsave") ||
+      HAS_SUFFIX(d_name, l, ".rpmorig") ||
+      HAS_SUFFIX(d_name, l, ".cfsaved"))
+    return false;
+
+  ptr  = Xmemcpy(path, basepath->d, basepath->l);
+  ptr  = Xmemcpy(ptr,  d_name,      l);
+  *ptr = '\0';
+  
+  return visitFile(path, vname, style);
+}
+
+static bool
+visitPath(PathInfo const *basepath,
+         char const *vname,
+         PathInfo const *style)
+{
+  char         tmp[basepath->l + style->l + sizeof(".d/")];
+  PathInfo     path = { .d = tmp };
+  char *       ptr;
+  DIR *                dir;
+  bool         did_something = false;
+
+  ptr  = Xmemcpy(tmp, basepath->d, basepath->l);
+  ptr  = Xmemcpy(ptr, style->d,    style->l);
+  *ptr = '\0';
+  path.l = ptr-tmp;
+
+  did_something = visitFile(path.d, vname, style->d) || did_something;
+
+  ptr = Xmemcpy(ptr, ".d/", sizeof(".d/"));
+  path.l = ptr-tmp;
+  
+  dir = opendir(tmp);
+  while (dir) {
+    struct dirent *ent =  readdir(dir);
+    if (ent==0) break;
+
+    did_something = visitDirentry(&path, ent->d_name, vname, style->d) || did_something;
+  }
+  if (dir!=0) closedir(dir);
+
+  return did_something;
+}
+
+void
+execScriptlets(PathInfo const *cfgdir, char const *vname, char const *style)
+{
+  char         path_buf[MAX(cfgdir->l, sizeof(CONFDIR "/.defaults")) +
+                        sizeof("/scripts/")];
+  PathInfo     basepath = { .d = path_buf };
+  PathInfo     styledir = {
+    .d = style,
+    .l = strlen(style)
+  };
+  char *       ptr;
+  bool         doit = true;
+
+  ptr = Xmemcpy(path_buf, cfgdir->d, cfgdir->l);
+  ptr = Xmemcpy(ptr,      "/scripts/", sizeof("/scripts/"));
+  basepath.l = ptr-path_buf-1;
+  doit =   !visitPath(&basepath, vname, &styledir);
+
+  if (doit) {
+    ptr = Xmemcpy(path_buf, CONFDIR "/.defaults/scripts/",
+                 sizeof(CONFDIR "/.defaults/scripts/"));
+    doit = !visitPath(&basepath, vname, &styledir);
+  }
+}
diff --git a/util-vserver/vserver-start/vserver-start.h b/util-vserver/vserver-start/vserver-start.h
new file mode 100644 (file)
index 0000000..67af782
--- /dev/null
@@ -0,0 +1,36 @@
+// $Id$    --*- 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.
+
+
+#ifndef H_UTIL_VSERVER_VSERVER_START_VSERVER_START_H
+#define H_UTIL_VSERVER_VSERVER_START_VSERVER_START_H
+
+#include <lib_internal/pathinfo.h>
+#include <stdbool.h>
+
+struct Options {
+    char const *               VSERVER_DIR;
+    char const *               VSERVER_NAME;
+    bool                       OPTION_DEBUG;
+    bool                       OPTION_DEFAULTTTY;
+};
+
+extern struct Options          opts;
+
+void   execScriptlets(PathInfo const *cfgdir, char const *name, char const *style);
+
+#endif //  H_UTIL_VSERVER_VSERVER_START_VSERVER_START_H
diff --git a/util-vserver/vserver-start/vshelper.c b/util-vserver/vserver-start/vshelper.c
new file mode 100644 (file)
index 0000000..4e1b1fe
--- /dev/null
@@ -0,0 +1,46 @@
+// $Id$    --*- 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 "vserver-start.h"
+#include "pathconfig.h"
+
+#include <lib_internal/util.h>
+#include <lib_internal/command.h>
+
+void
+Vshelper_doSanityCheck()
+{
+  struct Command       cmd = {
+    .filename = "/bin/bash"
+  };
+
+  Command_init(&cmd, 10);
+  Command_appendParameter(&cmd, "/bin/bash");
+  Command_appendParameter(&cmd, "-c");
+  Command_appendParameter(&cmd, ". " PATH_UTILVSERVER_VARS ";. " PATH_FUNCTIONS "; vshelper.doSanityCheck");
+  if (!Command_exec(&cmd, true) ||
+      !Command_wait(&cmd, true))
+    WRITE_MSG(2, "vserver-start: failed to do the vshelper-sanitycheck\n");
+
+  if (cmd.rc!=0)
+    exit(0);
+}
diff --git a/util-vserver/vserver-start/vshelper.h b/util-vserver/vserver-start/vshelper.h
new file mode 100644 (file)
index 0000000..f928e7a
--- /dev/null
@@ -0,0 +1,25 @@
+// $Id$    --*- 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.
+
+
+#ifndef H_UTIL_VSERVER_VSERVER_START_VSHELPER_H
+#define H_UTIL_VSERVER_VSERVER_START_VSHELPER_H
+
+void           Vshelper_doSanityCheck();
+
+
+#endif //  H_UTIL_VSERVER_VSERVER_START_VSHELPER_H