PDA

View Full Version : Executing a Program With Arguments



HalNineThousand
04-13-2008, 10:10 PM
I don't know how platform specific exec() and its relatives are, but my guess is it'd have to be.

I'm running an executable from a C++ program this way:


string cmd = "testprog", arg = "samp1", marg = "one two three";
execlp(cmd.c_str(), arg.c_str(), marg.c_str(), (char *) 0);


When I use this to call a test program I've written in C++, it works and each string is taken as a separate argument. Then when I change from my test program to using Xine, I change the first argument to a music file that's in the same directory and remove the 2nd argument. If I run Xine from the command like this:

xine music.flac

it works just fine, but when I try to run it from my program, with xine as the first argument to execlp() and the file name as the 2nd, it doesn't play or do anything.

To me, this isn't just a Xine issue. Whatever is making it not work with Xine could have the same effect with other programs.

Why is it that Xine won't read in the argument and play it? Could the program specifically be checking to see how it is run and acting differently? Is this a problem I'll be running into with a lot of programs?

Any help appreciated!

Thanks!

Valery Reznic
04-13-2008, 11:23 PM
I don't know how platform specific exec() and its relatives are, but my guess is it'd have to be.

I'm running an executable from a C++ program this way:


string cmd = "testprog", arg = "samp1", marg = "one two three";
execlp(cmd.c_str(), arg.c_str(), marg.c_str(), (char *) 0);


When I use this to call a test program I've written in C++, it works and each string is taken as a separate argument. Then when I change from my test program to using Xine, I change the first argument to a music file that's in the same directory and remove the 2nd argument. If I run Xine from the command like this:

xine music.flac

it works just fine, but when I try to run it from my program, with xine as the first argument to execlp() and the file name as the 2nd, it doesn't play or do anything.

To me, this isn't just a Xine issue. Whatever is making it not work with Xine could have the same effect with other programs.

Why is it that Xine won't read in the argument and play it? Could the program specifically be checking to see how it is run and acting differently? Is this a problem I'll be running into with a lot of programs?

Any help appreciated!

Thanks!

Change your code too


string cmd = "testprog", arg = "samp1", marg = "one two three";
err = execlp(cmd.c_str(), arg.c_str(), marg.c_str(), (char *) 0);
if (err) {
perror("EXECVP")
}

And look what errno says you.

Alternative approach is run your program under strace as
strace -f <your_program> [arguments]

and you'll see what actual arguments execve receive.

Valery.

HalNineThousand
04-14-2008, 12:11 AM
I get absolutely nothing from the error by changing the code. I did it slightly differently:


ecode = execlp(cmd.c_str(), arg.c_str(), marg.c_str(), (char *) 0);
cout << "Error return code: " << ecode << endl;
if (ecode) {
perror("EXECVP")
}

(I already had ecode as an int so I used that.)

It doesn't even print the first line after the execlp() function! I do get two lines of output from Xine, but it's the copyright notice and nothing useful. Even after I kill Xine (closing the window), my program exits and there's still no output from my program.

I tried with strace, but I've never even heard of that before and there are thousands of lines of output so I'm still working on that. I didn't see any error codes where xine was mentioned in the output, but I'm still looking.

After re-reading the exec() man page several times, it finally hit me what it means by "The exec family of functions shall replace the current process image with a new process image. The new image shall be constructed from a regular, executable file called the new process image file. There shall be no return from a successful exec, because the calling process image is overlaid by the new process image." In other words, I should not expect a call to exec() to ever return.

So when calling exec(), is it essentially forking or starting an independent thread?

This is the first step in what I am doing. I wanted to start a program and to be able to kill it after a length of time. This will be used to start a program to capture audio data and save it to a file for a set length of time. One thing I liked about exec() or, rather, execlp() was that I could have a config file that specified the program to run without needing the path and that I could pass a file name with the path to the program as an argument without having to scan it and add escape characters if it contains spaces or other troublesome characters.

My original idea was to use pthreads to create a thread that would launch a program, wait the length of time it would record the incoming audio, then kill that thread. My experimenting with threads shows this doesn't work, and I would think that's due to exec() not actually returning.

Is there something better for me to use or are there more ways to work with exec() so I can kill a program after I've started it? I've gotten a lot of noise when Googling on launching programs from within a C++ program. If I had to include the full path to the program I'm launching, I can deal with that, but I'd rather not have to scan a filename and escape the characters like spaces or quotation marks.

Salem
04-14-2008, 09:56 AM
ecode = execlp(cmd.c_str(), arg.c_str(), marg.c_str(), (char *) 0);
cout << "Error return code: " << ecode << endl;
if (ecode) {
perror("EXECVP")
}

If execlp() succeeds, then none of the commands which follow it will be executed.

Also, its cmd, argv0, argv1 etc, so perhaps
ecode = execlp(cmd.c_str(), cmd.c_str(), arg.c_str(), marg.c_str(), (char *) 0);

HalNineThousand
04-14-2008, 10:09 AM
Using the command as the 1st and 2nd argument does the trick. Thanks!

Now is there any way to kill the process after it's been launched?