0

I am searching documentation for ioctl() and I found something in POSIX standard: https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/

But it looks like this is only a fraction...

For example I can't find any information afout this TIOCGWINSZ that obviously people are using: Getting terminal width in C?

In my C programs only include this header sys/ioctl.h and I am guessing that on my Debian machine this is the file that is actually included:

┌───┐
│ $ │ ziga > ziga--workstation > usr
└─┬─┘
  └─> cat /usr/include/linux/ioctl.h 
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_IOCTL_H
#define _LINUX_IOCTL_H

#include <asm/ioctl.h>

Now I try to find the included header asm/ioctl.h and again I am only guessing that this is it:

┌───┐
│ $ │ ziga > ziga--workstation > usr
└─┬─┘
  └─> cat /usr/include/asm-generic/ioctl.h 
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_GENERIC_IOCTL_H
#define _ASM_GENERIC_IOCTL_H

/* ioctl command encoding: 32 bits total, command in lower 16 bits,
 * size of the parameter structure in the lower 14 bits of the
 * upper 16 bits.
 * Encoding the size of the parameter structure in the ioctl request
 * is useful for catching programs compiled with old versions
 * and to avoid overwriting user space outside the user buffer area.
 * The highest 2 bits are reserved for indicating the ``access mode''.
 * NOTE: This limits the max parameter size to 16kB -1 !
 */

/*
 * The following is for compatibility across the various Linux
 * platforms.  The generic ioctl numbering scheme doesn't really enforce
 * a type field.  De facto, however, the top 8 bits of the lower 16
 * bits are indeed used as a type field, so we might just as well make
 * this explicit here.  Please be sure to use the decoding macros
 * below from now on.
 */
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS   8

/*
 * Let any architecture override either of the following before
 * including this file.
 */

#ifndef _IOC_SIZEBITS
# define _IOC_SIZEBITS  14
#endif

#ifndef _IOC_DIRBITS
# define _IOC_DIRBITS   2
#endif

#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
#define _IOC_TYPEMASK   ((1 << _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK   ((1 << _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK    ((1 << _IOC_DIRBITS)-1)

#define _IOC_NRSHIFT    0
#define _IOC_TYPESHIFT  (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT  (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT   (_IOC_SIZESHIFT+_IOC_SIZEBITS)

/*
 * Direction bits, which any architecture can choose to override
 * before including this file.
 *
 * NOTE: _IOC_WRITE means userland is writing and kernel is
 * reading. _IOC_READ means userland is reading and kernel is writing.
 */

#ifndef _IOC_NONE
# define _IOC_NONE  0U
#endif

#ifndef _IOC_WRITE
# define _IOC_WRITE 1U
#endif

#ifndef _IOC_READ
# define _IOC_READ  2U
#endif

#define _IOC(dir,type,nr,size) \
    (((dir)  << _IOC_DIRSHIFT) | \
     ((type) << _IOC_TYPESHIFT) | \
     ((nr)   << _IOC_NRSHIFT) | \
     ((size) << _IOC_SIZESHIFT))

#define _IOC_TYPECHECK(t) (sizeof(t))

/*
 * Used to create numbers.
 *
 * NOTE: _IOW means userland is writing and kernel is reading. _IOR
 * means userland is reading and kernel is writing.
 */
#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr)        (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr)       (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr)     (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr)       (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

/* ...and for the drivers/sound files... */

#define IOC_IN      (_IOC_WRITE << _IOC_DIRSHIFT)
#define IOC_OUT     (_IOC_READ << _IOC_DIRSHIFT)
#define IOC_INOUT   ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#define IOCSIZE_MASK    (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT   (_IOC_SIZESHIFT)

#endif /* _ASM_GENERIC_IOCTL_H */


#endif /* _LINUX_IOCTL_H */
 

This file does not include anything! It is a dead end and still no slightest trace of TIOCGWINSZ...

What is happening? I am clueless...

Is POSIX programming becomming a lost art? Where is the documentation? How can anyone expect programmer novices to learn anything if standards are so dissorganized...

To me it seems everybody just likes coding as a hobby... even if their code is useless to the world without documentation. I get it that some lone wolves can do this, but I could never imagine something like this from POSIX standard...


