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

Hello all. I am trying to make my perl script communicate with Rational Clearcase - update a snapshot view. To keep a long story short, if you are removing a vob source repository from a config spec of a snapshot view, clearcase prompts you asking if that is ok. Rational decided this prompt should be sent to STDERR instead of STDOUT. Doh! Here's my problem. I am trying to make my code answer the question with a "yes" every time. However, I can't seem to trap the output that's going to STDERR, send a yes, and continue on with the update.

Can anyone give me a hand? here's what i have so far:

local (*HIS_IN, *HIS_OUT, *HIS_ERR); my $pid = open3(*HIS_IN, *HIS_OUT , *HIS_ERR, "cleartool setcs $CS_FIL +ENAME"); while(<HIS_OUT>){ print "$_"; if (<HIS_ERR>){ print HIS_IN "yes\n"; } } close HIS_IN; close HIS_OUT; waitpid($pid,0);

This seems to get stuck in an infinite loop. This seems like it sends in the "yes" because the update continues (and i'd want to send in a "yes" to ANY of those updates..which is why there's no regex)...but something happens later on and the process seems to hang.

Code tags added by GrandFather

Replies are listed 'Best First'.
Re: IPC::open3 obfuscification
by tilly (Archbishop) on Dec 17, 2008 at 02:27 UTC
    The likely problem is that you check HIS_ERR before anything is written there, then wait on output to HIS_OUT. Meanwhile he sends output to HIS_ERR and waits for input on HIS_IN. (It is theoretically possible that there are additional buffering problems.)

    There are generally 3 ways to go. First you can look for a real API to use that will be more reliable. Secondly you can learn about select, sysread and syswrite. This will let you follow 2 handles at once, but you will need to handle stuff that Perl normally takes care of with buffering. The third is that you can use a module like Expect to abstract away some of those details.

    I would first look for an API, then I'd look at Expect. I would not hand-roll a solution from unbuffered IO.

Re: IPC::open3 obfuscification
by ikegami (Patriarch) on Dec 17, 2008 at 02:30 UTC
    <> blocks until a newline is received, so your program hangs if the client waits for input after sending two lines in a row to STDERR. You can also run into problems if the child's STDOUT is buffered.
      That is another possibility, and made me think of the following hackish solution that does what the original code was meant to:
      system("yes yes | cleartool setcs $CS_FILENAME 2> /dev/null");
      (This assumes Unix.)

      If you want more flexible error handling you need to go down the other paths I suggested.

      It will be nearly impossible for me use an API. There is a lot of legacy code surrounding this snippet. Is it possible to redirect STDERR to STDOUT and do a pattern match on the phrases I would want to send "yes" to, will that work? My other question is - once STDERR has something in it, does the process continue? I tried just sending "yes" to the input after every line, however, my program still hung after a bit. Almost like once STDERR had something in it, STDOUT got nothing, and thus, the snapshot update also stopped.
        Redirecting is possible, but is very likely to create buffering issues. Printing after every line can cause possible problems if either there are buffering issues, or if 2 questions are asked in a row. There is also the possibility that at some point it asks a non-yes/no question, in which case you need more logic. Try my suggested hack, if that fails you should be able to see the question it trips up on.

        About using an API, I know what legacy code can be like but you still can do it. Just put a well-named function call in that line, and go off to write your function somewhere however is best. Then the legacy code is no worse, and you're free to write that function however you see best.

Re: IPC::open3 obfuscification
by Anonymous Monk on Dec 17, 2008 at 01:37 UTC
    Wow. That's really ugly. Can a mod fix my post to make that code display correctly?
      Also, that is my post..sorry for not being logged in