我的程序使用现有的库,文档有限,我无法控制。出于本问题的目的,使用如下:
#include <theirlib.hpp>
using their_lib::Node;
int main ( int argc, char** argv )
{
Node my_node;
// connect to the master communication server
my_node.init();
// ...
}
出于其自身最为人所知的原因,init()
不接受任何参数,而是尝试从环境变量中查找通信服务器的URI(以及其他参数)。我可以通过ltrace
:
...
15:43:24 libtheirlib.so->getenv("THEIRLIB_MASTER_URI") = nil <0.000173>
...
现在,我可以用脚本包装我的程序并预先设置环境变量,但是如果我希望能够在运行时更改它们呢?我可以使用setenv()
,但这仍然会让我觉得污染环境,如果我想一次连接到多个主服务器怎么办?
我有什么选择(如果有的话)阻止theirlib
使用环境变量来改变其行为并强制它使用我可以在代码中提供的值?
答案 0 :(得分:4)
您的程序将在子shell中运行,因此没有&#34;污染环境&#34; - 没有其他流程会看到你setenv()
。
答案 1 :(得分:1)
肮脏的伎俩,但可以插入您自己的getenv
实现。
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
static char *theirlib_master_uri;
static char *(*real_getenv)(const char *);
char *getenv(const char *name) {
if (!strcmp(name, "THEIRLIB_MASTER_URI"))
return theirlib_master_uri;
if (!real_getenv)
*((void **)&real_getenv) = dlsym(RTLD_NEXT, "getenv");
return real_getenv(name);
}
这可以在LD_PRELOAD
共享对象或您自己的程序中完成。