I am trying to use execvp()
to execute terminal programs from a GUI program. My test of choice was calling konsole
(my terminal) with -e
for execution and nvim ~/test.txt
as the arguments. Calling the command from the Linux shell and writing the file yields expected results (the file already existed and had the following data prior to running both tests):
Output:
QLayout: Cannot add a null widget to QHBoxLayout/
Process <pid> did not die with SIGHUP
Calling the command using execvp()
via the following example produces the following:
#include <unistd.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
int main() {
vector<string> strvec = {"konsole", "-e", "nvim", "~/test.txt"};
vector<char*> vec;
for (auto& str : strvec)
vec.push_back(str.data());
vec.push_back(nullptr);
for (auto& arg : vec)
printf("%s\n", arg);
execvp(vec[0], vec.data());
}
Output:
konsole
-e
nvim
~/test.txt
(null)
QLayout: Cannot add a null widget to QHBoxLayout/
Process <pid> did not die with SIGHUP
The file is invalid?
Why is this happening, and what am I doing wrong?
~
only has special meaning to a shell, not in general for path names.
When you type ~
in a context where expansion happens in a shell, the shell will expand it to $HOME
(i.e. the home directory). The result will be used in the shell command.
So in your first example the shell will execute konsole
and pass the arguments
konsole
-e
nvim
/home/user/test.txt
(assuming $HOME
is /home/user
)
not as you are doing
konsole
-e
nvim
~/test.txt
~
itself is a valid character in Linux path names and ~
is just a normal directory with that name that nvim will then try to look for in the current working directory.
Additionally, as mentioned in the question comments, printf("%s\n", arg);
has undefined behavior when arg
is a null pointer value, although implementations are often nice about it and define it to print something like (null)
.