Alexander Dyagilev
Alexander Dyagilev

Reputation: 1425

Get bash $PATH from C++ program

In the Terminal app my $PATH is:

/usr/local/opt/python/libexec/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

If the user starts my C++ application using Dock, its $PATH is:

/usr/bin:/bin:/usr/sbin:/sbin

I would like my app to always has the same $PATH as terminal (bash) has. Is there an easy way to achieve this?

The only way I'm aware of for now is to create a bash script on the disk with something like echo $PATH, launch it from my C++ program using bash -l command, read the output and update my process' PATH variable accordingly.

And, I do not want to change user system's config in any way. This should work without any additional actions required from the user and do not affect the user's system in any way.

Upvotes: 3

Views: 563

Answers (2)

JBRWilkinson
JBRWilkinson

Reputation: 4875

Launching an application from Shell/Explorer/Dock/etc gets a different environment to the Command Line/Terminal/bash in many scenarios because the Shell/Explorer/Dock was invoked by the GUI login process and not the Command Line/Terminal/Bash.

When you run Terminal/Bash, the .bashrc/.bash_profile, etc scripts are run, and these are often configured to add things to the PATH environment variable for command-line convenience.

It's not clear from the question whether your application will be used by other users or just yourself:

  1. Can you change the 'Dock Icon' to point to a Shell script that sets up the PATH environment variable before launching the C++ application?

  2. Failing that, if it's only for you, you can hack your systemwide bashrc: sudo $EDITOR /etc/bashrc ..but this is not recommended

  3. If your C++ application has a dependency on something in the $PATH, can you code around it? For example, use the absolute path to whatever application you need to run.

Upvotes: 0

Gintaras
Gintaras

Reputation: 224

If you don’t like your solution of calling bash, here’s a stub to exercise more control over invoking shells and perhaps test if the user default shell isn’t bash all from within a c++ program:

setenv("PATH", "/MyCustomPath:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin", 1);

To Read bash's path:

std::string exec(const char* cmd) {
    char buffer[128];
    std::string result = "";
    FILE* pipe = popen(cmd, "r");
    if (!pipe) throw std::runtime_error("popen() failed!");
    try {
        while (fgets(buffer, sizeof buffer, pipe) != NULL) {
            result += buffer;
        }
    } catch (...) {
        pclose(pipe);
        throw;
    }
    pclose(pipe);
    return result;
}

setenv("PATH", exec("bash -l -c 'echo -n $PATH'").c_str(), 1);

Upvotes: 3

Related Questions