Như đã nêu, bạn có thể sử dụng sigaction
để bẫy ctrl-c hoặc select
để bẫy bất kỳ đầu vào chuẩn nào.
Tuy nhiên, lưu ý rằng với phương pháp thứ hai, bạn cũng cần đặt TTY để nó ở chế độ ký tự tại một thời điểm thay vì chế độ dòng tại một thời điểm. Cái sau là mặc định - nếu bạn nhập một dòng văn bản, nó sẽ không được gửi đến stdin của chương trình đang chạy cho đến khi bạn nhấn enter.
Bạn cần sử dụng tcsetattr()
chức năng để tắt chế độ ICANON và có thể tắt cả ECHO. Từ bộ nhớ, bạn cũng phải đặt thiết bị đầu cuối trở lại chế độ ICANON khi chương trình thoát ra!
Chỉ để hoàn thiện, đây là một số mã tôi vừa gõ lên (nb: không kiểm tra lỗi!) Để thiết lập Unix TTY và mô phỏng các <conio.h>
chức năng DOS kbhit()
và getch()
:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <termios.h>
struct termios orig_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
int main(int argc, char *argv[])
{
set_conio_terminal_mode();
while (!kbhit()) {
}
(void)getch();
}