all repos — fluxbox @ 87b45bd0d18323898d5c09bb7cad7566e3267635

custom fork of the fluxbox windowmanager

bugfix: avoid naive use of 'putenv' by providing 'FbTk::App::setenv()'

to quote from 'man putenv':

   The string pointed to by string becomes part of the environment,
   so altering the string changes the environment.

so, using putenv like

   {
      std::string foo("FOO=bar");
      putenv(foo.c_str());
   }

is wrong and leads to a potentially corrupted environment. valgrind
complaint correctly.

FbTk::App seems to be the appropriate place to hold '::seten()'
because it alters the environment of the application.
Mathias Gumz akira at fluxbox dot org
commit

87b45bd0d18323898d5c09bb7cad7566e3267635

parent

f3ad09c4ce70cc58871eeac49d640f213f3cd16f

4 files changed, 66 insertions(+), 36 deletions(-)

jump to
M src/FbCommands.ccsrc/FbCommands.cc

@@ -142,8 +142,7 @@ pid_t pid = fork();

if (pid) return pid; - string displaystring("DISPLAY="); - displaystring += DisplayString(FbTk::App::instance()->display()); + string display = DisplayString(FbTk::App::instance()->display()); int screen_num = m_screen_num; if (screen_num < 0) { if (Fluxbox::instance()->mouseScreen() == 0)

@@ -158,12 +157,11 @@ const char *shell = getenv("SHELL");

if (!shell) shell = "/bin/sh"; - // remove last number of display and add screen num - displaystring.erase(displaystring.size()-1); - displaystring += FbTk::StringUtil::number2String(screen_num); + display.erase(display.size()-1); + display += FbTk::StringUtil::number2String(screen_num); setsid(); - putenv(const_cast<char *>(displaystring.c_str())); + FbTk::App::setenv("DISPLAY", display.c_str()); execl(shell, shell, "-c", m_cmd.c_str(), static_cast<void*>(NULL)); exit(EXIT_SUCCESS);

@@ -197,34 +195,7 @@ }

void ExportCmd::execute() { - // the setenv()-routine is not everywhere available and - // putenv() doesnt manage the strings in the environment - // and hence we have to do that on our own to avoid memleaking - static set<char*> stored; - char* newenv = new char[m_name.size() + m_value.size() + 2]; - if (newenv) { - - char* oldenv = getenv(m_name.c_str()); - - // oldenv points to the value .. we have to go back a bit - if (oldenv && stored.find(oldenv - (m_name.size() + 1)) != stored.end()) - oldenv -= (m_name.size() + 1); - else - oldenv = NULL; - - memset(newenv, 0, m_name.size() + m_value.size() + 2); - strcat(newenv, m_name.c_str()); - strcat(newenv, "="); - strcat(newenv, m_value.c_str()); - - if (putenv(newenv) == 0) { - if (oldenv) { - stored.erase(oldenv); - delete[] oldenv; - } - stored.insert(newenv); - } - } + FbTk::App::instance()->setenv(m_name.c_str(), m_value.c_str()); } REGISTER_COMMAND(exit, FbCommands::ExitFluxboxCmd, void);
M src/FbTk/App.ccsrc/FbTk/App.cc

@@ -26,6 +26,21 @@ #include "Image.hh"

#include "EventManager.hh" +#ifdef HAVE_CSTRING + #include <cstring> +#else + #include <string.h> +#endif +#ifdef HAVE_CSTDLIB + #include <cstdlib> +#else + #include <stdlib.h> +#endif + + +#include <set> + + namespace FbTk { App *App::s_app = 0;

@@ -77,6 +92,46 @@

void App::end() { m_done = true; //end loop in App::eventLoop +} + +bool App::setenv(const char* key, const char* value) { + + if (!key || !*key) + return false; + + static std::set<char*> stored; + + const size_t key_size = strlen(key); + const size_t value_size = value ? strlen(value) : 0; + + char* newenv = new char[key_size + value_size + 2]; + if (newenv) { + + char* oldenv = getenv(key); + + // oldenv points to the value .. we have to go back a bit + if (oldenv && stored.find(oldenv - (key_size + 1)) != stored.end()) + oldenv -= (key_size + 1); + else + oldenv = NULL; + + memset(newenv, 0, key_size + value_size + 2); + strcat(newenv, key); + strcat(newenv, "="); + if (value_size > 0) + strcat(newenv, value); + + if (putenv(newenv) == 0) { + if (oldenv) { + stored.erase(oldenv); + delete[] oldenv; + } + stored.insert(newenv); + } + return true; + } + + return false; } } // end namespace FbTk
M src/FbTk/App.hhsrc/FbTk/App.hh

@@ -53,6 +53,11 @@ virtual void eventLoop();

/// forces an end to event loop void end(); bool done() const { return m_done; } + + // the setenv()-routine is not everywhere available and + // putenv() doesnt manage the strings in the environment + // and hence we have to do that on our own to avoid memleaking + static bool setenv(const char* key, const char* value); private: static App *s_app; bool m_done;
M src/main.ccsrc/main.cc

@@ -219,8 +219,7 @@ exit(EXIT_FAILURE);

} opts.session_display = argv[i]; - string display_env = "DISPLAY=" + opts.session_display; - if (putenv(const_cast<char *>(display_env.c_str()))) { + if (!FbTk::App::setenv("DISPLAY", argv[i])) { cerr<<_FB_CONSOLETEXT(main, WarnDisplayEnv, "warning: couldn't set environment variable 'DISPLAY'", "")<<endl;