如何使用ncurses在窗口中捕獲命令行輸出?在ncurses中捕獲命令行輸出
假設我正在執行像「ls」這樣的命令,我想在ncurses中設計的特定窗口中輸出該輸出。我是新來ncurses.help me.Thanks提前
如何使用ncurses在窗口中捕獲命令行輸出?在ncurses中捕獲命令行輸出
假設我正在執行像「ls」這樣的命令,我想在ncurses中設計的特定窗口中輸出該輸出。我是新來ncurses.help me.Thanks提前
一個我能想到的是使用system()來執行命令,它的輸出重定向到一個臨時文件的事情:
system("ls > temp");
然後打開文件溫度,讀取其內容並將其顯示在窗口上。
不是一個優雅的解決方案,但工程。
更優雅的解決方案可能是在程序中實現重定向。查看dup()和dup2()系統調用(請參閱dup(2)聯機幫助頁)。所以,你會想要做的是(實際上,這就是由系統調用()的殼最後也做):
代碼段:
char *tmpname;
int tmpfile;
pid_t pid;
int r;
tmpname = strdup("/tmp/ls_out_XXXXXX");
assert(tmpname);
tmpfile = mkstemp(tmpname);
assert(tmpfile >= 0);
pid = fork();
if (pid == 0) { // child process
r = dup2(STDOUT_FILENO, tmpfile);
assert(r == STDOUT_FILENO);
execl("/bin/ls", "ls", NULL);
assert(0);
} else if (pid > 0) { // parent
waitpid(pid, &r, 0);
/* you can mmap(2) tmpfile here, and read from it like it was a memory buffer, or
* read and write as normal, mmap() is nicer--the kernel handles the buffering
* and other memory management hassles.
*/
} else {
/* fork() failed, bail violently for this example, you can handle differently as
* appropriately.
*/
assert(0);
}
// tmpfile is the file descriptor for the ls output.
unlink(tmpname); // file stays around until close(2) for this process only
更多挑剔的程序(那些關心他們有一個用於輸入和輸出的終端),您將需要查看僞ttys,請參閱pty(7)手冊頁。 (或google'pty')。如果你想讓ls做它的多列漂亮打印(例如,ls會檢測到它正在輸出到一個文件,並且將一個文件名寫入一行),這將是必需的。如果你想讓ls去做你需要一個pty。另外,你應該能夠在fork()之後設置$ LINES和$ COLUMNS環境變量,以便讓ls能夠很好地打印到你的窗口大小 - 同樣,假設你正在使用一個pty,最重要的變化是你可以刪除tmpfile = mkstemp(...);並用pty打開邏輯替換它和周圍的邏輯,並且擴展dup2()調用來處理stdin和stderr ,dup2()從它們的pty文件句柄)。 ()和printw()/ addch()/ addstr()命令轉換到相應的控制檯中(如果用戶可以在窗口中執行任意程序,則需要小心ncurses程序)代碼,所以一味打印ncurses程序的輸出會壓制你的程序輸出並忽略你的窗口位置。 GNU屏幕是研究如何處理這個問題的一個很好的例子 - 它實現了一個VT100終端仿真器來捕獲ncurses代碼,並使用自己的termcap/terminfo條目實現自己的'screen'終端。屏幕的子程序在僞終端中運行。 (xterm和其他終端仿真器執行類似的技巧。)
最後說明:我沒有編譯上面的代碼。它可能有小的錯別字,但應該大致正確。如果您使用mmap(),請確保使用munmap()。另外,在完成ls輸出後,您需要關閉(tmpfile)。 unlink()在代碼中或者在close()調用之前可能會早得多 - 取決於你是否希望人們看到你的輸出 - 我通常將unlink()直接放在mkstemp之後()調用 - 如果tmp目錄是磁盤備份的,這可以防止內核將文件寫回磁盤(由於tmpfs,這是不太常見的)。另外,在取消鏈接()以防止內存泄漏之後,您需要釋放(tmpname)。 strdup()是必需的,因爲tmpname是由mkstemp()修改的。
諾曼·馬特夫顯示了他的Introduction to the Unix Curses Library第五頁的方式:
// runs "ps ax" and stores the output in cmdoutlines
runpsax()
{ FILE* p; char ln[MAXCOL]; int row,tmp;
p = popen("ps ax","r"); // open Unix pipe (enables one program to read
// output of another as if it were a file)
for (row = 0; row < MAXROW; row++) {
tmp = fgets(ln,MAXCOL,p); // read one line from the pipe
if (tmp == NULL) break; // if end of pipe, break
// don’t want stored line to exceed width of screen, which the
// curses library provides to us in the variable COLS, so truncate
// to at most COLS characters
strncpy(cmdoutlines[row],ln,COLS);
// remove EOL character
cmdoutlines[row][MAXCOL-1] = 0;
}
ncmdlines = row;
close(p); // close pipe
}
...
他然後叫mvaddstr(...)
通過ncurses的熄從數組行。
是的示例是curses示例應用程序的一部分,但顯示的代碼與curses無關。這只是常規的輸出重定向 – sehe 2016-12-14 20:04:53