make lttctl and lttd interaction more standard : real daemon
[lttv.git] / ltt / branches / poly / lttv / modules / gui / tracecontrol / tracecontrol.c
index dd2fc97aedb522d2c7cb76a7cdfd10274cbdf259..75921a452bf203af051938a9ed60c3f2c2ff9c65 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <pty.h>
+#include <utmp.h>
+#include <sys/wait.h>
+#include <sys/poll.h>
 
 #define MAX_ARGS_LEN PATH_MAX * 10
 
@@ -73,6 +77,7 @@ static void start_clicked (GtkButton *button, gpointer user_data);
 static void pause_clicked (GtkButton *button, gpointer user_data);
 static void stop_clicked (GtkButton *button, gpointer user_data);
 
+
 /**
  *  @struct _ControlData
  *  
@@ -161,6 +166,8 @@ gui_control(Tab *tab)
   
   gtk_container_add(GTK_CONTAINER(tcd->window), GTK_WIDGET(tcd->main_box));
   
+  GList *focus_chain = NULL;
+  
   /*
    * start/pause/stop buttons
    */
@@ -279,6 +286,7 @@ gui_control(Tab *tab)
   tcd->lttctl_path_label = gtk_label_new("path to lttctl:");
   gtk_widget_show (tcd->lttctl_path_label);
   tcd->lttctl_path_entry = gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(tcd->lttctl_path_entry),PACKAGE_BIN_DIR "/lttctl");
   gtk_widget_show (tcd->lttctl_path_entry);
   gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttctl_path_label,0,2,10,11,GTK_FILL,GTK_FILL,2,2);
   gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttctl_path_entry,2,6,10,11,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0);
@@ -287,6 +295,7 @@ gui_control(Tab *tab)
   tcd->lttd_path_label = gtk_label_new("path to lttd:");
   gtk_widget_show (tcd->lttd_path_label);
   tcd->lttd_path_entry = gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(tcd->lttd_path_entry),PACKAGE_BIN_DIR "/lttd");
   gtk_widget_show (tcd->lttd_path_entry);
   gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttd_path_label,0,2,11,12,GTK_FILL,GTK_FILL,2,2);
   gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttd_path_entry,2,6,11,12,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0);
@@ -295,12 +304,48 @@ gui_control(Tab *tab)
   tcd->fac_path_label = gtk_label_new("path to facilities:");
   gtk_widget_show (tcd->fac_path_label);
   tcd->fac_path_entry = gtk_entry_new();
-  gtk_entry_set_text(GTK_ENTRY(tcd->fac_path_entry),PACKAGE_DATA_DIR "/facilities");
+  gtk_entry_set_text(GTK_ENTRY(tcd->fac_path_entry),PACKAGE_DATA_DIR "/" PACKAGE "/facilities");
   gtk_widget_set_size_request(tcd->fac_path_entry, 250, -1);
   gtk_widget_show (tcd->fac_path_entry);
   gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->fac_path_label,0,2,12,13,GTK_FILL,GTK_FILL,2,2);
   gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->fac_path_entry,2,6,12,13,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0);
 
