2011-06-20 62 views
3

有一個庫(libvte,終端仿真庫),其使用一對文件描述符用於PTY主/從對。我需要能夠從庫中「偷走」主fd供我自己使用(爲了在非常罕見的情況下實現對ZMODEM的支持,當我唯一的鏈接是通過終端訪問'net'時)。但是,有一個問題。防止文件描述符對POSIX系統閉合

你可以告訴你想要的文件描述符改變到一個新的libvte,但隨後嘗試關閉它使用主,並開始使用新的來代替。這是行不通的,因爲當主人關閉時奴隸會消失。本來,我認爲,這將有可能使用dup()上pty主,這樣當libvte在PTY主做close(),我還是有一個正常運作的FD使用。這顯然是錯誤的。

我需要找到一個辦法之一:

  • 座libvte的對FD read()操作。
  • 偷FD從libvte距離,直到我用它做(例如,直到rz過程,我把它連接到出口)

是否有可能一個POSIX系統上做任何的這些東西?或者是否有其他方法可以在不修補libvte本身的情況下完成同樣的任務?我問的原因是解決方案必須在相當多的現有系統上工作。

如果是在所有相關的,我與libvte接口(和GTK +本身)通過Python。但是,我不會反對在C中編寫Python擴展,然後我可以從Python程序調用,因爲您不必在任何系統上都有權加載Python擴展。

如果沒有可能,我可能會被迫分叉libvte做我想做的事情,並將其與我的程序分發,但我不想這樣做---我不想被卡住保持一個叉!

+0

你不想用Python或C標記嗎?祝你好運! – shellter

+0

我會的,但是這個問題對於兩者都是不可知論的,我認爲......如果我標記「C」,人們可能會說這不是一個C問題,這是一個Python問題(作爲目標環境和所有);如果我標記Python,他們可能會說這實際上是C級或系統調用級別的問題......不知道該怎麼辦! –

+0

只是對於那些通過語言檢查'他們'專業的人來說,可能永遠不會看到你的問題。我會用'C'去,因爲這(幾乎肯定)是POSIX的基礎語言。與'文件描述符'相比? ;-)?如果您沒有得到任何答案,您可以在一天或兩天內將其更改爲Python。我在我的標準'檢查S.O.'中加入'C'我在晦澀難懂的問題上看到的答案的力度令人h目結舌;-)祝你好運! – shellter

回答

3

一個可能的解決辦法是寫一個打開自己的pty主/從對,libvte,並且在從屬pty運行實際的目標程序之間介於助手進程:

+---------------+ 
| libvte  | 
|    | 
| pty master=|-----\ 
+---------------+  | 
         | 
+---------------+  | 
| helper proxy |  | 
|    |  | 
| stdin/stdout=|-----/ 
|    | 
| pty master=|-----\ 
+---------------+  | 
         | 
+---------------+  | 
| target  |  | 
|    |  | 
| stdin/stdout=|-----/ 
+---------------+ 

你的助手進程通常只是通過數據,直到看到ZMODEM流量。然後它會停止將數據傳遞到stdin/stdout(最終結果爲libvte),而是通過單獨的文件描述符將其傳遞到您的應用程序,或者甚至僅調用rz本身。

1

dup()「d文件描述符不受其他情況下的close()電話;然而,libvte可能會調用其他一些關閉方法來改變它的狀態。使用strace進行更詳細的調查。

除此之外,也有一些事情可以做,但他們都不是很漂亮。一種選擇是從libvte下取代文件描述符。那就是:

  • 首先,使用dup()讓自己的FD的副本,地方
  • 藏匿它使用dup2()覆蓋libvte的fd與你自己的選擇之一。這應該是一個新的pty,配置類似於您正在竊取的配置,以避免混淆libvte。由於你永遠不會寫任何東西到另一端,讀取將會阻塞(你需要對任何數據libvte可能寫下來做一些事情!)
  • 如果libvte可能在這個時候阻塞read(),send給它的線程發送一個信號(沒有操作 - 而不是 SIGIGN - 處理程序)來中斷read()調用。
  • 跟你在一開始
  • 複製到恢復正常,使用dup2()把FD回來,然後複製任何PTY狀態變化libvte可能已經到原來的描述作出的FD的工作。

或者,你可以按照caf的建議來做,而且從一開始就有一個代理pty。