Path: utzoo!attcan!uunet!seismo!sundc!pitstop!sun!gorodish!guy From: guy@gorodish.Sun.COM (Guy Harris) Newsgroups: comp.unix.questions Subject: Re: fcntl() versus ioctl() Keywords: FNDELAY Message-ID: <68560@sun.uucp> Date: 15 Sep 88 18:33:29 GMT References: <1380@solo7.cs.vu.nl> <7034@ki4pv.uucp> Sender: news@sun.uucp Lines: 68 > Well, this is a good question. Let's examine it. First of all, note > that fcntl(2) operates on file descriptors (just like ioctl(2) does). Well, no. "fcntl()" and "ioctl()" both take file descriptors as arguments. However, they don't necessarily "operate on" those descriptors, in the sense that they may fetch information from, or change the state of, objects to which those descriptors refer, rather than the descriptors themselves. "fcntl()" acts either on the file descriptor or on the file table entry to which the descriptor refers (later UNIX releases also added other functions, such as record locking, which don't fit this model, but you can argue that they should have added a new call for those; 4.2BSD also misimplemented no-delay mode as an "ioctl()", and had the "fcntl()" basically do the "ioctl()" for you, but the original implementation of "fcntl()" in S3 got this right). "ioctl()" generally acts on the object (file, device) to which the file table entry referred to by the file descriptor refers (earlier UNIX releases stuck functions such as FIOCLEX that operate on the descriptor and leave everything below it alone, but you can argue that adding "fcntl()" for this function was the right idea). > In many environments, it even offers several of the same sorts of > controls. The only such control I can think of is FIOCLEX, and you can argue that, in a pure sense, this shouldn't have been an "ioctl()" but should only have been an "fcntl()". > I don't see any moral difference between fcntl(2) and ioctl(2), myself. See above. > Thus, if ioctl() might cause a parent to suffer, fcntl() may be expected > to have a similar hazard. In general, both "fcntl()" and "ioctl()" *can* act on objects that are shared by various file descriptors, so they *might* cause objects shared with a parent to be affected. However, while (with the exception of FIOCLEX, which could be argued shouldn't have been an "ioctl()") "ioctl()" acts *only* on shared objects, "fcntl()" *can* act on non-shared objects (the file descriptor itself). Given that, the no-delay flag could have been a flag associated with the file descriptor entry, in which case the parent will *not* be affected if a process sets no-delay mode. The argument you gave indicates that it is certainly *possible* for "fcntl()"s setting no-delay mode to affect descriptors in the parent, but it basically amounts to "this is how it was implemented"; it certainly was implemented that way, but it didn't necessarily *have* to be implemented that way. It could conceivably have been implemented as a per-descriptor flag (similar to the "close-on-exec" flag). > Now, consider the effect proposed by maart@cs.vu.nl above: that the > parent's fd should not be affected by a child's action. Mainly, the > "stty" command (remember: commands are run as children of shells) no > longer works. It is no longer practical to change your tty modes. Well, no. He specifically referred to "fcntl()"s done by the child, not "ioctl()"s done by the child; there already exists a precedent for "fcntl()"s that don't affect the parent (F_SETFD), and in fact there even exists a precedent for "ioctl()"s that don't affect the parent (FIOCLEX). Implementing no-delay mode as a per-descriptor flag would hardly imply that "ioctl()"s such as the terminal "ioctl()"s would be obliged not to affect parents of the process doing the "ioctl()".