ron@mlfarm.com (Ronald Florence) (03/13/91)
I can't get this bit of code to work: procedure main() write(pipe("bogus-command", "nonsense", "logname")) end procedure pipe(cmd[]) until inf := open(pop(cmd), "pr") got := !inf close(inf) return got end The idea is to try opening a pipe to a series of commands until one succeeds. It doesn't work (at least here), because instead of the open() failing on "bogus-command" and "nonsense", the shell reports that the command wasn't found. Any idea how to do what I want to do? -- Ronald Florence ron@mlfarm.com
nowlin@isidev.UUCP (03/16/91)
> I can't get this bit of code to work: > > procedure main() > write(pipe("bogus-command", "nonsense", "logname")) > end > > procedure pipe(cmd[]) > until inf := open(pop(cmd), "pr") > got := !inf > close(inf) > return got > end > > The idea is to try opening a pipe to a series of commands until one > succeeds. It doesn't work (at least here), because instead of the > open() failing on "bogus-command" and "nonsense", the shell reports > that the command wasn't found. > > Any idea how to do what I want to do? > -- > > Ronald Florence ron@mlfarm.com The problem is that the pipe-read in Icon invokes the command in a sub-shell and the open of the sub-shell almost never fails. That's why the first bogus command in your list terminates the program. The main reason to test the success or failure of the open in this program is in case the pop() fails. The real way to test the success or failure of a command invoked with the pipe-read is to check the return value from the close of the pipe. This is where the exit code of the command is returned. For standard UNIX this exit code should be zero if the command succeeded. The second problem is that the "not found" error comes from the sub-shell instead of the command being tested. There's no (easy) way to redirect that error output without invoking the command in a separate sub-shell. The following program works that way. I included three sets of test data since the possibility of an infinite loop, if there's no command that succeeds, should be tested: procedure main() write(pipe("bogus-command","nonsense","logname","more-junk")) write(pipe("bogus-command","nonsense","lognothing","more-junk")) write(pipe("logname","bogus-command","nonsense","more-junk")) end procedure pipe(cmd[]) repeat { inf := open("(" || pop(cmd) || ") 2>&1","pr") | fail got := !inf if close(inf) = 0 then return got } end This version of pipe() follows the basic algorithm you used. I know the order of precedence of the expression containing the open() is not obvious here but once a procedure fails it fails. It doesn't make any difference if it's trying to assign the result of failure to a variable. The following version of the pipe() procedure uses goal directed evaluation instead of iteration. I like this one better: procedure pipe(cmd[]) if inf := open("(" || !cmd || ") 2>&1","pr") & got := !inf & close(inf) = 0 then return got else fail end +-------------------------------------------------------------------------+ | --- --- | | | S | Iconic Software, Inc. - Jerry Nowlin - uunet!isidev!nowlin | | --- --- | +-------------------------------------------------------------------------+