捕捉来自另一个 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 中,让我们说跨各种终端共享输入,以便我的线程可以使用它。有什么办法吗?

我搜索了各种选项:

编辑:如果我没记错的话,该程序正在 运行 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 来完成繁重的工作。

它作为一个独立的输入设备存在,允许您做一些事情:

  1. 使用 udev 控制哪些用户帐户可以访问它。

  2. 使用 udev 实际上分离它与终端,这样条形码扫描器就不能用来输入(可能有害的)命令。