在我的应用程序中使用 gpm 作为鼠标输入从 mc (午夜指挥官)开始

在我的应用程序中使用 gpm 作为鼠标输入从 mc (午夜指挥官)开始

我使用 libgpm 来读取控制台应用程序中的鼠标事件。如果直接从 shell 启动它就可以正常工作。如果从 mc(午夜指挥官)启动,它不会接收任何鼠标事件。

问题与 mc 为我的进程创建的伪终端有关。我可以通过强制 gpm 使用作为第二个参数传递给 Gpm_Open 的指定控制台屏幕(而不是 0 - auto?)来半解决这个问题。

int Gpm_Open(Gpm_Connect*,int);

有什么方法可以知道在伪 tty(由 mc 创建)上运行时应该使用哪个虚拟控制台屏幕?我考虑过使用活动控制台,但它可能不是我的应用程序运行的控制台。可能遍历进程树并检查它的 TTY 是否是真正的控制台可以工作,但我不知道如何获取给定 pid 的 tty(name) ,我担心我需要提升权限。

或者希望有更简单的解决方法吗?

编辑:我刚刚注意到,从 mc 但通过 sudo (使用命令行)启动我的进程,而不强制 gpm 使用特定的 vc 屏幕 - 简单有效!

答案1

我设法创建一个简单的启动脚本,执行它ps f是为了获取进程树。它给了我很好的输出,告诉我我需要的一切:

PID TTY      STAT   TIME COMMAND
281 tty1     Ss     0:00 -bash
383 tty1     S+     0:00  \_ mc
385 pts/0    Ss     0:00      \_ bash -rcfile .bashrc
408 pts/0    R+     0:00          \_ ps f

从最后一行解析出来导致我使用真正的 TTY=tty1 进行处理(当然这是有罪的mc)。所以最后我可以用解析后的 mc 的 tty 号码作为参数来执行我的程序。

另一种选择是通过解析“/proc/PID/stat”文件来检索程序内的 tty 编号,就像ps程序中包含 tty dev id 和父进程 id 一样。但使用脚本让我觉得它不太依赖于操作系统。下面的示例“/proc/PID/stat”:

383 (mc) R 281 383 281 1025 383 ...
            |            |_ TTY:  test major bits for type and minor for id
            |______________ PPID: use to traverse tree 

所以最后我想出了这段代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <gpm.h>

static int find_tty()
{
    char buf[256];
    char* ptr;
    FILE* f;
    int r;
    char stat;
    int ppid,pgrp,sess,tty;

    int pid = getpid();

    while (pid>0)
    {
        sprintf(buf,"/proc/%d/stat",pid);
        f = fopen(buf,"r");
        if (!f)
            return 0;
        r = fread(buf,1,255,f);
        fclose(f);
        if (r<=0)
            return 0;
        buf[r] = 0;
        ptr = strchr(buf,')');
        if (!ptr || !ptr[1])
            return 0;
        r = sscanf(ptr+2,"%c %d %d %d %d", &stat,&ppid,&pgrp,&sess,&tty);
        if (r!=5)
            return 0;
        if ( (tty&~63) == 1024 && (tty&63) )
            return tty&63;
        pid = ppid;
    }
    return 0;
}

int main(int argc, char* argv[])
{
    Gpm_Connect gpm_connect;
    // ...

    int gpm = Gpm_Open(&gpm_connect,find_tty()/*0*/);
    // ...
}

相关内容