stevesu@bronze.UUCP (Steve Summit) (09/23/83)
While I'm dredging up these silly old questions, here's another one: Has anyone ever fixed this long-standing bug in sh? "If << is used to provide standard input to an asynchronous process invoked by &, the shell gets mixed up about naming the input document. A garbage file /tmp/sh* is created, and the shell complains about not being able to find the file by another name." The first time I read that I thought, "What an obscure bug. Who'd want to do that?" Since then, though, there have been a couple of occasions when I've wanted to use that very construction. Given the bizarre way that the shell is written, and the fact that the bug has been so glaringly reported there in sh(1) for so long without being fixed, I would guess that it's nearly impossible. Has anyone tried? Steve Summit textronix!tekmdp!bronze!stevesu
guy@rlgvax.UUCP (Guy Harris) (09/27/83)
1) The description of the shell bug: "If << is used to provide standard input to an asynchronous process invoked by &, the shell gets mixed up about naming the input document. A garbage file /tmp/sh* is created, and the shell complains about not being able to find the file by another name." is incorrect. The correct version is: "If << is used to provide standard input to an asynchronous process invoked by &, the parent shell deletes a temporary file needed by the child shell executing the command. A garbage file /tmp/sh* is created, and the shell complains about not being able to find the temporary file." 2) Yes, I *tried* fixing it, by having the child shell delete the temporary file. The trouble is that you can construct a pathological case in which neither the parent nor the child shell knows the right time to delete the temporary file. "Here documents" which are to have shell variable and `` expansion performed are done with two files. The shell makes a literal copy of the text of the here document at the time the command line is parsed. Each time the command is to be executed, the shell reads from the literal copy, expanding variables and ``s, and writes the expanded copy to another file. Then the command is run with its standard input redirected to the expanded copy. Now, take the command: while (something) do command <<EOF & This is a $test. EOF done The child process (i.e., the one that's going to run the command "command") is the one that makes the expanded copy of the here document. Since the command is going to be executed in a loop, however, it can't delete the literal copy after it does the expansion because it may be needed next time around the loop. The parent knows when it's done with the loop; however, it does not know when the last child process has opened the literal copy, so it can't delete the literal copy after the last pass through the loop. After discovering this I gave up; does anybody see a way out? The C shell solves the problem by reading the literal copy directly from the shell file, which is presumably not deleted by the shell. I don't remember how it handles the case of when the loop is typed at the terminal. Since the same bug is listed in the 5.0 manual, I suspect nobody's come up with a fix yet; since it has the same statement of the bug, it is conceivable that nobody in the USG has looked into it. If anybody's fixed it, please let us all know; I have to create a lot of trash temporary files because I want to kick off loops in the background like that. Guy Harris {seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy
ntt@dciem.UUCP (Mark Brader) (09/29/83)
I don't think the shell should accept the example while (something) do command <<EOF & This is a $test. EOF done given by rlgvax!guy (Guy Harris). I think & should cut off what the forked shell sees, so that the above example would be typed as: while (something) do ( command <<EOF This is a $test. EOF ) & done Never having used a shell where <<...& worked anyway, I don't know whether the first version is supposed to work. However, an approximation of the desired effect can be obtained by now replacing the (...) with sh -c "...". It's not as good because of having to escape quotation marks and because of the limit on argument lists, but will work for simple cases. I also think the precedence of & and ; should not be equal; I think a;b&c;d& should be interpreted as (a;b)&(c;d)& with the present interpretation having to be typed as a;(b&);c;(d&), similarly to ; and |. Mark Brader, NTT Systems Inc., Toronto
guy@rlgvax.UUCP (Guy Harris) (10/01/83)
The example while (something) do command <<EOF & This is a $test. EOF done was incorrect; it should have read while (something) do command <<EOF This is a $test. EOF done & This sort of loop is useful if you want to nroff a bunch of documents in the background, the macro package has one-time actions (so you can't use one nroff command), and you want to stick a ".po 10" command at the beginning of each file but you see no point in 1) creating a file "/tmp/po10" or 2) editing the documents when the next time you run them you'll only have to take the ".po 10" out again; this is done with for i in {the_documents} do nroff {options} - $i <<EOF .po 10 EOF done {your_favorite_redirection}& Unfortunately, the V7 Bourne shell, the System III Bourne shell, and the System V Bourne shell lose on this; you either have to put the ".po 10" into a file or run the job in the foreground. Guy Harris {seismo,mcnc,we13,brl-bmd,allegra}!rlgvax!guy