+static int execute_command(const gchar *command, const gchar *username,
+ const gchar *password, const gchar *lttd_path, const gchar *fac_path)
+{
+ pid_t pid;
+ int fdpty;
+ pid = forkpty(&fdpty, NULL, NULL, NULL);
+ int retval = 0;
+
+ 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(ret == -1) {
+ g_warning("An error occured in wait : %s",
+ strerror(errno));
+ } else {
+ if(WIFEXITED(status))
+ if(WEXITSTATUS(status) != 0) {
+ retval = WEXITSTATUS(status);
+ g_warning("An error occured in the su command : %s",
+ strerror(retval));
+ }
+ }
+
+ g_info("Child exited.");
+
+ } else if(pid == 0) {
+ /* Setup environment variables */
+ if(strcmp(lttd_path, "") != 0)
+ setenv("LTT_DAEMON", lttd_path, 1);
+ if(strcmp(fac_path, "") != 0)
+ setenv("LTT_FACILITIES", fac_path, 1);
+
+ g_message("Executing (as %s) : %s\n", username, command);
+
+ execlp("su", "su", "-p", "-c", command, username, NULL);
+ exit(-1); /* not supposed to happen! */
+
+ //gint ret = execvp();
+
+ } else {
+ /* error */
+ g_warning("Error happened when forking for su");
+ }
+
+ return retval;
+}
+
+
+/* Callbacks */
+
+void start_clicked (GtkButton *button, gpointer user_data)
+{
+ ControlData *tcd = (ControlData*)user_data;
+
+ const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
+ const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
+ const gchar *channel_dir =
+ gtk_entry_get_text(GTK_ENTRY(tcd->channel_dir_entry));
+ const gchar *trace_dir = gtk_entry_get_text(GTK_ENTRY(tcd->trace_dir_entry));
+ const gchar *trace_name =
+ gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
+
+ const gchar *trace_mode_sel =
+ gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
+ const gchar *trace_mode;
+ if(strcmp(trace_mode_sel, "normal") == 0)
+ trace_mode = "normal";
+ else
+ trace_mode = "flight";
+
+ gboolean start_daemon =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd->start_daemon_check));
+
+ gboolean append =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd->append_check));
+
+ const gchar *subbuf_size =
+ gtk_entry_get_text(GTK_ENTRY(tcd->subbuf_size_entry));
+ const gchar *subbuf_num =
+ gtk_entry_get_text(GTK_ENTRY(tcd->subbuf_num_entry));
+ const gchar *lttctl_path =
+ gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
+ 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));
+
+
+ /* Setup arguments to su */
+ /* child */
+ gchar args[MAX_ARGS_LEN];
+ gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
+
+ args[0] = '\0';
+
+ /* 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);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* channel dir */
+ strncat(args, "-l ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, channel_dir, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* trace dir */
+ strncat(args, "-t ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, trace_dir, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* name */
+ strncat(args, "-n ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, trace_name, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* trace mode */
+ strncat(args, "-m ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, trace_mode, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* Start daemon ? */
+ if(start_daemon) {
+ strncat(args, "-d", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ } else {
+ /* Simply create the channel and then start tracing */
+ strncat(args, "-b", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ }
+
+
+ /* Append to trace ? */
+ if(append) {
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, "-a", 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;
+ }
+
+ /* 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;
+ }
+
+
+ int retval = execute_command(args, username, password, lttd_path, fac_path);
+
+ if(retval) {
+ gchar msg[256];
+ guint msg_left = 256;
+
+ strcpy(msg, "A problem occured when executing the su command : ");
+ msg_left = 256 - strlen(msg) - 1;
+ strncat(msg, strerror(retval), msg_left);
+ GtkWidget *dialogue =
+ gtk_message_dialog_new(
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ msg);
+ gtk_dialog_run(GTK_DIALOG(dialogue));
+ gtk_widget_destroy(dialogue);
+ }
+
+}
+
+
+void pause_clicked (GtkButton *button, gpointer user_data)
+{
+ ControlData *tcd = (ControlData*)user_data;
+
+ const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
+ const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
+ const gchar *trace_name =
+ gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
+ const gchar *lttd_path = "";
+ const gchar *fac_path = "";
+
+ const gchar *lttctl_path =
+ gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
+
+ /* Setup arguments to su */
+ /* child */
+ gchar args[MAX_ARGS_LEN];
+ gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
+
+ args[0] = '\0';
+
+ /* 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);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* name */
+ strncat(args, "-n ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, trace_name, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* Simply pause tracing */
+ strncat(args, "-q", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ int retval = execute_command(args, username, password, lttd_path, fac_path);
+ if(retval) {
+ gchar msg[256];
+ guint msg_left = 256;
+
+ strcpy(msg, "A problem occured when executing the su command : ");
+ msg_left = 256 - strlen(msg) - 1;
+ strncat(msg, strerror(retval), msg_left);
+ GtkWidget *dialogue =
+ gtk_message_dialog_new(
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ msg);
+ gtk_dialog_run(GTK_DIALOG(dialogue));
+ gtk_widget_destroy(dialogue);
+ }
+
+}
+
+void unpause_clicked (GtkButton *button, gpointer user_data)
+{
+ ControlData *tcd = (ControlData*)user_data;
+
+ const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
+ const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
+ const gchar *trace_name =
+ gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
+ const gchar *lttd_path = "";
+ const gchar *fac_path = "";
+
+ const gchar *lttctl_path =
+ gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
+
+ /* Setup arguments to su */
+ /* child */
+ gchar args[MAX_ARGS_LEN];
+ gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
+
+ args[0] = '\0';
+
+ /* 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);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* name */
+ strncat(args, "-n ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, trace_name, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* Simply unpause tracing */
+ strncat(args, "-s", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ int retval = execute_command(args, username, password, lttd_path, fac_path);
+ if(retval) {
+ gchar msg[256];
+ guint msg_left = 256;
+
+ strcpy(msg, "A problem occured when executing the su command : ");
+ msg_left = 256 - strlen(msg) - 1;
+ strncat(msg, strerror(retval), msg_left);
+ GtkWidget *dialogue =
+ gtk_message_dialog_new(
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ msg);
+ gtk_dialog_run(GTK_DIALOG(dialogue));
+ gtk_widget_destroy(dialogue);
+ }
+
+}
+
+void stop_clicked (GtkButton *button, gpointer user_data)
+{
+ ControlData *tcd = (ControlData*)user_data;
+
+ const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
+ const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
+ const gchar *trace_name =
+ gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
+ const gchar *lttd_path = "";
+ const gchar *fac_path = "";
+
+ const gchar *lttctl_path =
+ gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
+ const gchar *trace_dir = gtk_entry_get_text(GTK_ENTRY(tcd->trace_dir_entry));
+
+ /* Setup arguments to su */
+ /* child */
+ gchar args[MAX_ARGS_LEN];
+ gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
+
+ args[0] = '\0';
+
+ /* 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);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* name */
+ strncat(args, "-n ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+ strncat(args, trace_name, args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* space */
+ strncat(args, " ", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ /* Simply stop tracing and destroy channel */
+ strncat(args, "-R", args_left);
+ args_left = MAX_ARGS_LEN - strlen(args) - 1;
+
+ int retval = execute_command(args, username, password, lttd_path, fac_path);
+ if(retval) {
+ gchar msg[256];
+ guint msg_left = 256;
+
+ strcpy(msg, "A problem occured when executing the su command : ");
+ msg_left = 256 - strlen(msg) - 1;
+ strncat(msg, strerror(retval), msg_left);
+ GtkWidget *dialogue =
+ gtk_message_dialog_new(
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
+ GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ msg);
+ gtk_dialog_run(GTK_DIALOG(dialogue));
+ gtk_widget_destroy(dialogue);
+ return;
+ }
+
+
+ /* Ask to the user if he wants to open the trace in a new window */
+ GtkWidget *dialogue;
+ GtkWidget *label;
+ gint id;
+
+ dialogue = gtk_dialog_new_with_buttons("Open trace ?",
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_YES,GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_NO,GTK_RESPONSE_REJECT,
+ NULL);
+ label = gtk_label_new("Do you want to open the trace in LTTV ?");
+ gtk_widget_show(label);
+
+ gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue)->vbox),
+ label);
+
+ id = gtk_dialog_run(GTK_DIALOG(dialogue));
+
+ switch(id){
+ case GTK_RESPONSE_ACCEPT:
+ {
+ create_main_window_with_trace(trace_dir);
+ }
+ break;
+ case GTK_RESPONSE_REJECT:
+ default:
+ break;
+ }
+ gtk_widget_destroy(dialogue);
+
+}
+