捕捉来自另一个 shell 的输入
Catch input from another shell
我目前有一个 C/C++ 程序,它使用条形码扫描器作为键盘,捕捉输入并用它做一些事情。这是代码的相关部分:
int get_InStream() {
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
}
void nonblock(int state) {
struct termios ttystate;
tcgetattr(STDIN_FILENO, &ttystate);
if (state == 1) {
// ~ICANON: turn off canonical mode
// ~ECHO: not display character
//~ ttystate.c_lflag &= ~ECHO; // (ICANON & ECHO);
tcgetattr( 0, &ttystate); /* read curr. setting */
original_mode = ttystate; /* remember these */
ttystate.c_lflag &= ~ICANON; /* no buffering */
//~ ttystate.c_lflag &= ~ECHO; /* no echo either */
tcsetattr( 0 , TCSANOW, &ttystate); /* install settings */
//minimum of number input read.
ttystate.c_cc[VMIN] = 1;
}
else if (state == 0) {
//~ // turn on canonical mode
//~ ttystate.c_lflag |= ECHO;
tcsetattr(0, TCSANOW, &original_mode); /* undo -icanon, -echo */
}
// set the terminal attributes.
tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}
bool keyState(int key) { // Uses ASCII table
bool pressed = false;
int i = get_InStream(); // Allows to read from terminal
if (i != 0) {
char c = fgetc(stdin);
if (c == (char) key) {
pressed = true;
} else {
pressed = false;
char string_key = c;
pthread_mutex_lock(&id_mutex);
// Append character to content buffer
strcat(content, string_key);
pthread_mutex_unlock(&id_mutex);
}
}
return pressed;
}
void* get_inputContent(void* arg) {
pthread_detach(pthread_self());
nonblock(1);
while (1) {
// if this returns True, content contains data
if (keyState(0x0A)) { // 0x0A in ASCII table corresponds to New Line
pthread_mutex_lock(&id_mutex);
printf("Read this %d characters through barcode scanner: %s\n", strlen(content), content); //DEBUG
// doSomething()
strcpy(content, "[=11=]"); // empty out content
pthread_mutex_unlock(&id_mutex);
}
}
nonblock(0);
pthread_exit(NULL);
}
现在这作为一个独立于主程序的线程工作得很好,但是如果我在主程序 运行ning 时打开另一个终端并且我将焦点放在新的终端上,条形码输入是没有被线抓住。
所以我想,无论是在 C/C++ 还是在 Bash 中,让我们说跨各种终端共享输入,以便我的线程可以使用它。有什么办法吗?
我搜索了各种选项:
- 要在
select()
中使用的另一个描述符
- 在 Bash
中使用 export
- 写入共享文件
但我对其中任何一个都不太确定。有什么建议吗?
编辑:如果我没记错的话,该程序正在 运行 Raspberry Pi OS 之前 Raspbian
这里是 XY problem 的情况。你的问题'X'是
How can I access the keyboard device as which the barcode scanner presents itself to the system regardless of the current state of the system?
但是你认为,通过解决问题'Y'
How can I keygrab input directed to a different terminal?
问题 Y 很难,因为它涉及安全问题。问题 X 很简单,但其解决方案取决于所使用的操作系统。
您提到了 bash 和 POSIX 样式文件描述符。所以我猜你喜欢 Linux。这样一来,问题就容易解决了!每个输入设备都将自己呈现为 /dev/input/event<X>
下的 evdev
设备。您的条形码扫描器也会显示在那里。
您可以自己实施 evdev
协议。或者只使用 libinput 来完成繁重的工作。
它作为一个独立的输入设备存在,允许您做一些事情:
使用 udev 控制哪些用户帐户可以访问它。
使用 udev 实际上分离它与终端,这样条形码扫描器就不能用来输入(可能有害的)命令。
我目前有一个 C/C++ 程序,它使用条形码扫描器作为键盘,捕捉输入并用它做一些事情。这是代码的相关部分:
int get_InStream() {
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
}
void nonblock(int state) {
struct termios ttystate;
tcgetattr(STDIN_FILENO, &ttystate);
if (state == 1) {
// ~ICANON: turn off canonical mode
// ~ECHO: not display character
//~ ttystate.c_lflag &= ~ECHO; // (ICANON & ECHO);
tcgetattr( 0, &ttystate); /* read curr. setting */
original_mode = ttystate; /* remember these */
ttystate.c_lflag &= ~ICANON; /* no buffering */
//~ ttystate.c_lflag &= ~ECHO; /* no echo either */
tcsetattr( 0 , TCSANOW, &ttystate); /* install settings */
//minimum of number input read.
ttystate.c_cc[VMIN] = 1;
}
else if (state == 0) {
//~ // turn on canonical mode
//~ ttystate.c_lflag |= ECHO;
tcsetattr(0, TCSANOW, &original_mode); /* undo -icanon, -echo */
}
// set the terminal attributes.
tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}
bool keyState(int key) { // Uses ASCII table
bool pressed = false;
int i = get_InStream(); // Allows to read from terminal
if (i != 0) {
char c = fgetc(stdin);
if (c == (char) key) {
pressed = true;
} else {
pressed = false;
char string_key = c;
pthread_mutex_lock(&id_mutex);
// Append character to content buffer
strcat(content, string_key);
pthread_mutex_unlock(&id_mutex);
}
}
return pressed;
}
void* get_inputContent(void* arg) {
pthread_detach(pthread_self());
nonblock(1);
while (1) {
// if this returns True, content contains data
if (keyState(0x0A)) { // 0x0A in ASCII table corresponds to New Line
pthread_mutex_lock(&id_mutex);
printf("Read this %d characters through barcode scanner: %s\n", strlen(content), content); //DEBUG
// doSomething()
strcpy(content, "[=11=]"); // empty out content
pthread_mutex_unlock(&id_mutex);
}
}
nonblock(0);
pthread_exit(NULL);
}
现在这作为一个独立于主程序的线程工作得很好,但是如果我在主程序 运行ning 时打开另一个终端并且我将焦点放在新的终端上,条形码输入是没有被线抓住。 所以我想,无论是在 C/C++ 还是在 Bash 中,让我们说跨各种终端共享输入,以便我的线程可以使用它。有什么办法吗?
我搜索了各种选项:
- 要在
select()
中使用的另一个描述符
- 在 Bash 中使用
- 写入共享文件 但我对其中任何一个都不太确定。有什么建议吗?
export
编辑:如果我没记错的话,该程序正在 运行 Raspberry Pi OS 之前 Raspbian
这里是 XY problem 的情况。你的问题'X'是
How can I access the keyboard device as which the barcode scanner presents itself to the system regardless of the current state of the system?
但是你认为,通过解决问题'Y'
How can I keygrab input directed to a different terminal?
问题 Y 很难,因为它涉及安全问题。问题 X 很简单,但其解决方案取决于所使用的操作系统。
您提到了 bash 和 POSIX 样式文件描述符。所以我猜你喜欢 Linux。这样一来,问题就容易解决了!每个输入设备都将自己呈现为 /dev/input/event<X>
下的 evdev
设备。您的条形码扫描器也会显示在那里。
您可以自己实施 evdev
协议。或者只使用 libinput 来完成繁重的工作。
它作为一个独立的输入设备存在,允许您做一些事情:
使用 udev 控制哪些用户帐户可以访问它。
使用 udev 实际上分离它与终端,这样条形码扫描器就不能用来输入(可能有害的)命令。