Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!helios!bcm!dimacs.rutgers.edu!seismo!uunet!rbj From: rbj@uunet.UU.NET (Root Boy Jim) Newsgroups: comp.unix.internals Subject: Re: dup2 Message-ID: <122697@uunet.UU.NET> Date: 15 Feb 91 04:16:42 GMT References: <122478@uunet.UU.NET> Organization: UUNET Communications Services, Falls Church, VA Lines: 121 richard@locus.com (Richard M. Mathews) writes: ? rbj@uunet.UU.NET (Root Boy Jim) writes: ? >richard@locus.com (Richard M. Mathews) writes: ? >>I have not yet seen a correct version of code for dup2() posted. The ? >>versions posted by Paul Falsted, Doug Gwyn, and Root Boy Jim all fail ? >>the following test case because they close "fd2" too soon: ? >I suppose it depends on your interpretation. And my interpretation was from the manual page. Remember, I am not writing Posix library code, or a Gwynix emulation package, but something I can plug into a piece of code that I'm trying to compile on a system that may not have dup2. ? >If you try dup2(-1,fileno(stdout)) ? >and end up with nowhere to print to, have you not made a copy of your ? >input file descriptor? ? ? By your argument, dup2(-1,fd) should be ? equivalent to close(fd) and should return success if the close succeeds. Sure, why not? I have made a copy of what you gave me. With lemons, I make lemonade. Garbage in, garbage out. And close always succeeds. Or rather, the only way it can fail is by attempting to close something which is not open. In any case, it's closed after the call. ? >What does the shell do with "cmd >&- 2>&1"? ? The above mentioned code returns without touching fd2 if the getf() ? fails on fd1. You're right, it complains. Sorry, not a good example. Or is it? Shouldn't I be able to close stderr that way? The answer is debatable. ? It certainly makes sense that if you return -1 you should ? leave the state of the process unchanged. Interesting notion. I'm not sure it's possible, tho, especially in a system call with complex interactions. ? This clearly is not the way dup2 is documented (it says, "-1 ? is returned if the given file descriptor is invalid"). Regarding dup2, you can't use "clearly" and "documented" in the same sentence. Even the SunOS manual pages, which are more specific than earlier manuals, are rather nebulous about the exact sequence. You deserve what you get. ? >And what is the "meaning" of dup2(1,1)? Anyone who trys to do this ? >probably has a logic error somewhere, regardless of the definition. ? >In any case, I am willing to add "if (new == old) return(new);" to my code. ? ? The above mentioned code has a special case to make sure it treats this ? as a no-op (though it does validate fd1). That is the meaning, but what is the "meaning"? I claim that anyone who calls dup2 with identical arguments has made a logic error. Often, dup2(old,new) is followed by close(old). The end result is the same. Perhaps a better solution would be to simply return an error while leaving the identical descriptor alone. ? >I also claim that I handled errno properly. It is not necessary ? >to preserve the old value of errno if dup2 returns true. ? ? The above mentioned code uses EBADF. Fcntl uses EINVAL. You definitely ? got that errno wrong. Touche. I threw the fcntl part in at the last minute. This has turned into a rather dry discussion on minutiae, which obscures the beauty of the recursive solution. To be honest, I didn't write it, altho I did fix the implementation. Or rather, I did the 20% of the code that solves 80% of the cases. Most people don't even check dup or dup2 because they "always work". At least I made the attempt. The objections you bring up are rather gray areas. To my mind, it's not clear that the standard definition is truly optimal, or that it applies all that often. ? As for preserving errno on success, it certainly ? is true that V7 dup2 did do so Because it was done in the kernel, where you have to go out of your way to alter a variable in user space. And it was done directly, rather than glommed onto something else. ? but it isn't clear that you need to. Exactly. ? The manual says in intro(2) that, "Errno is not cleared on successful ? calls." It doesn't promise that errno isn't changed. I think it is a ? nice extra feature to add those few lines of code to preserve errno. I believe the fcntl errno should be remapped correctly. On preserving the previous errno upon successful return, I disagree. In fact I believe it is actually counterproductive. As more and more "system calls" are replaced with library functions to more general, powerful and modern interfaces, this task gets harder and harder, all for dubious results. And some day someone will complain when errno changes mysteriously. Better to declare open season on it now before people start caring. If you didn't test it immediately, then you didn't really care about it and it's gone forever. However, I thank you for your observations. It's refreshing to know that the man who smugly wrote "We think of everything" didn't. ? Richard M. Mathews Freedom for Lithuania ? richard@locus.com Laisve! ? lcc!richard@seas.ucla.edu ? ...!{uunet|ucla-se|turnkey}!lcc!richard -- [rbj@uunet 1] stty sane unknown mode: sane