Document directory
- Password program using the termios Structure
The termios structure is a standard interface defined in the POSIX specification. It is similar to the termio interface in system v. It sets the value in the termios data structure and uses a small value.
Group function calls allow you to control terminal interfaces.
The terminal values can be adjusted to be divided into the following groups according to different modes:
1. input mode
2. Output Mode
3. Control Mode
4. Local Mode
5. Special Control Mode
A typical definition of the smallest termios structure is as follows:
Struct termios
{
Tcflag_t c_iflag;
Tcflag_t c_oflag;
Tcflag_t c_cflag;
Tcflag_t c_lflag;
Cc_t c_cc [NCCs];
};
The structure member name corresponds to the five parameter types listed above.
You can call the tcgetattr function to initialize the termios structure corresponding to a terminal. The prototype of this function is as follows:
#include<termios.h>int tcgetattr(int fd, struct termios *termios_p);
This function call writes the value of the current terminal interface variable to the structure pointed to by the termios_p parameter. If these values are modified, you can call the tcsetattr function to reconfigure them.
Terminal interface.
#include<termios.h>int tcsetattr(int fd , int actions , const struct termios *termios_h);
The actions parameter controls the modification methods. There are three ways to modify the parameters, as shown below.
1. tcsanow: Modify the value immediately
2. tcsadrain: after the current output is complete, modify the value.
3. tcsaflush: after the current output is complete, modify the value, but discard any currently available input that has not been returned from the read call.
Next we will introduce the five modes respectively.
1. input mode
The input mode controls how the input data is processed before being passed to the program. You can control the c_iflag members in the termios structure. All logos are defined
Macro, and can be combined by bit or.
The macros that can be used for c_iflag members are shown in the following figure:
Brkint: an interruption occurs when a termination state is detected in the input line.
Tgnbrk: Ignore the termination status in the input line.
Tcrnl: converts the received carriage return to a new line.
Tgncr: ignore accepted new line characters.
Inlcr: converts a new line to a carriage return.
Ignpar: Ignore characters with incorrect parity check.
Inpck: performs a parity check on the received characters.
Parmrk: Mark the parity check error.
Istrip: splits all received characters into seven bits.
Ixoff: Enable software flow control for input.
Ixon: enables software flow control for the output.
If neither the brkint nor the tgnbrk flag is set, the termination status in the input line is read as null (0x00) characters.
Iii. Output Mode
The output mode controls the processing method of output characters, that is, how to process the characters sent by the program before being passed to the serial port or screen. The output mode is controlled by setting the c_oflag member ID.
Opsot: Enable the output processing function
Onlcr: converts a linefeed from the output to a carriage return.
Ocrnl: converts a carriage return to a linefeed.
Onocr: Line 3 does not output carriage return characters.
Onlret: Do not output carriage return
Nldly: line feed delay selection
Crdly: Carriage Return Delay
Tabdly: tab latency
...
The output mode is rarely used.
Iv. Control Mode
The control mode controls the hardware features of the terminal and is configured with the c_cflag member ID.
Clocal: Ignore all modem status lines
Cread: Enable character Receiver
Cs5, 6/7, or 8: 5/6/7/8 bits are used for sending or receiving characters.
Cstopb: Use two stop bits for each character
Hupcl: hangs up the modem when it is disabled
Parenb: enables the generation and detection of parity codes.
Parodd: only odd test is used instead of even verification.
Generally, this method is not used. It is easier to directly modify the terminal configuration file to modify hardware features.
5. Local Mode
Using c_lflag members to control certain features of the Terminal
Echo: Enable local ECHO for input characters
Echonl: returns a line break.
Icanon: Enable Standard Input Processing
Isig: Enable Signal
...
Echo and icanon are the most common symbols. The former suppresses the echo (Suppression?) of the typed characters ??), The latter is described as follows:
6. Special control characters
In standard mode and non-standard mode, the c_cc array has different values:
Standard mode:
Veof: EOF character
Veol: EOL character
Verase: erase character
Vintr: intr character
Vkill: Kill character
Vquit: Quit character
Vstart: Start character
Vstop: Stop character
Non-standard mode:
Vintr: intr character
Vmin: min value
Vquit: Quit character
Vsusp: susp character
Vtime: Time Value
Vstart: Start character
Vstop: Stop character
1. Character
Intr: This character enables the Terminal Driver to send a SIGINT signal to the process connected to the terminal.
Quit: This character enables the Terminal Driver to send sigquit signals to processes connected to the terminal.
EOF; this character enables the Terminal Driver to pass all the characters in the input line to the application that is reading the input. if the input is empty, the read operation returns 0, as if the read operation was called at the end of the file.
...
2. Time and Min values
These two values are only used in non-standard mode. They work together to control the reading method of the input, but also to control what will happen when a program tries to associate a file descriptor with a terminal.
Min = 0, time = 0: Read returns immediately. If the characters to be processed are returned, if not, 0 is returned for the read call and no characters are read.
Min = 0, time> 0: A string is processed or returned after 0.1 seconds of time
Min> 0, time = 0: Read waits until Min characters can be read. The returned value is the number of characters. 0 is returned when the end of the file is reached.
Min> 0, time> 0: When the read is called, it will wait to receive a character. enable a character interval timer after receiving the first character and each subsequent character. when there are min characters that can be read or the interval between two characters exceeds the time limit of 0.1 seconds, read returns
By setting min and time values, we can process the input character by character
3. access terminal mode through shell
Stty-A: This command is used to view the settings of the current terminal.
Stty sane: If you accidentally set the terminal mode, you can use this command to restore it. Another recovery method is to save the current stty settings before the settings and read the settings as needed.
Stty-G> save_stty: Save the current settings to the save_atty file.
Stty $ (cat save_stty): Read the save_atty file and restore the original terminal settings.
The third recovery method is to re-create a terminal simulator, view the dead Terminal Process, and kill it.
4. Set Terminal Mode in Command Line Mode
For example, if you want the shell script to read a single character, you need to disable the standard mode and set min to 1 and time to 0:
Stty-icanon min1 time 0
In another example, the echo function is disabled when the password is entered:
Atty-echo
After using this command, execute Atty echo and restore the echo function again.
5. Terminal speed
The termios structure does not contain members and identifiers about the terminal speed, but we can use a set of functions. Note that the input and output are separated and different functions should be used.
# Include <termios. h>
Speed_t cfgetispeed (const struct termios *);
Speed_t cfgetospeed (const struct termios *);
Int cfsetispeed (struct termios *, speed_t speed );
Int cfseospeed (struct termios *, speed_t speed );
These functions only apply to the termios structure. Therefore, you must call tcgetattr () to obtain the termios structure, call one of the preceding functions to set the terminal speed, and call tcsetattr () to make the settings take effect.
The value that can be set by the speed parameter above, of which the following are important:
B0: terminal suspended
B1200: 1200 Port
B2400: 2400 Port
B9600: 9600 Port
B19200: 19200 Potter
B38400: 38400 Potter
6. Other functions
These functions act directly on file descriptors and do not need to read or write the termios structure:
# Include <termios. h>
Int tcdrain (int fd); Keep the caller waiting until all queued output is sent.
Int tcflow (INT, int flowtype); pause or start output again
Int tcflush (int fd, int in_out_selector); empty input, output, or both.
Password program using the termios Structure
#include <termios.h>#include <stdio.h>#include <stdlib.h>#define PASSWORD_LEN 8int main(){ struct termios initialrsettings, newrsettings; char password[PASSWORD_LEN + 1]; tcgetattr(fileno(stdin), &initialrsettings); newrsettings = initialrsettings; newrsettings.c_lflag &= ~ECHO; printf("Enter password: "); if(tcsetattr(fileno(stdin), TCSAFLUSH, &newrsettings) != 0) { fprintf(stderr,"Could not set attributes\n"); } else { fgets(password, PASSWORD_LEN, stdin); tcsetattr(fileno(stdin), TCSANOW, &initialrsettings); fprintf(stdout, "\nYou entered %s\n", password); } exit(0);}
Read every character
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <termios.h>char *menu[] = { "a - add new record", "d - delete record", "q - quit", NULL,};int getchoice(char *greet, char *choices[], FILE *in, FILE *out);int main(){ int choice = 0; FILE *input; FILE *output; struct termios initial_settings, new_settings; if (!isatty(fileno(stdout))) { fprintf(stderr,"You are not a terminal, OK.\n"); } input = fopen("/dev/tty", "r"); output = fopen("/dev/tty", "w"); if(!input || !output) { fprintf(stderr, "Unable to open /dev/tty\n"); exit(1); } tcgetattr(fileno(input),&initial_settings); new_settings = initial_settings; new_settings.c_lflag &= ~ICANON; new_settings.c_lflag &= ~ECHO; new_settings.c_cc[VMIN] = 1; new_settings.c_cc[VTIME] = 0; new_settings.c_lflag &= ~ISIG; if(tcsetattr(fileno(input), TCSANOW, &new_settings) != 0) { fprintf(stderr,"could not set attributes\n"); } do { choice = getchoice("Please select an action", menu, input, output); printf("You have chosen: %c\n", choice); } while (choice != 'q'); tcsetattr(fileno(input),TCSANOW,&initial_settings); exit(0);}int getchoice(char *greet, char *choices[], FILE *in, FILE *out){ int chosen = 0; int selected; char **option; do { fprintf(out, "Choice: %s\n",greet); option = choices; while(*option) { fprintf(out, "%s\n",*option); option++; } do { selected = fgetc(in); } while (selected == '\n' || selected == '\r'); option = choices; while(*option) { if(selected == *option[0]) { chosen = 1; break; } option++; } if(!chosen) { fprintf(out, "Incorrect choice, select again\n"); } } while(!chosen); return selected;}