Existe um caminho mais geral. Em todas as plataformas com terminais virtuais, incluindo linux e BSD, o Xserver mantém um fd aberto para o terminal em que está sendo executado. No linux, continua sendo uma boa solução verificar o terminal de controle do processo X para distinguir entre múltiplos processos X (use o sétimo campo de /proc/<..>/stat
). Mais geralmente, olhe através da lista de fds abertos do processo X, e só precisa de alguma filtragem simples para sair do terminal onde o Xserver está rodando. (Infelizmente, obter a lista de fds abertos é novamente dependente da plataforma ...) Para plataformas sysctl
como o BSD, o código será semelhante a este, além de um tratamento de erros:
int ttyByOpenFds(int curPid) {
int ctl[4] = { CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC, curPid };
size_t sizeGuess = 50*sizeof(kinfo_file);
char* buf = malloc(sizeGuess);
int rv = sysctl(ctl, 4, buf, &sizeGuess, 0, 0);
if (rv < 0 && errno == ESRCH) return 0;
else if (rv < 0 && errno == ENOMEM) { /* try again */ }
else if (rv < 0) throw SystemException("unexpected error getting args", errno);
char* position = buf;
while (position < buf + sizeGuess) {
kinfo_file* kfp = reinterpret_cast<kinfo_file*>(position);
position += kfp->kf_structsize;
if (kfp->kf_type != KF_TYPE_VNODE) continue;
if (kfp->kf_vnode_type != KF_VTYPE_VCHR) continue;
if (kfp->kf_fd < 0) continue;
char* name = devname(kfp->kf_un.kf_file.kf_file_rdev, S_IFCHR);
if (!name) continue;
unsigned int ttynum = 0;
if (sscanf(name, "ttyv%u", &ttynum) != 1) continue;
if (ttynum < 8 && kfp->kf_fd <= 2) continue; // stderr going to a console
return ttynum;
}
return 0;
}