{
tcflag_t c_iflag; /*input mode flags*/
tcflag_t c_oflag; /*output mode flags*/
tcflag_t c_cflag; /*control mode flags*/
tcflag_t c_lflag; /*local mode flags*/
cc_t c_cc[NCCS]; /*control charters*/
speed_t c_ispeed; /*input speed*/
speed_t c_ospeed; /*output speed*/
};
각 멤버는 터미널 동작을 세밀하게 제어하기 위해 사용됩니다.
c_iflag
(Input Flags):
c_oflag
(Output Flags):
c_cflag
(Control Flags):
c_lflag
(Local Flags):
c_line
:
c_cc
(Control Characters):
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#define ASK "Do you want another transaction"
#define TRIES 3 // 최대 시도 횟수
#define SLEEPTIME 2 // 각 시도 간 대기 시간
#define BEEP putchar('\a') // 사용자에게 알림
int get_response(char *question, int maxtries) {
int input;
printf("mode setting starts !\n"); // 모드 변경 메시지 출력
fflush(stdout);
// 터미널 모드 변경
tty_mode(0); // 현재 모드 저장
set_cr_noecho_mode(); // 모드 변경: -icanon, echo
set_nodelay_mode(); // 모드 변경: noinput = EOF
printf("%s (y/n)?\n", question);
fflush(stdout);
while(1) {
sleep(SLEEPTIME); // wait a bit
input = tolower(get_ok_char()); // get next char
if(input == 'y') {
printf("yes\n");
break; // 변경 완료 메시지를 출력하고 종료
}
if(input == 'n') {
printf("no\n");
break; // 변경 완료 메시지를 출력하고 종료
}
if(maxtries-- == 0) {
printf("time out\n");
break; // 변경 완료 메시지를 출력하고 종료
}
BEEP;
}
// 입력 모드 변경 복원
tty_mode(1); // 원래 모드로 복원
return (input == 'y') ? 0 : 1;
}
int get_ok_char() {
int c;
while((c = getchar()) != EOF && strchr("yYnN",c) == NULL);
return c;
}
void tty_mode(int how) {
static struct termios original_mode;
static int original_flags;
if (how == 0) {
tcgetattr(0, &original_mode);
original_flags = fcntl(0, F_GETFL);
} else {
tcsetattr(0, TCSANOW, &original_mode);
fcntl(0, F_SETFL, original_flags);
}
}
void set_nodelay_mode() {
int termflags;
termflags = fcntl(0, F_GETFL); // 현재 설정 읽기
termflags |= O_NDELAY; // nodelay 비트 설정
fcntl(0, F_SETFL, termflags); // 설정 적용
printf("Nodelay mode is set\n"); // 모드 변경 완료 메시지 출력
fflush(stdout);
}
void set_cr_noecho_mode() {
struct termios ttystate;
tcgetattr(0, &ttystate); // 현재 설정 읽기
ttystate.c_lflag &= ~ICANON; // 버퍼링 비활성화
ttystate.c_lflag &= ~ECHO; // 에코 비활성화
ttystate.c_cc[VMIN] = 1; // 한 번에 1 문자씩 읽기
tcsetattr(0, TCSANOW, &ttystate); // 설정 적용
printf("CR-NoEcho mode is set\n"); // 모드 변경 완료 메시지 출력
fflush(stdout);
}
int main() {
int response;
response = get_response(ASK, TRIES);
printf("mode setting is finish !\n"); // 모드 변경 완료 메시지 출력
return response;
}
터미널에서 사용자에게 여러 번의 'y/n' 질문을 하고 사용자의 응답을 처리하는 프로그램
int get_response(char *question, int maxtries)
: 이 함수는 사용자에게 질문을 묻고, 사용자의 입력을 받아서 처리합니다. 입력을 받기 전에 터미널 모드를 변경하여 라인 버퍼링을 해제하고 입력을 에코하지 않도록 설정합니다. 사용자의 입력에 따라 "yes", "no", 또는 "time out" 메시지를 출력하고 해당 결과를 반환합니다.
int get_ok_char()
: 이 함수는 사용자로부터 입력을 받아서 대기 상태에 있는 입력을 처리합니다. 사용자가 "y" 또는 "n"을 입력할 때까지 대기하며, 대소문자를 구분하지 않도록 변환하여 반환합니다.
void tty_mode(int how)
: 이 함수는 현재 터미널 모드를 저장하고, 필요한 경우 모드를 복원합니다. "how" 인수가 0이면 현재 모드를 저장하고, 1이면 저장한 모드를 복원합니다.
void set_nodelay_mode()
: 이 함수는 터미널 모드를 변경하여 입력 대기 시간 없이 바로 반환하도록 설정합니다. 모드가 변경되면 "Nodelay mode is set" 메시지를 출력합니다.
void set_cr_noecho_mode()
: 이 함수는 터미널 모드를 변경하여 라인 버퍼링을 비활성화하고 입력 에코를 비활성화합니다. 한 번에 한 문자씩 입력을 받도록 설정합니다. 모드가 변경되면 "CR-NoEcho mode is set" 메시지를 출력합니다.
int main()
: 먼저 get_response
함수를 호출하여 사용자와의 상호작용을 수행하고, 모드 변경이 완료된 후 "mode setting is finish !" 메시지를 출력합니다. 마지막으로 get_response
함수의 반환값을 반환합니다.
echo 모드를 해제하여 사용자가 입력할 때는 보이진 않지만,
입력 후에는 yes/no/time out을 print하게 했다.
TCSANOW: 즉시 적용
TCSADRAIN: 출력 종료 후 적용
TCSAFLUSH: 출력 종료 후 적용. 변화 발생시 생긴 데이터를 버림