0

I am trying to run a C++ app (under Linux) from another directory. The app is supposed to read some files in the directory where it is. Let's assume the executable is in

/opt/app/proj/

All files to read by the app are in the same directory if I run the code from this directory, everything runs fine. but if I am in /home/user/Document/ and execute the code

/opt/app/proj/application

it does not find the files!! in my C++ code I have added something like:

string cwd(get_current_dir_name());
string path(argv[0]);
string CONFIG_FILE = "configuration.conf";
string FILETYPES  = "extensions.txt";

int pos = path.find("./");
if(pos>=0){
    path = cwd+path.substr(pos+1, path.length()-1);
}
pos     = path.find_last_of("/");
path    = path.substr(0,pos+1);
CONFIG_FILE = path + CONFIG_FILE;
FILETYPES   = path + FILETYPES;

It still doesn't work.. Need help...

PhoenixBlue
  • 967
  • 2
  • 9
  • 26
  • What is `CONFIG_FILE` ? Which variable do you use ? More code more declarations. – Blacktempel Aug 18 '16 at 15:40
  • print all the paths in your app and check if the paths you are formulating are correct. Use cout to print or gdb to debug. – Ravi Aug 18 '16 at 15:44
  • Hi CONFIG_FILE and FILETYPES are just two strings defining file names I just edited my question. Sorry for the misunderstanding – PhoenixBlue Aug 18 '16 at 15:45
  • It doesn't work because the working directory is the directory from where you start the program, not where the programs executable is. This is the reason many applications have arguments specifying things like configuration files or paths to their configuration files, because in the POSIX world there is no way to get the directory to where the executable is (or at least no *portable* way, on Linux check the symbolic link `/proc/self/exe`). – Some programmer dude Aug 18 '16 at 15:46
  • @Ravi funny enough when I run the code from its directory, I can print all the files, no problem. But when the code is ran from my documents, it does not print those! – PhoenixBlue Aug 18 '16 at 15:46
  • Also, manual handling of paths is cumbersome. I recommend you look into the [Boost filesystem library](http://www.boost.org/doc/libs/1_61_0/libs/filesystem/doc/index.htm). Or the upcomming C++17 [`std::filesystem namespace](http://en.cppreference.com/w/cpp/filesystem). – Some programmer dude Aug 18 '16 at 15:48
  • @PhoenixBlue I meant the 'path' not the file names. make sure the paths are correct/absolute. If they are relative then they will be appended to the current working directory(cwd). Since you are running the application from a different directory - relative paths will result in missing files. Start by checking the value of 'path' in your app. – Ravi Aug 18 '16 at 15:54

4 Answers4

0

Starting a new process on Linux is, roughly, a two step process:

  1. The fork() system call.

  2. The child process executes the exec() system call.

To start the new process from a different directory, just have the child process chdir() to the directory, before executing the exec() system call.

If you are using system(), you can replace it with fork()+exec(), to do this, or since system() executes the shell, to actually run the command, you can manually prepend the "chdir" command, although this is less clean.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

If you need to find the path to your executable, just read the /proc/self/exe symlink, then you can use dirname() or basename() on that to get the directory and then chdir() to that location and access your files just as if you had been started there.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
0

To directly answer your questions, the working directory for Linux is the directory where the executable was started not where is resides. As others mentioned, you can use readlink to get the path from the /proc/self/exe. You can then use the fully qualified path to find other files of interest. Here are some details and examples.

In general, I would not recommend this approach. The two approaches that I've commonly used are:

  1. Always start the program(s) from a certain relative directory. For example, [variable path]/bin will be the starting point. Use relative paths in the executable to find other files. The ../log for logs, ../conf directory will contain configuration files and so. If the executable is not started from the right spot then it just immediately errors out when trying to open a file. This approach has the advantage of using relative paths so that moving to a new root is simple.
  2. Pass the config file as a command line parameter or env variable. The config file will contain full details on other files of interest without referencing the relative starting place of the executable. The binary starts from anywhere and the config file has all the details. If the config file has a bunch of hard coded path then this approach can be a hassle when a new root is required. A good approach is to define a ROOT variable e.g. ROOT=/home/mfisher/project and then have other paths relative to that e.g. BIN=$ROOT/bin
Community
  • 1
  • 1
Matthew Fisher
  • 2,258
  • 2
  • 14
  • 23
-1

Thanks very much for your input. Actually my code worked, it just that I was trying to read from the config file before doing this process above. My mistake. Though, I tried to have a look at your propositions to know better about C programming. Thanks again!

PhoenixBlue
  • 967
  • 2
  • 9
  • 26