Question

I'm trying to make an executable that appends export PATH="$PATH:/my/current/directory" to my ~/.bash_profile ( I'm on OSX 10.9.2 compiling w/ g++.) For now I'm just trying to get the current working directory to reach the current shell (I was getting it to a subshell with setenv() I think but I don't know if that helps) and I can take it from there.

OK, source code:

#include <iostream>
#include <string>
using namespace std;
int main(){
  /*Add current directory to path (locally)*/
  string CWD = getenv("PWD");
  string endquote = "\"";
  string mystring = "PATH=\"$PATH:";
  mystring += CWD;
  mystring += endquote;
  // JUST TRYING TO GET THE PATH TO UPDATE IN SHELL
  // WILL EVENTUALLY UPDATE THIS TO GO INTO .bash_profile
  system(mystring);
  system("echo $PATH");
  return 0;
}

and error:

setup.cpp:11:3: error: no matching function for call to 'system'
  system(mystring);
  ^~~~~~
/usr/include/stdlib.h:177:6: note: candidate function not viable: no known conversion from 'string' (aka 'basic_string<char,
      char_traits<char>, allocator<char> >') to 'const char *' for 1st argument
int      system(const char *) __DARWIN_ALIAS_C(system);
         ^
1 error generated.

Is a constructor the way to go here (to change const char * to string)? I don't know much about them but what the heck, I've spent hours on this already so I might as well spend some more time right?

Was it helpful?

Solution

I think that you should rely less on environment variables and external programs, and more on what you can programmatically find and do with the C++ libraries and POSIX APIs. In this case, you don't need much, really:

  • getuid to find the current user;
  • getpwuid to find the current user's home directory;
  • getcwd to get the current working directory;
  • pretty standard file output stream stuff.

This six-line program appends export PATH="$PATH:current_working_path" to ~/.bash_profile.

#include <fstream>
#include <string>
#include <pwd.h>
#include <unistd.h>
#include <sys/param.h>

using namespace std;

int main()
{
    char path[MAXPATHLEN];
    struct passwd* user_info = getpwuid(getuid());
    string user_directory = user_info->pw_dir;
    string current_directory = getcwd(path, sizeof path);

    ofstream bash_profile(user_directory + "/.bash_profile", ios_base::app);
    bash_profile << "export PATH=\"$PATH:" << current_directory << '"' << endl;
}

Note that this will not affect the bash process from which you call the executable. Environment variables are strictly inherited: modifying them from a child process will not affect the parent process. There is no way to make that happen from a child process, as far as I know. (The commands that let you manipulate the environment of the bash process are built into the shell and do not run as a separate process, precisely for this reason.)

However, you could make it print the same string to the standard output and run it with backticks, or run source ~/.bash_profile after you run this program.

OTHER TIPS

You'll need to call it

 system(mystring.c_str());

The system() function has no notion about std::string, it requires a const char* parameter, which can be aquired from a std::string using the c_str() method.

Also note that the applied system() command doesn't export the path anywhere than to the (sub-)shell started from it, neither it goes to your local profile.

To really achieve what you intend, you'll need to open and modify your ~/.bashrc file (you can simply append another export PATH=$PATH:<your stuff> line there)! (see here for more information)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top