1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2005 Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 #include <gdk/gdkkeysyms.h>
29 #include <lttv/lttv.h>
30 #include <lttv/module.h>
31 #include <lttv/hook.h>
33 #include <lttvwindow/lttvwindow.h>
34 #include <lttvwindow/lttvwindowtraces.h>
36 #include "hTraceControlInsert.xpm"
37 #include "TraceControlStart.xpm"
38 #include "TraceControlPause.xpm"
39 #include "TraceControlStop.xpm"
41 #include <sys/types.h>
50 #define MAX_ARGS_LEN PATH_MAX * 10
52 GSList
*g_control_list
= NULL
;
54 /*! \file lttv/modules/gui/tracecontrol/tracecontrol.c
55 * \brief Graphic trace start/stop control interface.
57 * This plugin interacts with lttctl to start/stop tracing. It needs to take the
58 * root password to be able to interact with lttctl.
62 typedef struct _ControlData ControlData
;
67 GtkWidget
*guicontrol_get_widget(ControlData
*tcd
);
68 ControlData
*gui_control(Tab
*tab
);
69 void gui_control_destructor(ControlData
*tcd
);
70 GtkWidget
* h_guicontrol(Tab
*tab
);
71 void control_destroy_walk(gpointer data
, gpointer user_data
);
77 static void start_clicked (GtkButton
*button
, gpointer user_data
);
78 static void pause_clicked (GtkButton
*button
, gpointer user_data
);
79 static void unpause_clicked (GtkButton
*button
, gpointer user_data
);
80 static void stop_clicked (GtkButton
*button
, gpointer user_data
);
84 * @struct _ControlData
86 * @brief Main structure of gui control
89 Tab
*tab
; /**< current tab of module */
91 GtkWidget
*window
; /**< window */
93 GtkWidget
*main_box
; /**< main container */
94 GtkWidget
*start_button
;
95 GtkWidget
*pause_button
;
96 GtkWidget
*unpause_button
;
97 GtkWidget
*stop_button
;
98 GtkWidget
*username_label
;
99 GtkWidget
*username_entry
;
100 GtkWidget
*password_label
;
101 GtkWidget
*password_entry
;
102 GtkWidget
*channel_dir_label
;
103 GtkWidget
*channel_dir_entry
;
104 GtkWidget
*trace_dir_label
;
105 GtkWidget
*trace_dir_entry
;
106 GtkWidget
*trace_name_label
;
107 GtkWidget
*trace_name_entry
;
108 GtkWidget
*trace_mode_label
;
109 GtkWidget
*trace_mode_combo
;
110 GtkWidget
*start_daemon_label
;
111 GtkWidget
*start_daemon_check
;
112 GtkWidget
*append_label
;
113 GtkWidget
*append_check
;
114 GtkWidget
*optional_label
;
115 GtkWidget
*subbuf_size_label
;
116 GtkWidget
*subbuf_size_entry
;
117 GtkWidget
*subbuf_num_label
;
118 GtkWidget
*subbuf_num_entry
;
119 GtkWidget
*lttd_threads_label
;
120 GtkWidget
*lttd_threads_entry
;
121 GtkWidget
*lttctl_path_label
;
122 GtkWidget
*lttctl_path_entry
;
123 GtkWidget
*lttd_path_label
;
124 GtkWidget
*lttd_path_entry
;
125 GtkWidget
*fac_path_label
;
126 GtkWidget
*fac_path_entry
;
130 * @fn GtkWidget* guicontrol_get_widget(ControlData*)
132 * This function returns the current main widget
133 * used by this module
134 * @param tcd the module struct
135 * @return The main widget
138 guicontrol_get_widget(ControlData
*tcd
)
144 * @fn ControlData* gui_control(Tab*)
146 * Constructor is used to create ControlData data structure.
147 * @param tab The tab structure used by the widget
148 * @return The Filter viewer data created.
151 gui_control(Tab
*tab
)
153 g_debug("filter::gui_control()");
156 GtkCellRenderer
*renderer
;
157 GtkTreeViewColumn
*column
;
159 ControlData
* tcd
= g_new(ControlData
,1);
163 tcd
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
164 gtk_window_set_title(GTK_WINDOW(tcd
->window
), "LTTng Trace Control");
166 * Initiating GtkTable layout
167 * starts with 2 rows and 5 columns and
168 * expands when expressions added
170 tcd
->main_box
= gtk_table_new(14,7,FALSE
);
171 gtk_table_set_row_spacings(GTK_TABLE(tcd
->main_box
),5);
172 gtk_table_set_col_spacings(GTK_TABLE(tcd
->main_box
),5);
174 gtk_container_add(GTK_CONTAINER(tcd
->window
), GTK_WIDGET(tcd
->main_box
));
176 GList
*focus_chain
= NULL
;
179 * start/pause/stop buttons
183 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStart_xpm
);
184 image
= gtk_image_new_from_pixbuf(pixbuf
);
185 tcd
->start_button
= gtk_button_new_with_label("start");
186 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->start_button), image);
187 g_object_set(G_OBJECT(tcd
->start_button
), "image", image
, NULL
);
188 gtk_button_set_alignment(GTK_BUTTON(tcd
->start_button
), 0.0, 0.0);
189 gtk_widget_show (tcd
->start_button
);
190 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_button
,6,7,0,1,GTK_FILL
,GTK_FILL
,2,2);
192 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
193 image
= gtk_image_new_from_pixbuf(pixbuf
);
194 tcd
->pause_button
= gtk_button_new_with_label("pause");
195 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->pause_button), image);
196 g_object_set(G_OBJECT(tcd
->pause_button
), "image", image
, NULL
);
197 gtk_button_set_alignment(GTK_BUTTON(tcd
->pause_button
), 0.0, 0.0);
198 gtk_widget_show (tcd
->pause_button
);
199 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->pause_button
,6,7,1,2,GTK_FILL
,GTK_FILL
,2,2);
201 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
202 image
= gtk_image_new_from_pixbuf(pixbuf
);
203 tcd
->unpause_button
= gtk_button_new_with_label("unpause");
204 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->unpause_button), image);
205 g_object_set(G_OBJECT(tcd
->unpause_button
), "image", image
, NULL
);
206 gtk_button_set_alignment(GTK_BUTTON(tcd
->unpause_button
), 0.0, 0.0);
207 gtk_widget_show (tcd
->unpause_button
);
208 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->unpause_button
,6,7,2,3,GTK_FILL
,GTK_FILL
,2,2);
210 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStop_xpm
);
211 image
= gtk_image_new_from_pixbuf(pixbuf
);
212 tcd
->stop_button
= gtk_button_new_with_label("stop");
213 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->stop_button), image);
214 g_object_set(G_OBJECT(tcd
->stop_button
), "image", image
, NULL
);
215 gtk_button_set_alignment(GTK_BUTTON(tcd
->stop_button
), 0.0, 0.0);
216 gtk_widget_show (tcd
->stop_button
);
217 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->stop_button
,6,7,3,4,GTK_FILL
,GTK_FILL
,2,2);
220 * First half of the filter window
221 * - textual entry of filter expression
222 * - processing button
224 tcd
->username_label
= gtk_label_new("Username:");
225 gtk_widget_show (tcd
->username_label
);
226 tcd
->username_entry
= gtk_entry_new();
227 gtk_entry_set_text(GTK_ENTRY(tcd
->username_entry
),"root");
228 gtk_widget_show (tcd
->username_entry
);
229 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->username_label
,0,2,0,1,GTK_FILL
,GTK_FILL
,2,2);
230 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->username_entry
,2,6,0,1,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
234 tcd
->password_label
= gtk_label_new("Password:");
235 gtk_widget_show (tcd
->password_label
);
236 tcd
->password_entry
= gtk_entry_new();
237 gtk_entry_set_visibility(GTK_ENTRY(tcd
->password_entry
), FALSE
);
238 gtk_widget_show (tcd
->password_entry
);
239 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->password_label
,0,2,1,2,GTK_FILL
,GTK_FILL
,2,2);
240 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->password_entry
,2,6,1,2,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
243 tcd
->channel_dir_label
= gtk_label_new("Channel directory:");
244 gtk_widget_show (tcd
->channel_dir_label
);
245 tcd
->channel_dir_entry
= gtk_entry_new();
246 gtk_entry_set_text(GTK_ENTRY(tcd
->channel_dir_entry
),"/mnt/relayfs/ltt");
247 gtk_widget_show (tcd
->channel_dir_entry
);
248 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->channel_dir_label
,0,2,2,3,GTK_FILL
,GTK_FILL
,2,2);
249 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->channel_dir_entry
,2,6,2,3,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
251 tcd
->trace_dir_label
= gtk_label_new("Trace directory:");
252 gtk_widget_show (tcd
->trace_dir_label
);
253 tcd
->trace_dir_entry
= gtk_entry_new();
254 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_dir_entry
),"/tmp/trace1");
255 gtk_widget_show (tcd
->trace_dir_entry
);
256 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_dir_label
,0,2,3,4,GTK_FILL
,GTK_FILL
,2,2);
257 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_dir_entry
,2,6,3,4,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
259 tcd
->trace_name_label
= gtk_label_new("Trace name:");
260 gtk_widget_show (tcd
->trace_name_label
);
261 tcd
->trace_name_entry
= gtk_entry_new();
262 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_name_entry
),"trace");
263 gtk_widget_show (tcd
->trace_name_entry
);
264 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_name_label
,0,2,4,5,GTK_FILL
,GTK_FILL
,2,2);
265 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_name_entry
,2,6,4,5,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
267 tcd
->trace_mode_label
= gtk_label_new("Trace mode ");
268 gtk_widget_show (tcd
->trace_mode_label
);
269 tcd
->trace_mode_combo
= gtk_combo_box_new_text();
270 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
272 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
274 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd
->trace_mode_combo
), 0);
275 gtk_widget_show (tcd
->trace_mode_combo
);
276 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_mode_label
,0,2,5,6,GTK_FILL
,GTK_FILL
,2,2);
277 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_mode_combo
,2,6,5,6,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
279 tcd
->start_daemon_label
= gtk_label_new("Start daemon ");
280 gtk_widget_show (tcd
->start_daemon_label
);
281 tcd
->start_daemon_check
= gtk_check_button_new();
282 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
), TRUE
);
283 gtk_widget_show (tcd
->start_daemon_check
);
284 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_label
,0,2,6,7,GTK_FILL
,GTK_FILL
,2,2);
285 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_check
,2,6,6,7,GTK_FILL
,GTK_FILL
,0,0);
287 tcd
->append_label
= gtk_label_new("Append to trace ");
288 gtk_widget_show (tcd
->append_label
);
289 tcd
->append_check
= gtk_check_button_new();
290 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->append_check
), FALSE
);
291 gtk_widget_show (tcd
->append_check
);
292 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_label
,0,2,7,8,GTK_FILL
,GTK_FILL
,2,2);
293 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_check
,2,6,7,8,GTK_FILL
,GTK_FILL
,0,0);
296 tcd
->optional_label
= gtk_label_new("Optional fields ");
297 gtk_widget_show (tcd
->optional_label
);
298 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->optional_label
,0,6,8,9,GTK_FILL
,GTK_FILL
,2,2);
300 tcd
->subbuf_size_label
= gtk_label_new("Subbuffer size:");
301 gtk_widget_show (tcd
->subbuf_size_label
);
302 tcd
->subbuf_size_entry
= gtk_entry_new();
303 gtk_widget_show (tcd
->subbuf_size_entry
);
304 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_size_label
,0,2,9,10,GTK_FILL
,GTK_FILL
,2,2);
305 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_size_entry
,2,6,9,10,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
307 tcd
->subbuf_num_label
= gtk_label_new("Number of subbuffers:");
308 gtk_widget_show (tcd
->subbuf_num_label
);
309 tcd
->subbuf_num_entry
= gtk_entry_new();
310 gtk_widget_show (tcd
->subbuf_num_entry
);
311 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_num_label
,0,2,10,11,GTK_FILL
,GTK_FILL
,2,2);
312 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_num_entry
,2,6,10,11,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
314 tcd
->lttd_threads_label
= gtk_label_new("Number of lttd threads:");
315 gtk_widget_show (tcd
->lttd_threads_label
);
316 tcd
->lttd_threads_entry
= gtk_entry_new();
317 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_threads_entry
), "1");
318 gtk_widget_show (tcd
->lttd_threads_entry
);
319 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_threads_label
,0,2,11,12,GTK_FILL
,GTK_FILL
,2,2);
320 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_threads_entry
,2,6,11,12,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
322 tcd
->lttctl_path_label
= gtk_label_new("path to lttctl:");
323 gtk_widget_show (tcd
->lttctl_path_label
);
324 tcd
->lttctl_path_entry
= gtk_entry_new();
325 gtk_entry_set_text(GTK_ENTRY(tcd
->lttctl_path_entry
),PACKAGE_BIN_DIR
"/lttctl");
326 gtk_widget_show (tcd
->lttctl_path_entry
);
327 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttctl_path_label
,0,2,12,13,GTK_FILL
,GTK_FILL
,2,2);
328 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttctl_path_entry
,2,6,12,13,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
331 tcd
->lttd_path_label
= gtk_label_new("path to lttd:");
332 gtk_widget_show (tcd
->lttd_path_label
);
333 tcd
->lttd_path_entry
= gtk_entry_new();
334 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_path_entry
),PACKAGE_BIN_DIR
"/lttd");
335 gtk_widget_show (tcd
->lttd_path_entry
);
336 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_path_label
,0,2,13,14,GTK_FILL
,GTK_FILL
,2,2);
337 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_path_entry
,2,6,13,14,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
340 tcd
->fac_path_label
= gtk_label_new("path to facilities:");
341 gtk_widget_show (tcd
->fac_path_label
);
342 tcd
->fac_path_entry
= gtk_entry_new();
343 gtk_entry_set_text(GTK_ENTRY(tcd
->fac_path_entry
),PACKAGE_DATA_DIR
"/" PACKAGE
"/facilities");
344 gtk_widget_set_size_request(tcd
->fac_path_entry
, 250, -1);
345 gtk_widget_show (tcd
->fac_path_entry
);
346 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->fac_path_label
,0,2,14,15,GTK_FILL
,GTK_FILL
,2,2);
347 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->fac_path_entry
,2,6,14,15,GTK_FILL
|GTK_EXPAND
|GTK_SHRINK
,GTK_FILL
,0,0);
349 focus_chain
= g_list_append (focus_chain
, tcd
->username_entry
);
350 focus_chain
= g_list_append (focus_chain
, tcd
->password_entry
);
351 focus_chain
= g_list_append (focus_chain
, tcd
->start_button
);
352 focus_chain
= g_list_append (focus_chain
, tcd
->pause_button
);
353 focus_chain
= g_list_append (focus_chain
, tcd
->unpause_button
);
354 focus_chain
= g_list_append (focus_chain
, tcd
->stop_button
);
355 focus_chain
= g_list_append (focus_chain
, tcd
->channel_dir_entry
);
356 focus_chain
= g_list_append (focus_chain
, tcd
->trace_dir_entry
);
357 focus_chain
= g_list_append (focus_chain
, tcd
->trace_name_entry
);
358 focus_chain
= g_list_append (focus_chain
, tcd
->trace_mode_combo
);
359 focus_chain
= g_list_append (focus_chain
, tcd
->start_daemon_check
);
360 focus_chain
= g_list_append (focus_chain
, tcd
->append_check
);
361 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_size_entry
);
362 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_num_entry
);
363 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_threads_entry
);
364 focus_chain
= g_list_append (focus_chain
, tcd
->lttctl_path_entry
);
365 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_path_entry
);
366 focus_chain
= g_list_append (focus_chain
, tcd
->fac_path_entry
);
368 gtk_container_set_focus_chain(GTK_CONTAINER(tcd
->main_box
), focus_chain
);
370 g_list_free(focus_chain
);
372 g_signal_connect(G_OBJECT(tcd
->start_button
), "clicked",
373 (GCallback
)start_clicked
, tcd
);
374 g_signal_connect(G_OBJECT(tcd
->pause_button
), "clicked",
375 (GCallback
)pause_clicked
, tcd
);
376 g_signal_connect(G_OBJECT(tcd
->unpause_button
), "clicked",
377 (GCallback
)unpause_clicked
, tcd
);
378 g_signal_connect(G_OBJECT(tcd
->stop_button
), "clicked",
379 (GCallback
)stop_clicked
, tcd
);
382 * show main container
384 gtk_widget_show(tcd
->main_box
);
385 gtk_widget_show(tcd
->window
);
388 g_object_set_data_full(
389 G_OBJECT(guicontrol_get_widget(tcd
)),
390 "control_viewer_data",
392 (GDestroyNotify
)gui_control_destructor
);
394 g_control_list
= g_slist_append(
403 * @fn void gui_control_destructor(ControlData*)
405 * Destructor for the filter gui module
406 * @param tcd The module structure
409 gui_control_destructor(ControlData
*tcd
)
413 /* May already been done by GTK window closing */
414 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
))){
415 g_info("widget still exists");
418 // lttvwindow_unregister_traceset_notify(tcd->tab,
419 // filter_traceset_changed,
420 // filter_viewer_data);
422 lttvwindowtraces_background_notify_remove(tcd
);
424 g_control_list
= g_slist_remove(g_control_list
, tcd
);
429 static int execute_command(const gchar
*command
, const gchar
*username
,
430 const gchar
*password
, const gchar
*lttd_path
, const gchar
*fac_path
)
434 pid
= forkpty(&fdpty
, NULL
, NULL
, NULL
);
442 /* discuss with su */
443 struct timeval timeout
;
447 struct pollfd pollfd
;
452 /* Read the output from the child terminal before the prompt. If no data in
453 * 200 ms, we stop reading to give the password */
454 g_info("Reading from child console...");
455 sleep(1); /* make sure the child is ready */
458 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
460 num_rdy
= poll(&pollfd
, 1, 200);
463 perror("Poll error");
468 /* Timeout : stop waiting for chars */
469 if(num_rdy
== 0) break;
471 switch(pollfd
.revents
) {
473 g_warning("Error returned in polling fd\n");
477 g_info("Polling FD : hung up.");
481 g_warning("Polling fd tells it is not open");
486 count
= read (fdpty
, buf
, 256);
490 } else if(count
== -1) {
491 perror("Error in read");
497 g_warning("Child hung up too fast");
502 /* Write the password */
503 g_info("Got su prompt, now writing password...");
505 ret
= write(fdpty
, password
, strlen(password
));
506 if(ret
< 0) perror("Error in write");
507 ret
= write(fdpty
, "\n", 1);
508 if(ret
< 0) perror("Error in write");
511 /* Take the output from the terminal and show it on the real console */
512 g_info("Getting data from child terminal...");
516 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
518 num_rdy
= poll(&pollfd
, 1, -1);
521 perror("Poll error");
525 if(num_rdy
== 0) break;
527 switch(pollfd
.revents
) {
529 g_warning("Error returned in polling fd\n");
533 g_info("Polling FD : hung up.");
537 g_warning("Polling fd tells it is not open");
542 count
= read (fdpty
, buf
, 256);
546 } else if(count
== -1) {
547 perror("Error in read");
552 if(num_hup
> 0) goto wait_child
;
555 g_info("Waiting for child exit...");
557 ret
= waitpid(pid
, &status
, 0);
560 g_warning("An error occured in wait : %s",
563 if(WIFEXITED(status
))
564 if(WEXITSTATUS(status
) != 0) {
565 retval
= WEXITSTATUS(status
);
566 g_warning("An error occured in the su command : %s",
571 g_info("Child exited.");
573 } else if(pid
== 0) {
574 /* Setup environment variables */
575 if(strcmp(lttd_path
, "") != 0)
576 setenv("LTT_DAEMON", lttd_path
, 1);
577 if(strcmp(fac_path
, "") != 0)
578 setenv("LTT_FACILITIES", fac_path
, 1);
580 g_message("Executing (as %s) : %s\n", username
, command
);
582 execlp("su", "su", "-p", "-c", command
, username
, NULL
);
583 exit(-1); /* not supposed to happen! */
585 //gint ret = execvp();
589 g_warning("Error happened when forking for su");
598 void start_clicked (GtkButton
*button
, gpointer user_data
)
600 ControlData
*tcd
= (ControlData
*)user_data
;
602 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
603 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
604 const gchar
*channel_dir
=
605 gtk_entry_get_text(GTK_ENTRY(tcd
->channel_dir_entry
));
606 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
607 const gchar
*trace_name
=
608 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
610 const gchar
*trace_mode_sel
;
613 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd
->trace_mode_combo
), &iter
);
615 gtk_combo_box_get_model(GTK_COMBO_BOX(tcd
->trace_mode_combo
)),
616 &iter
, 0, &trace_mode_sel
, -1);
617 //const gchar *trace_mode_sel =
618 //2.6+ gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
619 const gchar
*trace_mode
;
620 if(strcmp(trace_mode_sel
, "normal") == 0)
621 trace_mode
= "normal";
623 trace_mode
= "flight";
625 gboolean start_daemon
=
626 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
));
629 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->append_check
));
631 const gchar
*subbuf_size
=
632 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_size_entry
));
633 const gchar
*subbuf_num
=
634 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_num_entry
));
635 const gchar
*threads_num
=
636 gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_threads_entry
));
637 const gchar
*lttctl_path
=
638 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
639 const gchar
*lttd_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_path_entry
));
640 const gchar
*fac_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->fac_path_entry
));
643 /* Setup arguments to su */
645 gchar args
[MAX_ARGS_LEN
];
646 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
651 strncat(args
, "exec", args_left
);
652 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
655 strncat(args
, " ", args_left
);
656 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
658 if(strcmp(lttctl_path
, "") == 0)
659 strncat(args
, "lttctl", args_left
);
661 strncat(args
, lttctl_path
, args_left
);
662 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
665 strncat(args
, " ", args_left
);
666 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
669 strncat(args
, "-l ", args_left
);
670 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
671 strncat(args
, channel_dir
, args_left
);
672 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
675 strncat(args
, " ", args_left
);
676 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
679 strncat(args
, "-t ", args_left
);
680 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
681 strncat(args
, trace_dir
, args_left
);
682 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
685 strncat(args
, " ", args_left
);
686 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
689 strncat(args
, "-n ", args_left
);
690 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
691 strncat(args
, trace_name
, args_left
);
692 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
695 strncat(args
, " ", args_left
);
696 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
699 strncat(args
, "-m ", args_left
);
700 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
701 strncat(args
, trace_mode
, args_left
);
702 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
705 strncat(args
, " ", args_left
);
706 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
710 strncat(args
, "-d", args_left
);
711 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
713 /* Simply create the channel and then start tracing */
714 strncat(args
, "-b", args_left
);
715 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
719 /* Append to trace ? */
722 strncat(args
, " ", args_left
);
723 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
724 strncat(args
, "-a", args_left
);
725 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
728 /* optional arguments */
730 if(strcmp(subbuf_size
, "") != 0) {
732 strncat(args
, " ", args_left
);
733 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
735 strncat(args
, "-z ", args_left
);
736 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
737 strncat(args
, subbuf_size
, args_left
);
738 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
741 /* number of subbuffers */
742 if(strcmp(subbuf_num
, "") != 0) {
744 strncat(args
, " ", args_left
);
745 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
747 strncat(args
, "-x ", args_left
);
748 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
749 strncat(args
, subbuf_num
, args_left
);
750 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
753 /* number of lttd threads */
754 if(strcmp(threads_num
, "") != 0) {
756 strncat(args
, " ", args_left
);
757 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
759 strncat(args
, "-N ", args_left
);
760 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
761 strncat(args
, threads_num
, args_left
);
762 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
766 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
770 guint msg_left
= 256;
772 strcpy(msg
, "A problem occured when executing the su command : ");
773 msg_left
= 256 - strlen(msg
) - 1;
774 strncat(msg
, strerror(retval
), msg_left
);
775 GtkWidget
*dialogue
=
776 gtk_message_dialog_new(
777 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
778 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
782 gtk_dialog_run(GTK_DIALOG(dialogue
));
783 gtk_widget_destroy(dialogue
);
789 void pause_clicked (GtkButton
*button
, gpointer user_data
)
791 ControlData
*tcd
= (ControlData
*)user_data
;
793 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
794 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
795 const gchar
*trace_name
=
796 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
797 const gchar
*lttd_path
= "";
798 const gchar
*fac_path
= "";
800 const gchar
*lttctl_path
=
801 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
803 /* Setup arguments to su */
805 gchar args
[MAX_ARGS_LEN
];
806 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
811 strncat(args
, "exec", args_left
);
812 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
815 strncat(args
, " ", args_left
);
816 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
818 if(strcmp(lttctl_path
, "") == 0)
819 strncat(args
, "lttctl", args_left
);
821 strncat(args
, lttctl_path
, args_left
);
822 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
825 strncat(args
, " ", args_left
);
826 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
829 strncat(args
, "-n ", args_left
);
830 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
831 strncat(args
, trace_name
, args_left
);
832 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
835 strncat(args
, " ", args_left
);
836 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
838 /* Simply pause tracing */
839 strncat(args
, "-q", args_left
);
840 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
842 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
845 guint msg_left
= 256;
847 strcpy(msg
, "A problem occured when executing the su command : ");
848 msg_left
= 256 - strlen(msg
) - 1;
849 strncat(msg
, strerror(retval
), msg_left
);
850 GtkWidget
*dialogue
=
851 gtk_message_dialog_new(
852 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
853 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
857 gtk_dialog_run(GTK_DIALOG(dialogue
));
858 gtk_widget_destroy(dialogue
);
863 void unpause_clicked (GtkButton
*button
, gpointer user_data
)
865 ControlData
*tcd
= (ControlData
*)user_data
;
867 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
868 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
869 const gchar
*trace_name
=
870 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
871 const gchar
*lttd_path
= "";
872 const gchar
*fac_path
= "";
874 const gchar
*lttctl_path
=
875 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
877 /* Setup arguments to su */
879 gchar args
[MAX_ARGS_LEN
];
880 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
885 strncat(args
, "exec", args_left
);
886 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
889 strncat(args
, " ", args_left
);
890 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
892 if(strcmp(lttctl_path
, "") == 0)
893 strncat(args
, "lttctl", args_left
);
895 strncat(args
, lttctl_path
, args_left
);
896 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
899 strncat(args
, " ", args_left
);
900 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
903 strncat(args
, "-n ", args_left
);
904 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
905 strncat(args
, trace_name
, args_left
);
906 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
909 strncat(args
, " ", args_left
);
910 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
912 /* Simply unpause tracing */
913 strncat(args
, "-s", args_left
);
914 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
916 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
919 guint msg_left
= 256;
921 strcpy(msg
, "A problem occured when executing the su command : ");
922 msg_left
= 256 - strlen(msg
) - 1;
923 strncat(msg
, strerror(retval
), msg_left
);
924 GtkWidget
*dialogue
=
925 gtk_message_dialog_new(
926 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
927 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
931 gtk_dialog_run(GTK_DIALOG(dialogue
));
932 gtk_widget_destroy(dialogue
);
937 void stop_clicked (GtkButton
*button
, gpointer user_data
)
939 ControlData
*tcd
= (ControlData
*)user_data
;
941 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
942 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
943 const gchar
*trace_name
=
944 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
945 const gchar
*lttd_path
= "";
946 const gchar
*fac_path
= "";
948 const gchar
*lttctl_path
=
949 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
950 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
952 /* Setup arguments to su */
954 gchar args
[MAX_ARGS_LEN
];
955 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
960 strncat(args
, "exec", args_left
);
961 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
964 strncat(args
, " ", args_left
);
965 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
967 if(strcmp(lttctl_path
, "") == 0)
968 strncat(args
, "lttctl", args_left
);
970 strncat(args
, lttctl_path
, args_left
);
971 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
974 strncat(args
, " ", args_left
);
975 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
978 strncat(args
, "-n ", args_left
);
979 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
980 strncat(args
, trace_name
, args_left
);
981 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
984 strncat(args
, " ", args_left
);
985 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
987 /* Simply stop tracing and destroy channel */
988 strncat(args
, "-R", args_left
);
989 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
991 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
994 guint msg_left
= 256;
996 strcpy(msg
, "A problem occured when executing the su command : ");
997 msg_left
= 256 - strlen(msg
) - 1;
998 strncat(msg
, strerror(retval
), msg_left
);
999 GtkWidget
*dialogue
=
1000 gtk_message_dialog_new(
1001 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1002 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1006 gtk_dialog_run(GTK_DIALOG(dialogue
));
1007 gtk_widget_destroy(dialogue
);
1012 /* Ask to the user if he wants to open the trace in a new window */
1013 GtkWidget
*dialogue
;
1017 dialogue
= gtk_dialog_new_with_buttons("Open trace ?",
1018 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1019 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1020 GTK_STOCK_YES
,GTK_RESPONSE_ACCEPT
,
1021 GTK_STOCK_NO
,GTK_RESPONSE_REJECT
,
1023 label
= gtk_label_new("Do you want to open the trace in LTTV ?");
1024 gtk_widget_show(label
);
1026 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue
)->vbox
),
1029 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
1032 case GTK_RESPONSE_ACCEPT
:
1034 create_main_window_with_trace(trace_dir
);
1037 case GTK_RESPONSE_REJECT
:
1041 gtk_widget_destroy(dialogue
);
1047 * @fn GtkWidget* h_guicontrol(Tab*)
1049 * Control Module's constructor hook
1051 * This constructor is given as a parameter to the menuitem and toolbar button
1052 * registration. It creates the list.
1053 * @param tab A pointer to the parent window.
1054 * @return The widget created.
1057 h_guicontrol(Tab
*tab
)
1059 ControlData
* f
= gui_control(tab
) ;
1065 * @fn static void init()
1067 * This function initializes the Filter Viewer functionnality through the
1070 static void init() {
1072 lttvwindow_register_constructor("guicontrol",
1074 "Insert Tracing Control Module",
1075 hTraceControlInsert_xpm
,
1076 "Insert Tracing Control Module",
1081 * @fn void control_destroy_walk(gpointer,gpointer)
1083 * Initiate the destruction of the current gui module
1084 * on the GTK Interface
1087 control_destroy_walk(gpointer data
, gpointer user_data
)
1089 ControlData
*tcd
= (ControlData
*)data
;
1091 g_debug("traceontrol.c : control_destroy_walk, %p", tcd
);
1093 /* May already have been done by GTK window closing */
1094 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
)))
1095 gtk_widget_destroy(guicontrol_get_widget(tcd
));
1099 * @fn static void destroy()
1100 * @brief plugin's destroy function
1102 * This function releases the memory reserved by the module and unregisters
1103 * everything that has been registered in the gtkTraceSet API.
1105 static void destroy() {
1107 g_slist_foreach(g_control_list
, control_destroy_walk
, NULL
);
1109 lttvwindow_unregister_constructor(h_guicontrol
);
1114 LTTV_MODULE("guitracecontrol", "Trace Control Window", \
1115 "Graphical module that let user control kernel tracing", \
1116 init
, destroy
, "lttvwindow")