+
+  GtkWidget *start_button;
+  GtkWidget *pause_button;
+  GtkWidget *stop_button;
+
+  GtkWidget *username_entry;
+  GtkWidget *password_entry;
+  GtkWidget *channel_dir_entry;
+  GtkWidget *trace_dir_entry;
+  GtkWidget *trace_name_entry;
+  GtkWidget *trace_mode_combo;
+  GtkWidget *start_daemon_check;
+  GtkWidget *subbuf_size_entry;
+  GtkWidget *subbuf_num_entry;
+  GtkWidget *lttctl_path_entry;
+  GtkWidget *lttd_path_entry;
+  GtkWidget *fac_path_entry;
+
+  focus_chain = g_list_append (focus_chain, tcd->username_entry);
+  focus_chain = g_list_append (focus_chain, tcd->password_entry);
+  focus_chain = g_list_append (focus_chain, tcd->start_button);
+  focus_chain = g_list_append (focus_chain, tcd->pause_button);
+  focus_chain = g_list_append (focus_chain, tcd->stop_button);
+  focus_chain = g_list_append (focus_chain, tcd->channel_dir_entry);
+  focus_chain = g_list_append (focus_chain, tcd->trace_dir_entry);
+  focus_chain = g_list_append (focus_chain, tcd->trace_name_entry);
+  focus_chain = g_list_append (focus_chain, tcd->trace_mode_combo);
+  focus_chain = g_list_append (focus_chain, tcd->start_daemon_check);
+  focus_chain = g_list_append (focus_chain, tcd->subbuf_size_entry);
+  focus_chain = g_list_append (focus_chain, tcd->subbuf_num_entry);
+  focus_chain = g_list_append (focus_chain, tcd->lttctl_path_entry);
+  focus_chain = g_list_append (focus_chain, tcd->lttd_path_entry);
+  focus_chain = g_list_append (focus_chain, tcd->fac_path_entry);
+
+  gtk_container_set_focus_chain(GTK_CONTAINER(tcd->main_box), focus_chain);
+
   g_signal_connect(G_OBJECT(tcd->start_button), "clicked",
       (GCallback)start_clicked, tcd);
   g_signal_connect(G_OBJECT(tcd->pause_button), "clicked", 
@@ -390,11 +435,138 @@ void start_clicked (GtkButton *button, gpointer user_data)
   const gchar *lttd_path = gtk_entry_get_text(GTK_ENTRY(tcd->lttd_path_entry));
   const gchar *fac_path = gtk_entry_get_text(GTK_ENTRY(tcd->fac_path_entry));
 
-  pid_t pid = fork();
+  //pid_t pid = fork();
+  pid_t pid;
+  int fdpty;
+  pid = forkpty(&fdpty, NULL, NULL, NULL);
 
   if(pid > 0) {
     /* parent */
+    gchar buf[256];
+    int status;
+    ssize_t count;
+    /* discuss with su */
+    struct timeval timeout;
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+
+    struct pollfd pollfd;
+    int num_rdy;
+    int num_hup = 0;
+
+
+    /* Read the output from the child terminal before the prompt. If no data in
+     * 200 ms, we stop reading to give the password */
+    g_info("Reading from child console...");
+    while(1) {
+      pollfd.fd = fdpty;
+      pollfd.events = POLLIN|POLLPRI;
+
+      num_rdy = poll(&pollfd, 1, 200);
+#if 0
+      if(num_rdy == -1) {
+        perror("Poll error");
+        goto wait_child;
+      }
+#endif //0
+      
+      /* Timeout : stop waiting for chars */
+      if(num_rdy == 0) break;
+
+      switch(pollfd.revents) {
+        case POLLERR:
+          g_warning("Error returned in polling fd\n");
+          num_hup++;
+          break;
+        case POLLHUP:
+          g_info("Polling FD : hung up.");
+          num_hup++;
+          break;
+        case POLLNVAL:
+          g_warning("Polling fd tells it is not open");
+          num_hup++;
+          break;
+        case POLLPRI:
+        case POLLIN:
+          count = read (fdpty, buf, 256);
+          if(count > 0) {
+            buf[count] = '\0';
+            printf("%s", buf);
+          } else if(count == -1) {
+            perror("Error in read");
+            goto wait_child;
+          }
+          break;
+      }
+      if(num_hup > 0) {
+        g_warning("Child hung up too fast");
+        goto wait_child;
+      }
+    }
+    
+    /* Write the password */
+    g_info("Got su prompt, now writing password...");
+    int ret;
+    ret = write(fdpty, password, strlen(password));
+    if(ret < 0) perror("Error in write");
+    ret = write(fdpty, "\n", 1);
+    if(ret < 0) perror("Error in write");
+    fsync(fdpty);
+
+    /* Take the output from the terminal and show it on the real console */
+    g_info("Getting data from child terminal...");
+    while(1) {
+      int num_hup = 0;
+      pollfd.fd = fdpty;
+      pollfd.events = POLLIN|POLLPRI;
+
+      num_rdy = poll(&pollfd, 1, -1);
+#if 0
+      if(num_rdy == -1) {
+        perror("Poll error");
+        goto wait_child;
+      }
+#endif //0
+      if(num_rdy == 0) break;
+
+      switch(pollfd.revents) {
+        case POLLERR:
+          g_warning("Error returned in polling fd\n");
+          num_hup++;
+          break;
+        case POLLHUP:
+          g_info("Polling FD : hung up.");
+          num_hup++;
+          break;
+        case POLLNVAL:
+          g_warning("Polling fd tells it is not open");
+          num_hup++;
+          break;
+        case POLLPRI:
+        case POLLIN:
+          count = read (fdpty, buf, 256);
+          if(count > 0) {
+            buf[count] = '\0';
+            printf("%s", buf);
+          } else if(count == -1) {
+            perror("Error in read");
+            goto wait_child;
+          }
+          break;
+      }
+      if(num_hup > 0) goto wait_child;
+    }
+wait_child:
+    g_info("Waiting for child exit...");
+    
+    ret = waitpid(pid, &status, 0);
+
+    if(WIFEXITED(ret))
+      if(WEXITSTATUS(ret) != 0)
+       g_warning("An error occured in the su command : %s",
+           strerror(WEXITSTATUS(ret)));
 
+    g_info("Child exited.");
 
   } else if(pid == 0) {
     /* child */
@@ -408,13 +580,22 @@ void start_clicked (GtkButton *button, gpointer user_data)
       setenv("LTT_FACILITIES", fac_path, 1);
    
     /* Setup arguments to su */
-    if(strcmp(lttctl_path, "") == 0) {
-      strncpy(args, "lttctl", args_left);
-      args_left = MAX_ARGS_LEN - strlen(args) - 1;
-    } else {
-      strncpy(args, lttctl_path, args_left);
-      args_left = MAX_ARGS_LEN - strlen(args) - 1;
-    }
+    //strncpy(args, "\'", args_left);
+    //args_left = MAX_ARGS_LEN - strlen(args) - 1;
+    
+    /* Command */
+    strncat(args, "exec", args_left);
+    args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+    /* space */
+    strncat(args, " ", args_left);
+    args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+    if(strcmp(lttctl_path, "") == 0)
+      strncat(args, "lttctl", args_left);
+    else
+      strncat(args, lttctl_path, args_left);
+    args_left = MAX_ARGS_LEN - strlen(args) - 1;
 
     /* space */
     strncat(args, " ", args_left);
@@ -470,43 +651,47 @@ void start_clicked (GtkButton *button, gpointer user_data)
       args_left = MAX_ARGS_LEN - strlen(args) - 1;
     }
     
-    /* space */
-    strncat(args, " ", args_left);
-    args_left = MAX_ARGS_LEN - strlen(args) - 1;
-
     /* optional arguments */
     /* subbuffer size */
     if(strcmp(subbuf_size, "") != 0) {
+      /* space */
+      strncat(args, " ", args_left);
+      args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
       strncat(args, "-z ", args_left);
       args_left = MAX_ARGS_LEN - strlen(args) - 1;
       strncat(args, subbuf_size, args_left);
       args_left = MAX_ARGS_LEN - strlen(args) - 1;
     }
 
-    /* space */
-    strncat(args, " ", args_left);
-    args_left = MAX_ARGS_LEN - strlen(args) - 1;
-
     /* number of subbuffers */
     if(strcmp(subbuf_num, "") != 0) {
+      /* space */
+      strncat(args, " ", args_left);
+      args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
       strncat(args, "-x ", args_left);
       args_left = MAX_ARGS_LEN - strlen(args) - 1;
       strncat(args, subbuf_num, args_left);
       args_left = MAX_ARGS_LEN - strlen(args) - 1;
     }
+   
+    //strncat(args, "\'", args_left);
+    //args_left = MAX_ARGS_LEN - strlen(args) - 1;
     
-    g_message("Executing (as %s) : %s", username, args);
+    g_message("Executing (as %s) : %s\n", username, args);
     
-    //execlp("su", "-p", );
-    //exit(-1): /* not supposed to happen! */
-    system(args);
-    exit(0);
+    execlp("su", "su", "-p", "-c", args, username, NULL);
+    exit(-1); /* not supposed to happen! */
+    //system(args);
+    //system("echo blah");
+    //exit(0);
     
     //gint ret = execvp();
   
   } else {
     /* error */
-
+    g_warning("Error happened when forking for su");
   }
   
 }
This page took 0.028157 seconds and 4 git commands to generate.