有一个库(libvte,一个终端仿真库),它使用一对文件描述符作为pty主/从对。我需要能够从库中“窃取”主fd以供我自己使用(为了在非常罕见的情况下实现对ZMODEM的支持,因为我对'net的唯一链接是通过终端)。但是,有一个问题。
您可以告诉libvte您要将文件描述符更改为新文件描述符,但它会尝试关闭它正在使用的主文件,并开始使用新文件描述符。这不起作用,因为当主人关闭时,奴隶就会消失。最初,我认为可以在pty master上使用dup()
,这样当libvte在PTY master上执行close()
时,我仍然可以使用正常运行的fd。这显然是错误的。
我需要找到一种方法:
read()
操作
rz
进程并退出)POSIX系统是否可以执行上述任一操作?或者,如果不修补libvte本身,还会有其他方法来完成同样的事情吗?我问的原因是解决方案必须在相当多的现有系统上工作。
如果它完全相关,我通过Python与libvte(和GTK +本身)连接。但是,我不反对在C中编写Python扩展,然后我可以从Python程序中调用它,因为您不必在任何系统上获得加载Python扩展的特权。
如果没有可能,我可能会被迫分叉libvte来做我想做的事情并用我的程序分发,但我不想这样做 - 我不想成为卡住了叉子!
答案 0 :(得分:3)
一种可能的解决方案是编写一个帮助程序进程,它打开自己的pty主/从对,并介于libvte
和在slave pty上运行的实际目标程序之间:
+---------------+
| libvte |
| |
| pty master=|-----\
+---------------+ |
|
+---------------+ |
| helper proxy | |
| | |
| stdin/stdout=|-----/
| |
| pty master=|-----\
+---------------+ |
|
+---------------+ |
| target | |
| | |
| stdin/stdout=|-----/
+---------------+
您的帮助程序进程通常只会传递数据,直到它看到ZMODEM流量。然后它停止将数据传递到stdin
/ stdout
(最后结束libvte
),而是通过单独的文件描述符将其传递给您的应用程序,或者甚至只调用rz
本身。
答案 1 :(得分:1)
dup()
'文件描述符不受其他实例的close()
调用的影响;但是,libvte可能会调用其他一些确实改变其状态的关闭方法。使用strace
进行更详细的调查。
除此之外,你可以做一些事情,但它们都不是很漂亮。一种选择是从libvte下替换文件描述符。那就是:
dup()
获取自己的fd副本,并将其存放在某个地方dup2()
以您自己选择的方式覆盖libvte的fd。这应该是一个新的pty,配置类似于你偷窃的配置,以避免混淆libvte。既然你永远不会把任何东西写到另一端,那么读取就会阻塞(你需要对libvte写的那些数据做些什么!)read()
,则向其线程发送一个信号(使用no-op - not SIGIGN - 处理程序)来中断{{ 1}}来电。read()
将fd放回,然后复制libvte可能对原始描述符所做的任何pty状态更改。或者,您可以像caf建议的那样做,并且从一开始就只需要代理pty。