As suggested I also tried man page and nothing: enter image description here

71GA
  • 1,132
  • 6
  • 36
  • 69
  • 3
    How about the [man page](https://man7.org/linux/man-pages/man4/tty_ioctl.4.html)? – Eugene Sh. Apr 14 '21 at 19:48
  • ioctl is super generic. It can do anything. Documentation has to be about specific uses of it. – Zan Lynx Apr 14 '21 at 19:51
  • It's not coming from the POSIX standard. It's Linux. `man 2 ioctl_tty` – Emanuel P Apr 14 '21 at 19:54
  • @EugeneSh. I tried and updated the answer accordingly. No success... @EmanuelP I also tried searching in the official Linux kernel documentation: https://www.kernel.org/doc/html/latest/index.html And `TIOCGWINSZ` can't be found. This is a serious problem... – 71GA Apr 14 '21 at 19:54
  • 1
    I gave you the exact link to the man page. On your local machine it can be either `man ioctl_tty` or `man tty_ioctl`. – Eugene Sh. Apr 14 '21 at 19:59
  • @EmanuelP ioctl is not just Linux. It's in the FreeBSD man page and also states, "The ioctl() function appeared in Version 7 AT&T UNIX." – Rob Apr 14 '21 at 19:59
  • @EmanuelP I found it in the `man tty_ioctl` now I want to know the reason why this is not documented anywhere else? And how could a beginner know where to search for? I mean... as usually everybody first thinks to check in the standard... And even if someone would look in the man page he will first check the `manm ioctl` which does not point to `man tty_ioctl` at the end. Why? This is so dissorganized... – 71GA Apr 14 '21 at 20:01
  • 4
    @71GA Because this isn't part of the POSIX standard, but system specific. `ioctl` is in POSIX, but not every individual control is. Per the man page: "Use of ioctl makes for nonportable programs. Use the POSIX interface described in termios(3) whenever possible." – Emanuel P Apr 14 '21 at 20:04
  • 2
    ioctl is device-specific. A device(driver) *may* implement it, defining its own *distinct* constants and semantics. (for example: a harddisk-driver could use it to change the RPM, and a tty-driver to change the number of (stop)bits) – wildplasser Apr 14 '21 at 20:04
  • 1
    On my machine I run `man ioctl`, and in the "CONFORMING TO" section it says "No single standard. ... See ioctl_list(2) for a list of many of the known ioctl() calls." Running `man ioctl_list` gives me the list, which includes TIOCGWINSZ which you were looking for. – Kevin Apr 14 '21 at 20:07
  • @71GA Disorganized it certainly is. There's no link in `man ioctl` to `ioctl_tty` because the first is part of the POSIX manual, and the latter of the Linux manual. POSIX is an attempt at standardization by defining the union of existing UNIX systems. This has certainly never been a top-down organization. – Emanuel P Apr 14 '21 at 20:07
  • Ok, thank you. @wildplasser In the standard I can realy read that *"The ioctl() function shall perform a variety of control functions on STREAMS devices."*. Is there any way to list all the man pages refering to `ioctl`? – 71GA Apr 14 '21 at 20:08
  • @Kevin This is very useful! – 71GA Apr 14 '21 at 20:09
  • 1
    `man -k ioctl` , for a start. – wildplasser Apr 14 '21 at 20:11
  • So when I am searching for some documentation I start with the POSIX standard and if I can't find it there, maybe man pages are the next step to go to. To me it is suprising that the next step is not "Linux kernel documentation". Could anyone elaborate on what is the **difference** between "man" pages and "Linux kernel documentation" philosophy? – 71GA Apr 14 '21 at 20:17
  • A beginner should read "Advanced Programming In The UNIX Environment" – Zan Lynx Apr 14 '21 at 21:24
  • @ZanLynx Book looks nice. At a first glance it looks like it tackles only "procedural" programming. Do you know of any good book that teaches "event driven" programming for Unix/Linux as well? Because this is what I really want to read about. – 71GA Apr 14 '21 at 21:52
  • A very useful command for programmers is `man -s2 -wK TIOCGWINSZ`. It will search all `man` pages for a string `TIOCGWINSZ`. – 71GA Apr 15 '21 at 17:07

0 Answers0