--- /dev/null
+// $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;
+}
--- /dev/null
+// $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);
+}
--- /dev/null
+// $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
--- /dev/null
+// $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);
+}
--- /dev/null
+// $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));
+}
--- /dev/null
+// $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;
+}
--- /dev/null
+// $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;
+}
--- /dev/null
+// $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);
+}
--- /dev/null
+// $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
--- /dev/null
+// $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();
+}
--- /dev/null
+// $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);
+ }
+}
--- /dev/null
+// $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
--- /dev/null
+// $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);
+}
--- /dev/null
+// $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