Get the running file name: argv[0] vs boost::filesystem::current_path() - c++

I am trying to get the current running file name in C++. I wrote a simple code that uses both argv[0] and boost current_path() method. The file is compiled into executable file mainWindow.
#include "boost/filesystem.hpp"
int main(int argc, char* argv[])
{
boost::filesystem::path full_path( boost::filesystem::current_path() );
std::cout << full_path.string() << "\n";
std::cout << argv[0] << "\n\n";
return 0;
}
Interestingly the output of each method is different.
argv[0] output is:
../VENTOS/src/loggingWindow/mainWindow
current_path() output is:
/home/mani/Desktop/VENTOS_Redpine
I am not running my program (mainWindow) directly from the terminal. Another application is calling my program and I guess that's why the output is different. Am I right on this?
My second question is: Without using the argv[0] option and relying only on the boost filesystem methods, how can I get the same result as argv[0]?

argv[0] only contains the command used to execute the the program. This may contain the path. It may contain a relative path. It may contain no path at all. It might not even contain the executable name thanks to symlinks etc.... It might even be empty if the hosting system chooses to provide nothing. It can't be trusted, so you don't want to use this as a basis for evaluating other methods.
boost::filesystem::current_path fails you because it only returns the current working directory. This may or may not be the location of the executable because it depends on the directory from which the program was run and whether or not the working directory has been changed by the program. To be honest I'm not sure if there is a sure-fire way to get the process name and path from Boost. There wasn't a few years ago, but time has a way of marching on, you know?
There are a slew of questions covering how to get the executable and path (Finding current executable's path without /proc/self/exe looks promising but is stale. That time marching thing again.) but all are platform-specific you may have to do some ifdef or linker wizardry to make this work.

Related

.exe does not run with more than one instance of "../" in the path

Issue
I have a Release-compiled MSVC C++17 "server" application. I usually make a child process from the client application to run a local server, so I use a relative directory path for the command line to execute as the child process. I am emulating that call here by typing in the relative path manually in powershell from where the client application executable runs.
It seems running run_Server.exe works with a command line like:
(Case 1)
PS C:\Users\me\Documents\MyProjectRelease1.0\Client_App_Folder> ../Server_App_Folder/run_Server.exe -help
(Proceeds to print out help)
But not with a command line like:
(Case 2)
PS C:\Users\me\Documents\MyProjectRelease1.0\Client_App_Folder\Client_App_Subfolder> ../../Server_App_Folder/run_Server.exe -help
(Waits a second then exits the program without any output)
Note: Client_App_Subfolder has an identical name as Client_App_Folder due to unimportant reasons.
Why is this happening? I may be mistaken, but I thought this did not happen under the exact same circumstances previously. I'm not finding much in the way of documentation about this phenomenon yet. I think this might have something to do with the up-directory ..\s in the command. Slash direction seems to not alter the results in this case in powershell.
Attempted Troubleshooting
Here's the first portion of main.cpp:
// Other #includes above.
#include <filesystem>
#include <iostream>
int main(int argc, char* argv[])
{
std::filesystem::path cwd = std::filesystem::current_path() / "filename.txt";
std::ofstream file(cwd.string());
file.close();
// ...proceed to parse command line arguments, etc.
}
This code results in outputting filename.txt in the MyProject\Client_App_Folder directory for the first case, but nothing for the second case.

how to pass on some output from a c++ program to the shell so that it can be used in the shell

Is there any good way i can make some data created by my c++ program available to the shell after exiting the program?
I have a c++ program, inside which i have a string containing a path:
std::string path = "/home/some/path"
I want this path to be available after the c++ program exits main and i am returned to the shell, so that i can use that path (e.g. cd to that path).
I have considered/tried the following approaches:
I tried making an environment variable in c++ program using setenv(). However the environment variable only exists while in the c++ program, and it is apparently not possible to make those changes visible in the shell after exiting the program.
(considered) writing the path to a temporary file, so that a bash script could later access the details of the path from it. However i have read many suggestions to not do that due to security vulnerabilities.
I tried calling the bash script from within the c++ program, using system(). This does not work if i try to cd to that directory (exiting the program will keep me in the same directory as before).
I figure that if i am desperate, i could have my program cout the path, and use the solutions as described here:
$ ./program | tee output.txt
Then the path is stored inside the file. This works technically, but has the undesirable effect of creating a file and printing the path to the screen, and is basically creating a temporary file.
another option to, again, cout in my program, and use command substitution. running in the shell
$ var=$(./program)
storing the path in var. This didnt work because my program does many things including requiring user input before calling
std::cout<< path << std::endl;.
Particularly, i have observed this approach to not display a curses window, which is required for the program.
the only solution that has worked is piping the output to tee.
Environment variables are only an input, they cannot be used to return any information from a program.
You are already using std::cin and std::cout for user input, and std::cerr should be reserved for error messages. However, you can have the shell open more filedescriptors, and have your program write to those. However, doing this with pure C++ is not possible. But if you don't mind using POSIX C functions:
#include <cstdio>
int main() {
FILE *f = fdopen(3, "w");
fprintf(f, "some path\n");
}
And then use it like so:
./program 3> output.txt
This of course creates an undesirable file. I don't think there is any way to store the output from an extra filedescriptor directly to a variable in bash. However, you could create a temporary file inside /dev/shm, so it will never be written to disk, or create a FIFO object and redirect the output from the program to the FIFO, and then read it back. For some examples of how to do this, see this question.
You could write the output that you want the user to see to stderr instead of stdout. Only output what you need your shell script to see to stdout:
#include <iostream>
int main() {
std::clog << "Enter data: "; // clog prints to stderr like cerr
std::string line;
std::getline(std::cin, line);
std::cout << line << '\n';
}
Then this will work:
var=$(./program)

QSettings weird behaviour on MacOS

Using Qt 5.11.1 via homebrew on MacOS 10.13.6, I'm using QSettings in my application. This is a working program that I'm porting from Linux and Windows now to MacOS.
The issue I'm having on MacOS is that it'll save the file to /Users/michaelleonetti/Library/Preferences/com.sonarcloud.Sonarcloud Service.plist, which it's supposed to, on first program execution.
If I delete the file sometimes it comes back. Sometimes it doesn't. If I edit the plist file with Xcode and save it, the values I write in "have" won't be there.
I can't identify a rhyme or a reason to make it work.
I've created a minimal example:
#include <QSettings>
#include <iostream>
int main( int argc, char *argv[] )
{
{ // Scope
QSettings settings( QSettings::NativeFormat, QSettings::UserScope, "My Application Company", "My Application" );
if( settings.contains( "have" ) )
std::cout << "We have: " << settings.value( "have" ).toString().toStdString() << std::endl;
else
std::cout << "You do not have" << std::endl;
settings.setValue( "version", 10 );
std::cout << "Path is: " << settings.fileName().toStdString() << std::endl;
}
return( EXIT_SUCCESS );
}
Output:
$ ./src/reproduce
You do not have
Path is: /Users/michaelleonetti/Library/Preferences/com.my-application-company.My Application.plist
File check
$ cat "/Users/michaelleonetti/Library/Preferences/com.my-application-company.My Application.plist"
cat: /Users/michaelleonetti/Library/Preferences/com.my-application-company.My Application.plist: No such file or directory
How can I get this issue solved?
I think this is due to QSettings being implemented on top of Apple's CFPreferences database. This is expected behavior and the "fix" is to call CFPreferencesSynchronize()
Docs:
writes all pending changes to preference data to permanent storage,
and reads latest preference data from permanent storage
Luckily it appears that QT wraps this in its Mac implementation for QSettings and you should be able to call QSettings::sync() to do this in a platform agnostic way.
Basically you need to synchronize your settings before you will see any changes from external writes**. This is also why the file doesn't appear to always be rewritten (it should on application exit when things are automatically flushed).
Note that you will also need synchronize your settings from the external application by calling CFPreferencesSynchronize() within that application in order to see changes made by your QT app.
It also might be interesting to know that there is a command line utility available called defaults that you can use to perform syncronized writes from a shell script or terminal.
** This occurs naturally at certain points automatically.

Run the same C++ Program from different Binary Names

Okay, for a homework assignment my professor wants us to write a program in C++ that converts from miles to km. I did all that, the program runs. However, he has this special way of calling the program:
The program's usage options are based
on the NAME of the BINARY FILE. If
the program name is 'km2miles', the
program interprets the command line
argument as a kilometer value to
convert to miles. If the name is
'miles2km', then it interprets as
miles being converted to km. Since the
first command line argument, argv[0]
is always the program's name, you can
use its value to decide which function
to call.
I only have 3 files in this project (he tells us to ONLY have these 3):
convert.cpp
distance.cpp
distance.h
Distance .h and .cpp have the different functions to convert Mi to Km and Vice Versa, the convert.cpp has the main function. However, the only way I know how to call this program (after compiling it) is to say:
./convert 10
Where 10 is the number to convert. He says it should be called like this:
$ km2miles 100
and
$ miles2km 60
I have no idea how to get the program to act differently by having a different name... especially when that name doesn't even run the program! Help would be appreciated.
You can:
specify a name when you build it, and build it twice
on Windows: copy convert miles2kms; copy convert kms2miles
on UNIX/Linux: cp convert miles2kms; cp convert kms2miles
on UNIX/Linx (better): make a link or symbolic link: ln -s convert miles2kms; ln -s convert kms2miles.
Inside your program, you should be doing something like:
#include <string>
#include <iostream>
int main(int argc, const char* argv[])
{
std::string program_name = argv[0];
if (argc != 2) {
std::cerr << "usage: " << program_name << " <value>\n";
return 0;
}
if (/* TODO: what would go here? */)
...
else
...
}
The instructions already tell you how:
Since the first command line argument, argv[0] is always the program's name, you can use its value to decide which function to call.
especially when that name doesn't even run the program!
If you're using gcc, by default it generates a binary named a.out, but you can rename it to be whatever you want. (Or you can specify the name of the output file via the -o command-line option.)
Well, he gave you one clue with the argv[0] thing.
Did you perhaps discuss symbolic links at some point in your class?
Difficult for me to give more hints without actually giving away the answer.
If you don't want to recompile the same code into 2 different executable files then you may need to use a symbolic link:
http://en.wikipedia.org/wiki/Symbolic_link

Executing a command from C++, What is expected in argv[0]?

I am using execv() to run commands from /bin/ such as 'ls', 'pwd', 'echo' from my c++ program, and I am wondering what value I should provide in argv[0];
const char * path = getPath();
char ** argv = getArgs();
execv(path,argv);
argv[0] is supposed to be the program name. It's passed to the program's main function. Some programs differentiate their behavior depending on what string argv[0] is. For example the GNU bash shell will disable some of its features if called using sh instead of bash. Best give it the same value that you pass to path.
In linux, argv[0] is the process name displayed by the top utility (which it probably gets from reading entries in /proc/)
argv[0] should be the full path of the command that you want to run.
I know that this is not the answer you're looking for but is there a specific reason why you're doing this? The reason I ask is that most if not all of the actions people normally run with either system() or execv() are available in libraries on either Windows or Unix and are safer, faster and less likely to suffer from circumstantial errors. By that I mean, for example, when the PATH changes and suddenly your code stops working.
If you're passing in a string, either in whole or in part, and running it then you also leave yourself open to a user gaining access to the system by entering a command that could be damaging. E.g. imagine you've implemented a file search using find /home -name and your user types in:
"%" -exec rm {} \;
Ouch!