1

我正在尝试从 Gnome/GTK 生成一个新应用程序到 CLI 应用程序,并将其输出读回我的 Gnome/GTK 应用程序。

对于大多数 shell 命令,该代码按预期工作,但使用tail -f /var/log/messagestop则不能。有没有办法解析这两个命令的输出?

我正在运行 Ubuntu 12.04.2 LTS 和 libgtk2.0。

#include <gtk/gtk.h>

static GtkWidget *window;          // pointer to window  
static GtkWidget *view;            // pointer to textview
static GtkTextBuffer *buffer;      // pointer to buffer
static GtkTextIter   iter;         // gtktextview iterator 
static GtkWidget *scrolled_window; // pointer to scrolled window

FILE *fp;                          // pointer to stdin/out file pipe
char line[256];                    // line read buffer size

static gboolean on_delete_event (GtkWidget *widget, GdkEvent *event, gpointer data){
  gtk_main_quit();  
  return FALSE;
}

void create_gui(){
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    g_signal_connect (G_OBJECT (window), "delete_event",
    G_CALLBACK(on_delete_event), NULL);
    gtk_window_set_title (GTK_WINDOW (window), "GUI Front-End for CLI");

    GtkWidget *box = gtk_vbox_new(FALSE, 10);                // Create a box and 
    gtk_container_add (GTK_CONTAINER(window), box);          // set it as window's main child.

    scrolled_window=gtk_scrolled_window_new(NULL, NULL);     // Now create scrolled window...  
    gtk_widget_set_usize(scrolled_window, 650, 450);         // Set scrolled window size..

    gtk_container_add(GTK_CONTAINER(box), scrolled_window);  // Add scrolled window to vbox.. 
    view = gtk_text_view_new();                              // Create textview..
    gtk_container_add(GTK_CONTAINER(scrolled_window), view); // Add textview to scrolled window..
    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));  // Assign textview buffer 
    }

void populate(){

 fp = popen("cat /var/log/messages", "r");                   // run shell command using pipe

 while ( fgets( line, sizeof line, fp)){                     //
   gtk_text_buffer_get_end_iter (buffer, &iter);             
   gtk_text_buffer_insert (buffer, &iter, line, -1);
 }  
   pclose(fp);                                               // CLOSE Pipe 
}

int main (int argc, char *argv[]){
  gtk_init (&argc, &argv);
  create_gui();
  populate(); 
  gtk_widget_show_all (window);
  gtk_main ();
  return 0;
}

// TODO
// fp = popen("ls -al", "r");        
// fp = popen("cat /proc/cpuinfo", "r");        
// fp = popen("cat /var/log/messages", "r");        
// fp = popen("lspci -v", "r");        
// fp = popen("w", "r");        
// fp = popen("last", "r");        
// fp = popen("pstree", "r");         

// fp = popen("tail -f /var/log/messages &", "r");  THIS DOES NOT WORK !      
// fp = popen("top", "r");                          NEITHER DOES THIS..
enter code here
4

1 回答 1

1

top并且tail -f是长时间运行的程序(实际上,它们永远不会退出),因此您读取整个输出并用它填充文本缓冲区的策略显然行不通。

相反,您需要创建一个IO 通道来监视管道发生的事情,将通道挂接到事件循环中,并在新输出到达时将其附加到文本缓冲区。对您的程序进行的最小更改是prepare像这样重写函数:

static gboolean data_ready(GIOChannel *channel, GIOCondition cond, gpointer data)
{
  FILE *fp = data;
  char line[256];

  if (fgets(line, sizeof line, fp)) {
      gtk_text_buffer_get_end_iter (buffer, &iter);             
      gtk_text_buffer_insert (buffer, &iter, line, -1);
      return TRUE;
  }
  else {
      fclose(fp);
      return FALSE;
  }
}

void populate(){
  FILE *fp = popen("top -b", "r");
  GIOChannel *channel = g_io_channel_unix_new(fileno(fp));
  g_io_add_watch(channel, G_IO_IN, data_ready, fp);
}
于 2013-06-22T18:09:28.200 回答