0

I'm having a problem running a perl script from within a C++ program using popen.

As soon as I call fgets, feof will return 1

So far, I have the following code.

std::string PerlOutput = "";
std::stringstream CommandToRun;
CommandToRun << "perl " << ScriptFile << " " << ParametersToPass; //Both variables are type std::string
std::cout << "Executing perl script, command to execute is:\n" + CommandToRun.str() << "\n";
FILE * perl_outpipe = popen(CommandToRun.str().c_str(), "r");
unsigned int MaxLineLen = 512;
char buffer[MaxLineLen];
while(!feof(perl_outpipe))
{
    if(fgets(buffer, MaxLineLen, perl_outpipe) != NULL)
    {
        PerlOutput.append(buffer);
    }
}
pclose(perl_outpipe);
std::cout << "Perl script output:\n" << PerlOutput << "\n"; //Huh? It's empty!
std::cout << "length of perl's output: " << PerlOutput.length() << "\n";

The idea is that perl's output may or may not be larger than the buffer, so with each fgets call, I simply append it into an std::string object, and deal with it once perl has finished its output.

But nothing ever gets appended into this string, as it immediately hits an eof. I first thought that maybe the command I was giving to popen might be wrong. Space characters in the wrong place etc, so before calling popen, I dump the exact command. If I copy and paste this command to a terminal window, and run the command myself, it works as expected.

Executing perl script, command to execute is:
perl scripts/testscript.pl param1=abc param2=123 param3=Nooo!\ not\ Jackson\ 5!

After a bit of reading, I found someone else with what sounded like the exact same problem a year ago. There were some slight differences, like PHP instead of Perl. Invoking the script directly, rather than calling the interpreter, with the script as an argument. And CentOS (where I'm using Debian). Other than that, it sounded almost exactly the same...

Apparently in that case it was a permissions issue, but this doesn't appear to be the case with me.

The permissions are:

rw-r--r-- mumbles mumbles scripts/testscript.pl
rwxr-xr-x root root /usr/bin/perl

My program is running as me (not as its own user), so it should have my permissions right? Everyone can read my script, and everyone can execute perl. So, if I can invoke my script that way, can anyone see why my C++ program can't?

My program's output (after perl has supposedly done its thing

Perl script output:

length of perl's output: 0
Community
  • 1
  • 1
Mumbles
  • 43
  • 5
  • Don't do `while (!feof(...))`, it will not work as you expect it to. Instead do e.g. `while (fgets(...) != NULL)`. – Some programmer dude Aug 19 '14 at 13:23
  • As for your question, if you run the script manually with the same arguments, what happens then? What output do you expect? Oh, and `perl_outpipe` is not `NULL`? – Some programmer dude Aug 19 '14 at 13:24
  • Also, check the return value of pclose. Pasting the same string on the command line isn't necessarily proof that it runs in popen. – greggo Aug 19 '14 at 13:26
  • I've added a few perror statements to try and trackd own where it is... – Mumbles Aug 19 '14 at 15:37
  • Immediately after popen, I've got `perror("popen");` which returns `popen Success`. I've changed the while loop as above. and have a perror inside it - it never gets called. I have one after it `perror("fgets-after");` and get `fgets-after: Invalid argument`. OK, sounds like I've found it... So I've added `std::cout << "ferror " << ferror(perl_outpipe)` and get `ferror 0`. So apparently no error. Finally I added `std::cout << "feof " << feof(perl_outpipe)` which prints `feof 1` The only error I can see is reaching end of file. – Mumbles Aug 19 '14 at 15:45
  • I cannot reproduce this, even with the buggy `while(!feof(perl_outpipe))` line. Try printing debug messages to stderr from the perl script. – n. m. could be an AI Aug 19 '14 at 15:52
  • @n.m. When I run the script manually in the terminal, it doesn't produce any debug errors. It was as barebones as I could make it. Literally just gets the parameters and prints them out `#!/usr/bin/perl -w use CGI':standard'; #for $param=param('arg') $param1=param('param1'); $param2=param('param2'); $param3=param('param3'); sub main() { print "param1: $param1\n"; print "param2: $param2\n"; print "param3: $param3\n"; } main();` – Mumbles Aug 19 '14 at 16:36
  • Let me try again. *Try printing debug messages to stderr*. This means take your script and insert new print statements that print to stderr. Then test it out. – n. m. could be an AI Aug 19 '14 at 16:38
  • OK, stderr printing isn't appearing in the program's console either, but once again, they are appearing when run manually from the terminal. At this point I'm fairly sure there is something wrong in the command I'm giving to popen, but just can't see what. unescaped backslashes have caught me out in the past, but that seems OK here... – Mumbles Aug 19 '14 at 17:13
  • This one probably won't be solvable. Elsewhere in the program, I was using popen to run ls. That one used to work, but at some point it's also stopped working. It doesn't sound good. Anyone know what could cause that? Sadly, I think I know the answer already... – Mumbles Aug 21 '14 at 05:45
  • More worst nightmare had come true. What would cause a `popen("ls","r");` to fail? I'd overflowed a completely unrelated string elsewhere in the program... (Actually I'd done a strcpy on one that didn't have a null terminator) Fixed that and suddenly my popen to perl is working... – Mumbles Sep 07 '14 at 07:40

0 Answers0