views:

291

answers:

2

Hello, I want to make some C++ program and I'm using function popen here to send commands to command line in Unix. It works fine, but when I call "cd directory", the directory doesn't change. I thing that it's same when I try to run "cd directory" in some script, after finishing script directory path change back. So, scripts I must run like ". ./script.sh" not "./sript.sh", but how to do that with popen function? I have tried to add ". " before first argument of popen, but running ". ls" makes error.

Code:

    cout << "@ Command from " << session->target().full() << ": " << message.body() << endl;
    //cout << "Prisla zprava" << endl;
    //m_session->send("Hello World","No Subject");
    //system(message.body().c_str());
    //if (nessage.body()=="")
    FILE* outp;
    char buffer[100];
    string outps="";
    outp = popen(message.body().c_str(),"r");
    while ( ! feof (outp) )
    {
            fgets (buffer , 100 , outp);
            outps=outps+buffer;
    }
    pclose(outp);
    cout << "& Output from command: " << outps << endl;
    m_session->send(outps.c_str(),"Output");`

In message.body(); is string which I want to run (I'm receiving this from XMPP). When the string is for example "ls", it returnes string with list of files in actual directory. But when the message is "cd directory", nothing happens, like triing to change directory in scripts.

A: 

It seems you have a bit of code that you do not understand. You are reading from outp, a pipe. Naming an input pipe outp is rather confusing. You then take the string you've read and pass it to m_session->send().

Nowhere in this whole process are you interacting with the Unix command line. In particular, popen() is not.

MSalters
Nope, you don't understand it.I got some string in message.body();. I create FILE* named outp (it's outp cause here I get output of function popen). I'm calling function popen, function popen takes string from argument, give it to Unix system and output from this command gives to outp. So if I want to call "ls" in C++ program, I'll call popen("ls","r") and the output of ls is in file, which popen returns. It works. But it doesn't work with "cd directory", as if you try to call "cd directory" from some bash script.
Garret Raziel
If you get the _output_ of another program, it's _input_ for you.
MSalters
+2  A: 

Typically, the way the popen() command executes the command is via the shell. So, it opens a pipe, and forks. The child does some plumbing (connecting the pipe to the standard input or standard output - depending on the flag) and then executes

execl("/bin/sh", "/bin/sh", "-c", "what you said", (char *)0);

So, how it all behaves is going to depend on your key environment variables - notably PATH.

If you want to execute a script in the current directory, then one of these options:

outp = popen("./script.sh", "r");
outp = popen("sh -x ./script.sh", "r");
outp = popen("sh -c './script.sh arg1 arg2'", "r");

If you want to execute the 'ls' command:

outp = popen("/bin/ls /the/directory", "r");

And if you want to change directory before running something:

outp = popen("cd /somewhere/else; ./script", "r");

And so on...

If you want to change the directory of the program that is using popen(), then you need to use the 'chdir()' system call (or possibly fchdir()). If you think you might want to get back to where you started, use:

int fd = open(".", O_RDONLY);
chdir("/some/where/else");
...do stuff in new directory
fchdir(fd);

(Clearly, you need some error checking in that lot.)

Jonathan Leffler