ayat101 has asked for the wisdom of the Perl Monks concerning the following question:

@args=("$pipeline/EXE/searchXY", "-5", "UEB2K005I", "$TRI", "234", "156", "4", "Print");
system(@args);

I have the above C program with its arguments in the standard way. It is not really important what the program does, as I need to do this for several different programs.

The program expects a filename in place of $TRI, or a variable with a string in it which will be used as the filename. The output is then printed to a textfile with the filename.

I want to instead send the output to a pipe so I can read it without going through writing to and accessing a text file, so I speed up the processing as this gets repeated many thousands of times.

I can not append the program call with a pipe, because the results do not go there. I need to trick the C program into thinking a pipe handle is a textfile.

How do I do this? Perhaps I need to invoke the program in a different way? Is it even possible?

Considered by Tanktalus - code tags, please
Unconsidered by castaway - Keep/Edit/Delete: 4/33/0 - Looks fine to me

  • Comment on Replace filename with pipe in program argument?

Replies are listed 'Best First'.
Re: Replace filename with pipe in program argument?
by Roy Johnson (Monsignor) on Mar 21, 2005 at 19:09 UTC
    If you are on a Unix system, see mknod, which will allow you to create a named pipe.

    Caution: Contents may have been coded under pressure.

      Or if your OS supports it, you could make a pipe and use /dev/fd/# (or the like) as the filename.

      Thanks :)

      This kind of works:

      my @args=();
      @args=("$pipeline/EXE/searchXY", "-5", "UEB2K005I", "locate", "234", "156", "4", "Print"); system(@args);

      where earlier system "/usr/bin/mkfifo $pipeline/OUT/locate";

      this sends it to the right place, but it gets the stuck at the process. Namely, the pipe is open for writing, and waits to be read, the C program gets paused until something reads the pipe... no problem so far :) This is as it should be from what I managed to understand about named pipes.

      One more minor problem is that my whole script gets stuck at the point of when the pipe is open, waiting to be read... as the reading part is after the pipe open (the call to the C program opens it).

      I suspect I need to start off the C program as some independent process, NOT use system(). I'll post the solutions when I fully work it out. The KEY here were named pipes :)

      THANKS ALL :) The suggestions were RIGHT what I needed.

        You just need to fork before you call system, so that your system is running in its own process.

        Caution: Contents may have been coded under pressure.
Re: Replace filename with pipe in program argument?
by graff (Chancellor) on Mar 21, 2005 at 19:40 UTC
    How much do you know about the C program(s) that you'll be running this way? Sometimes, when command-line tools are written to require filename args, a filename of "-" (dash character \0x2d) is accepted as referring to stdin (when the required arg is an input file name) or stdout (when the required arg is an output file name).

    If your C programs follow this sort of convention, do a pipeline "open()" to launch the sub-process, and put "-" where the output file name should be. Then read from the pipeline file handle in the normal way, just like reading from any data file.

    (If the C programs don't follow this convention, and you don't have / can't update the C source code, and you can't create a named pipe as suggested in an earlier reply, then you'll just have to put up with saving output to a named file, and reading that file as a separate step in your perl script.)

Re: Replace filename with pipe in program argument?
by insaniac (Friar) on Mar 21, 2005 at 18:51 UTC
    even worse: is it really related to this site? I thought it was about Perl... :-/

    but i would suggest: change the C program to output to plain old STDOUT if you want to catch the output in a pipe ( for instance with a normal printf)

    --
    to ask a question is a moment of shame
    to remain ignorant is a lifelong shame
Re: Replace filename with pipe in program argument?
by ayat101 (Initiate) on Mar 21, 2005 at 19:10 UTC
    I need this solution for good reasons. Modifying the C programs is not practical - in effect can not do it.

    Plus Perl is used to "glue" other programs together, it is a well known approach, and this is how I use it in large parts... so it is 100% Perl related. I'm just curious if enybody has ever managed to do it? Or if they even heard of a way to do it?

Re: Replace filename with pipe in program argument?
by perlfan (Parson) on Mar 21, 2005 at 20:15 UTC
    This might help. It is simple C program I wrote a while back that takes in STDIN, and prints it to STDOUT.
    #include <stdio.h> #include <stdlib.h> #define RETBUFF 512 int main(int argc, char** argv) { char* input[RETBUFF]; while (fscanf(stdin,"%s",&input) != EOF) { printf("%s",&input); fflush(stdout); } return 0; }
Re: Replace filename with pipe in program argument?
by ayat101 (Initiate) on Mar 22, 2005 at 10:17 UTC
    Ok, got it now, and it works properly :)

    unless (defined ($pid = fork)) { die "cannot fork: $!"; } unless ($pid) { my @args=(); @args=("$pipeline/EXE/searchXY", "-5", "UEB2K005I", "locate", "234 +", "156", "4", "Print"); system(@args); exit; # the child stops here } open(FIFO, "<$pipeline/OUT/locateXY"); my $line; while ($line = <FIFO>) { print "rep $line"; #or whatever here } close(FIFO); waitpid($pid, 0); #clean up

    Now I just need a good reference/tutorial on fork to understand this properly :)

    P.S. At some points you may want to add the two following lines, at appropriate places, before and after you use the above code, respectively:

    system "/usr/bin/mkfifo $pipeline/OUT/locateXY"; system "chmod 777 $pipeline/OUT/locateXY"; #as needed system "rm $pipeline/OUT/locateXY"; #to clean up if required