Question: I am trying to use `LD_PRELOAD` on linux to wrap calls to `system` function to add some preprocessing to the argument. Here's my `system.cpp`:

```
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string>
#include <iostream>

typedef int (*orig_system_type)(const char *command);

int system(const char *command)
{
    std::string new_cmd = std::string("set -f;") + command;
    // next line is for debuggin only
    std::cout << new_cmd << std::endl;

    orig_system_type orig_system;
    orig_system = (orig_system_type)dlsym(RTLD_NEXT,"system");
    return orig_system(new_cmd.c_str());
}

```

I build it with

```
g++ -shared -fPIC -ldl -o libsystem.so system.cpp

```

which produces the .so object. I then run my program with

```
$ LD_PRELOAD=/path/to/libsystem.so ./myprogram

```

I do not get any errors - but seemingly my `system` function is not called. Running with `LD_DEBUG=libs`, I can see that my .so is being loaded, however my `system` function is not being called and the one from the standard library is called instead.

What do I need to change in code/build to get it to work?

Answer: 
You need

```
extern "C" int system ...

```

because it is called by a C function. The C++ version has its name mangled so it is not recognizable.
You might also want to consider saving the "orig\_system" pointer so that you avoid calling dlsym every time. You can do this in a [constructor/init](https://stackoverflow.com/questions/9759880/automatically-executed-functions-when-loading-shared-libraries) function, so you would have something like

```
extern "C" {

typedef int (*orig_system_type)(const char *command);

static orig_system_type orig_system;

static void myInit() __attribute__((constructor));

void myInit()
{
    orig_system = (orig_system_type)dlsym(RTLD_NEXT,"system");
}

int system(const char *command)
{
    std::string new_cmd = std::string("set -f;") + command;
    // next line is for debuggin only
    std::cout << new_cmd << std::endl;
    return orig_system(new_cmd.c_str());
}

}

```

(this code isn't tested, but I have used this technique in the past).

An alternative would be to use GNU ld's --wrap option.

If you compile your shared lib with

-Wl,--wrap system

then in your code you write

```
extern "C" {

void* __real_system(const char* command);
void* __wrap_system(const char* command)
{
    std::string new_cmd = std::string("set -f;") + command;
    // next line is for debuggin only
    std::cout << new_cmd << std::endl;
    return __real_system(new_cmd.c_str());
}

}

```

(Note that I've never used this).