I’m trying to create a program that can open a terminal browser and navigate through a website. It works fine up until the child process is called. The following error shows up
“xdotool: Unknown command: search –onlyvisible –name Terminal windowactivate keydown Down”
I’ve tested the command in a separate terminal and it indeed works but it doesn’t get recognized in my code. I get the feeling it might have to do with the fact that execl doesnt return back to main but I’m new to programming so I don’t know for certain.
Heres the code
#include <iostream> #include <string> #include <unistd.h> using namespace std; int main(int argc, char *argv[]) { string thread; cout << "website: "; cin >> thread; const char* xdo = "xdotool"; pid_t pid = fork(); string strThread = "" + thread; string xdoCMD = " search --onlyvisible --name Terminal windowactivate keydown Down"; if (pid < 0) { cout << "Process failed" << endl; return 1; } else if (pid == 0) { execl("/usr/bin/xdotool", "xdotool", xdoCMD.c_str(), (char *) NULL); } else { // sleep(1); execl("/usr/bin/elinks", "elinks", strThread.c_str(), (char *) NULL); } }
Advertisement
Answer
execl(3) is calling execve(2) (whose arguments go into the main
of the executed program). They return only on failure.
So
execl("/usr/bin/xdotool", "xdotool", xdoCMD.c_str(), (char *) NULL);
is calling the xdotool
program with two arguments, xdotool
and xdoCMD.c_str()
-as a single second argument.
You should split xdoCMD.c_str()
into several pieces. Build an appropriate (NULL
terminated!) array of char*
from it, then call execvp(3) on that.
In effect, you should mimic what the shell does. Perhaps you might even want globbing (but you need to decide what kind of expansions you want; beware perhaps of code injection). See glob(7).
Don’t forget to check against failure (of fork
, execvp
etc…)
BTW, both the gdb
debugger (don’t forget to compile with g++ -Wall -g
) and strace(1) are useful to find such a bug.