home *** CD-ROM | disk | FTP | other *** search
- From: cbosgd!cbosgd.ATT.COM!mark@ucbvax.berkeley.edu (Mark Horton)
- Date: 28 Oct 86 03:12:38 GMT
- Organization: AT&T Bell Laboratories, Columbus, Oh
-
- The iocntl proposal, as stated in section C.3 of the POSIX book,
- has a bug. For those who don't have the book handy, it defines
- iocntl(fildes, command, mask, argp, argpsize)
- where command specifies the unique name of the control; mask is
- either IO_READ, IO_WRITE, or IO_READ|IO_WRITE; argp is a pointer
- to the argument, and argpsize is the number of bytes in the argument.
-
- It proposes implementation of upward compatibility
- with ioctl with a define such as
- #define ioctl(a, b, c) iocntl(a, b, c, sizeof(c))
- and using a two ident define for b, thus
- #define IO_READ 1
- #define IO_WRITE 2
- #define TERM_MASK ('T'<<8)
- #define SOME_MASK (IO_READ|IO_WRITE),(TERM_MASK | 0)
- ...
- struct foo *ptr = ...
- ioctl(0, SOME_MASK,ptr);
-
- The bug here is that the sizeof is taken on the pointer, not the
- item itself, so it will always be 4 on a typical 32 bit machine.
-
- One obvious fix might change the spec to read
- #define ioctl(a, b, c) iocntl(a, b, c, sizeof(*c))
- This might work for many cases. But there are two cases for
- which it fails:
-
- (1) ioctls where the object pointed to is an array. In particular
- if the argument is a character string, as in SVr3's I_PUSH ioctl
- to push a streams module, this won't work.
- (2) ioctls where the argument value itself, rather than what's at
- the end of a pointer, is passed. System V does this a lot;
- see, for example, TCSBRK, TCXONC, and TCFLSH.
-
- One possible solution to this problem would be to rearrange the
- order of the arguments to iocntl. If it becomes
-
- iocntl(fildes, command, mask, argpsize, argp)
-
- then a trick similar to the one used in 4.2BSD becomes possible:
-
- #define ioctl iocntl
- #define IO_READ 1
- #define IO_WRITE 2
- #define TERM_MASK ('T'<<8)
- #define SOME_MASK (IO_READ|IO_WRITE),(TERM_MASK | 0),sizeof (struct foo)
- ...
- struct foo *ptr = ...
- ioctl(0, SOME_MASK, ptr);
-
- Another possibility is similar, but closer to what 4.2 does. We
- define iocntl as a function that takes three parameters, just like
- ioctl, but the second parameter is a long, and we get
-
- iocntl(fildes, (long) command, argp)
-
- #define ioctl iocntl
- #define IO_READ (1<<14)
- #define IO_WRITE (2<<14)
- #define TERM_MASK ('T'<<24)
- #define SOME_MASK (long) (IO_READ|IO_WRITE)|(TERM_MASK | 0)|sizeof (struct foo)
- ...
- struct foo *ptr = ...
- ioctl(0, SOME_MASK, ptr);
-
- As I understand it, the only reason for playing these games, instead of
- just doing what 4.2 did and leaving it called ioctl, is that ioctl is
- defined to take an int as the 2nd parameter, and this method has to pass
- a long. It works on a 32 bit machine, but not on a 16 bit CPU such as
- an 80286 (unless you implement "int" as 32 bits.) Am I missing something?
-
- These comments apply to termcntl as well as iocntl.
-
- By the way, if this proposal is going to be used, please let's change
- the name from iocntl to something that doesn't *sound* the same as
- ioctl. Otherwise there will be lots of confusion.
-
- Mark
-
- Volume-Number: Volume 8, Number 9
-
-