Skip to content

Instantly share code, notes, and snippets.

@neoneye
Created May 17, 2016 18:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neoneye/3d11bf5a0a8c3a919b55ae8a119ea06d to your computer and use it in GitHub Desktop.
Save neoneye/3d11bf5a0a8c3a919b55ae8a119ea06d to your computer and use it in GitHub Desktop.
posix_spawn with an "environment" class
// Copyright © 2015 Simon Strandgaard. All rights reserved.
// MIT license
#include "environment.hpp"
#include <unistd.h>
#include <iostream>
#include <boost/algorithm/string/predicate.hpp>
extern char **environ;
void Environment::populateWithGlobalEnvironment() {
for (char **env = ::environ; *env; ++env) {
environment.push_back(*env);
}
}
void Environment::prependRaw(const std::string &env) {
environment.insert(environment.begin(), env);
}
void Environment::appendRaw(const std::string &env) {
environment.push_back(env);
}
void Environment::print() {
for (auto &env: environment) {
std::cout << "environment-item: " << env << std::endl;
}
}
boost::optional<std::string> Environment::get(const std::string &key) {
std::string prefix(key + "=");
for (auto &env: environment) {
if (!boost::starts_with(env, prefix)) { continue; }
return env.substr(prefix.size());
}
return boost::none;
}
void Environment::set(const std::string &key, const std::string &value) {
std::string prefix(key + "=");
std::string combined(key + "=" + value);
int i = -1;
for (auto &env: environment) {
++i;
if (!boost::starts_with(env, prefix)) { continue; }
environment[i] = combined;
return;
}
environment.push_back(combined);
}
bool Environment::remove(const std::string &key) {
std::string prefix(key + "=");
int i = -1;
for (auto &env: environment) {
++i;
if (!boost::starts_with(env, prefix)) { continue; }
environment.erase(environment.begin() + i);
return true;
}
return false;
}
CStringArrayPtr Environment::c_str_array() {
size_t n = environment.size();
size_t n1 = n + 1;
CStringArrayPtr result(
new const char*[n1],
std::default_delete<const char*[]>()
);
const char** array = result.get();
for (size_t i=0; i<n; ++i) {
array[i] = environment[i].c_str();
}
array[n] = 0;
return result;
}
void Environment::prepend(const std::string &key, const std::string &value, const std::string &separator) {
boost::optional<std::string> s = get(key);
std::string joinedValue(value);
if (s) {
joinedValue += separator + s.value();
}
set(key, joinedValue);
}
void Environment::append(const std::string &key, const std::string &value, const std::string &separator) {
boost::optional<std::string> s = get(key);
std::string joinedValue;
if (s) {
joinedValue = s.value() + separator;
}
joinedValue += value;
set(key, joinedValue);
}
// Copyright © 2015 Simon Strandgaard. All rights reserved.
// MIT license
#ifndef environment_hpp
#define environment_hpp
#include <vector>
#include <string>
#include <memory>
#include <boost/optional.hpp>
typedef std::shared_ptr<const char*> CStringArrayPtr;
class Environment {
private:
std::vector<std::string> environment;
public:
void populateWithGlobalEnvironment();
void prependRaw(const std::string &env);
void appendRaw(const std::string &env);
void print();
boost::optional<std::string> get(const std::string &key);
void set(const std::string &key, const std::string &value);
bool remove(const std::string &key);
CStringArrayPtr c_str_array();
void prepend(const std::string &key, const std::string &value, const std::string &separator);
void append(const std::string &key, const std::string &value, const std::string &separator);
};
#endif /* environment_hpp */
// Copyright © 2015 Simon Strandgaard. All rights reserved.
// MIT license
const char *argv[] = {
NULL,
NULL
};
argv[0] = path_to_executable.c_str();
Environment e;
e.populateWithGlobalEnvironment();
Configuration::getInstance().updateEnvironmentWithStuff1(e);
Configuration::getInstance().updateEnvironmentWithStuff2(e);
e.set("MYAPP_USER_ID", user_id);
e.set("MYAPP_TIMESTAMP", timestamp);
CStringArrayPtr ptr = e.c_str_array();
char * const* environ2 = const_cast<char * const*>(ptr.get());
int exitStatus = -1;
pid_t pid;
int status = ::posix_spawn(&pid, argv[0], NULL, NULL, (char * const*)argv, environ2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment