From e3be43e3ee2157a63ea175463629c2433f595854 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Sat, 3 Jul 2004 00:07:42 +0000 Subject: [PATCH] initial checkin git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1628 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- util-vserver/vserver-start/configuration-init.c | 30 +++++ util-vserver/vserver-start/configuration.c | 96 +++++++++++++ util-vserver/vserver-start/configuration.h | 38 ++++++ util-vserver/vserver-start/interface-add.c | 127 +++++++++++++++++ util-vserver/vserver-start/interface-free.hc | 25 ++++ util-vserver/vserver-start/interface-init.hc | 31 +++++ util-vserver/vserver-start/interface-read.c | 131 ++++++++++++++++++ util-vserver/vserver-start/interface.c | 39 ++++++ util-vserver/vserver-start/interface.h | 60 +++++++++ util-vserver/vserver-start/main.c | 128 ++++++++++++++++++ util-vserver/vserver-start/scriptlets.c | 172 ++++++++++++++++++++++++ util-vserver/vserver-start/vserver-start.h | 36 +++++ util-vserver/vserver-start/vshelper.c | 46 +++++++ util-vserver/vserver-start/vshelper.h | 25 ++++ 14 files changed, 984 insertions(+) create mode 100644 util-vserver/vserver-start/configuration-init.c create mode 100644 util-vserver/vserver-start/configuration.c create mode 100644 util-vserver/vserver-start/configuration.h create mode 100644 util-vserver/vserver-start/interface-add.c create mode 100644 util-vserver/vserver-start/interface-free.hc create mode 100644 util-vserver/vserver-start/interface-init.hc create mode 100644 util-vserver/vserver-start/interface-read.c create mode 100644 util-vserver/vserver-start/interface.c create mode 100644 util-vserver/vserver-start/interface.h create mode 100644 util-vserver/vserver-start/main.c create mode 100644 util-vserver/vserver-start/scriptlets.c create mode 100644 util-vserver/vserver-start/vserver-start.h create mode 100644 util-vserver/vserver-start/vshelper.c create mode 100644 util-vserver/vserver-start/vshelper.h diff --git a/util-vserver/vserver-start/configuration-init.c b/util-vserver/vserver-start/configuration-init.c new file mode 100644 index 0000000..55be6a0 --- /dev/null +++ b/util-vserver/vserver-start/configuration-init.c @@ -0,0 +1,30 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#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 index 0000000..435c9ea --- /dev/null +++ b/util-vserver/vserver-start/configuration.c @@ -0,0 +1,96 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#endif + +#include "configuration.h" +#include "interface.h" + +#include +#include +#include + +#include +#include + +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 index 0000000..d32fc42 --- /dev/null +++ b/util-vserver/vserver-start/configuration.h @@ -0,0 +1,38 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#include + +#include + +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 index 0000000..6c03825 --- /dev/null +++ b/util-vserver/vserver-start/interface-add.c @@ -0,0 +1,127 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#endif + +#include "interface.h" +#include "pathconfig.h" + +#include +#include +#include + +#include +#include + +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 index 0000000..f7f5eab --- /dev/null +++ b/util-vserver/vserver-start/interface-free.hc @@ -0,0 +1,25 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 index 0000000..cde6d94 --- /dev/null +++ b/util-vserver/vserver-start/interface-init.hc @@ -0,0 +1,31 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 + +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 index 0000000..1d72518 --- /dev/null +++ b/util-vserver/vserver-start/interface-read.c @@ -0,0 +1,131 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#endif + +#include "interface.h" + +#include +#include + +#include +#include + +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 index 0000000..6afbbe4 --- /dev/null +++ b/util-vserver/vserver-start/interface.c @@ -0,0 +1,39 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#endif + +#include "interface.h" + +#include "vserver-start.h" +#include "configuration.h" + +#include + +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 index 0000000..2277950 --- /dev/null +++ b/util-vserver/vserver-start/interface.h @@ -0,0 +1,60 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 + +#include +#include +#include + +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 index 0000000..5896281 --- /dev/null +++ b/util-vserver/vserver-start/main.c @@ -0,0 +1,128 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#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 + +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 index 0000000..30874ca --- /dev/null +++ b/util-vserver/vserver-start/scriptlets.c @@ -0,0 +1,172 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#endif + +#include "vserver-start.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 index 0000000..67af782 --- /dev/null +++ b/util-vserver/vserver-start/vserver-start.h @@ -0,0 +1,36 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#include + +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 index 0000000..4e1b1fe --- /dev/null +++ b/util-vserver/vserver-start/vshelper.c @@ -0,0 +1,46 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 +#endif + +#include "vserver-start.h" +#include "pathconfig.h" + +#include +#include + +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 index 0000000..f928e7a --- /dev/null +++ b/util-vserver/vserver-start/vshelper.h @@ -0,0 +1,25 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// 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 -- 1.8.1.5