Home > Net >  Which attribute in the termios struct generated by cfmakeraw() is responsible for the functionality
Which attribute in the termios struct generated by cfmakeraw() is responsible for the functionality

Time:10-23

I am trying to replicate the standard unblocking setup of ncurses (raw(), noecho()...) with termios.h. I was perusing the tcsetattr() man page to find out about all the flags, and I noticed there is a function called cfmakeraw(). This intrigued me because it looks like a simple solution, but I am confused by several things.

Firstly, though, I will paste here the attribute configuration that cfmakeraw() generates, together with explanations of each attribute:

/* 
cfmakeraw() sets the terminal to something like the "raw" mode of the old Version 7 terminal driver: 
input is available character by character, echoing is disabled, and all special processing of terminal 
input and output characters is disabled. The terminal attributes are set as follows:
*/

termios_p->c_iflag &= ~(    IGNBRK |    /* Ignore BREAK condition on input. */
                            BRKINT |    /* If IGNBRK is set, a BREAK is ignored. If it is not set but 
    BRKINT is set, then a BREAK causes the input and output queues to be flushed, and if the terminal is 
    the controlling terminal of a foreground process group, it will cause a SIGINT to be sent to this 
    foreground process group. When neither IGNBRK nor BRKINT are set, a BREAK reads as a null byte ('\0'), 
    except when PARMRK is set, in which case it reads as the sequence \377 \0 \0. */
                            PARMRK |    /* If IGNPAR is not set, prefix a character with a parity error 
    or framing error with \377 \0. If neither IGNPAR nor PARMRK is set, read a character with a parity 
    error or framing error as \0. */
                            ISTRIP |    /* Strip off eighth bit. */ 
                            INLCR |     /* Translate NL to CR on input. */
                            IGNCR |     /* Ignore carriage return on input. */ 
                            ICRNL |     /* Translate carriage return to newline on input 
    (unless IGNCR is set) */
                            IXON);      /* Enable XON/XOFF flow control on output. */
termios_p->c_oflag &= ~     OPOST;      /* Enable implementation-defined output processing. */
termios_p->c_lflag &= ~(    ECHO |      /* Echo input characters. */
                            ECHONL |    /* If ICANON is also set, echo the NL character even if ECHO 
    is not set. */
                            ICANON |    /* The setting of the ICANON canon flag in c_lflag determines 
    whether the terminal is operating in canonical mode (ICANON set) or noncanonical mode (ICANON unset). 
    By default, ICANON set. In noncanonical mode input is available immediately (without the user having 
    to type a line-delimiter character), no input processing is performed, and line editing is disabled. 
    The settings of MIN (c_cc[VMIN]) and TIME (c_cc[VTIME]) determine the circumstances in which a 
    read(2) completes; there are four distinct cases: */
                            ISIG |      /* When any of the characters INTR, QUIT, SUSP, or DSUSP are 
    received, generate the corresponding signal.  */
                            IEXTEN);    /* Enable implementation-defined input processing. This flag, 
    as well as ICANON must be enabled for the special characters EOL2, LNEXT, REPRINT, WERASE to be 
    interpreted, and for the IUCLC flag to be effective.  */
termios_p->c_cflag &= ~(    CSIZE |     /* Character size mask. Values are CS5, CS6, CS7, or CS8.  */
                            PARENB);    /* Enable parity generation on output and parity checking 
    for input. */
termios_p->c_cflag |=       CS8;        /* (sets character mask I guess) */

Now, the most important question is which of these flags is responsible for the raw() behavior of ncurses, where the input will not generate a terminal signal (e.g. CTRL-C won't abort the program)?

Secondly, I am utterly confused by the lack of cfmakeraw() setting VMIN and VTIME, which seem to be of extreme importance when disabling ICANON (of the mentioned 4 scenarios, the VMIN=0, VTIME=0 appears to be the most useful.)

Up until now I have only used ~(ECHO | ICANON) and x.c_cc[VMIN]=0; x.c_cc[VTIME]=0 in my code, but I want to learn how to also disable the signal generation, and how to set all the other settings accordingly (and which need not be set).

Thank you!

CodePudding user response:

Now, the most important question is which of these flags is responsible for the raw() behavior of ncurses, where the input will not generate a terminal signal (e.g. CTRL-C won't abort the program)?

There is much more to raw mode than suppression of signal generation, but the flag that specifically controls whether input such as CTRL-C causes signals to be sent is the c_lflag flag ISIG.

Secondly, I am utterly confused by the lack of cfmakeraw() setting VMIN and VTIME, which seem to be of extreme importance when disabling ICANON

Yes, you should pay attention to c_cc[VMIN] and c_cc[VTIME] when using the terminal driver in non-canonical mode. You need to set these appropriately for your application's needs, which cfmakeraw() has no way to discern.

I want to learn how to also disable the signal generation,

See above.

and how to set all the other settings accordingly (and which need not be set).

All the settings always have values. Most of those in c_cc[] plus a few others are meaningful only when other settings have specific values, but the rest are meaningful all the time. You may or may not need to change them from their initial values and / or set them non-zero, but you do need to ensure that all 50-ish of the regular flags plus the relevant settings in c_cc all are set to the correct values for the terminal behavior you want.

  •  Tags:  
  • c
  • Related