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>
52 #define MAX_ARGS_LEN PATH_MAX * 10
54 GSList
*g_control_list
= NULL
;
56 /*! \file lttv/modules/gui/tracecontrol/tracecontrol.c
57 * \brief Graphic trace start/stop control interface.
59 * This plugin interacts with lttctl to start/stop tracing. It needs to take the
60 * root password to be able to interact with lttctl.
64 typedef struct _ControlData ControlData
;
69 GtkWidget
*guicontrol_get_widget(ControlData
*tcd
);
70 ControlData
*gui_control(Tab
*tab
);
71 void gui_control_destructor(ControlData
*tcd
);
72 GtkWidget
* h_guicontrol(Tab
*tab
);
73 void control_destroy_walk(gpointer data
, gpointer user_data
);
79 static void start_clicked (GtkButton
*button
, gpointer user_data
);
80 static void pause_clicked (GtkButton
*button
, gpointer user_data
);
81 static void unpause_clicked (GtkButton
*button
, gpointer user_data
);
82 static void stop_clicked (GtkButton
*button
, gpointer user_data
);
86 * @struct _ControlData
88 * @brief Main structure of gui control
91 Tab
*tab
; /**< current tab of module */
93 GtkWidget
*window
; /**< window */
95 GtkWidget
*main_box
; /**< main container */
96 GtkWidget
*start_button
;
97 GtkWidget
*pause_button
;
98 GtkWidget
*unpause_button
;
99 GtkWidget
*stop_button
;
100 GtkWidget
*username_label
;
101 GtkWidget
*username_entry
;
102 GtkWidget
*password_label
;
103 GtkWidget
*password_entry
;
104 GtkWidget
*channel_dir_label
;
105 GtkWidget
*channel_dir_entry
;
106 GtkWidget
*trace_dir_label
;
107 GtkWidget
*trace_dir_entry
;
108 GtkWidget
*trace_name_label
;
109 GtkWidget
*trace_name_entry
;
110 GtkWidget
*trace_mode_label
;
111 GtkWidget
*trace_mode_combo
;
112 GtkWidget
*start_daemon_label
;
113 GtkWidget
*start_daemon_check
;
114 GtkWidget
*append_label
;
115 GtkWidget
*append_check
;
116 GtkWidget
*optional_label
;
117 GtkWidget
*subbuf_size_label
;
118 GtkWidget
*subbuf_size_entry
;
119 GtkWidget
*subbuf_num_label
;
120 GtkWidget
*subbuf_num_entry
;
121 GtkWidget
*lttd_threads_label
;
122 GtkWidget
*lttd_threads_entry
;
123 GtkWidget
*lttctl_path_label
;
124 GtkWidget
*lttctl_path_entry
;
125 GtkWidget
*lttd_path_label
;
126 GtkWidget
*lttd_path_entry
;
127 GtkWidget
*fac_path_label
;
128 GtkWidget
*fac_path_entry
;
132 * @fn GtkWidget* guicontrol_get_widget(ControlData*)
134 * This function returns the current main widget
135 * used by this module
136 * @param tcd the module struct
137 * @return The main widget
140 guicontrol_get_widget(ControlData
*tcd
)
146 * @fn ControlData* gui_control(Tab*)
148 * Constructor is used to create ControlData data structure.
149 * @param tab The tab structure used by the widget
150 * @return The Filter viewer data created.
153 gui_control(Tab
*tab
)
155 g_debug("filter::gui_control()");
158 GtkCellRenderer
*renderer
;
159 GtkTreeViewColumn
*column
;
161 ControlData
* tcd
= g_new(ControlData
,1);
165 tcd
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
166 gtk_window_set_title(GTK_WINDOW(tcd
->window
), "LTTng Trace Control");
168 * Initiating GtkTable layout
169 * starts with 2 rows and 5 columns and
170 * expands when expressions added
172 tcd
->main_box
= gtk_table_new(14,7,FALSE
);
173 gtk_table_set_row_spacings(GTK_TABLE(tcd
->main_box
),5);
174 gtk_table_set_col_spacings(GTK_TABLE(tcd
->main_box
),5);
176 gtk_container_add(GTK_CONTAINER(tcd
->window
), GTK_WIDGET(tcd
->main_box
));
178 GList
*focus_chain
= NULL
;
181 * start/pause/stop buttons
185 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStart_xpm
);
186 image
= gtk_image_new_from_pixbuf(pixbuf
);
187 tcd
->start_button
= gtk_button_new_with_label("start");
188 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->start_button), image);
189 g_object_set(G_OBJECT(tcd
->start_button
), "image", image
, NULL
);
190 gtk_button_set_alignment(GTK_BUTTON(tcd
->start_button
), 0.0, 0.0);
191 gtk_widget_show (tcd
->start_button
);
192 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_button
,6,7,0,1,GTK_FILL
,GTK_FILL
,2,2);
194 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
195 image
= gtk_image_new_from_pixbuf(pixbuf
);
196 tcd
->pause_button
= gtk_button_new_with_label("pause");
197 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->pause_button), image);
198 g_object_set(G_OBJECT(tcd
->pause_button
), "image", image
, NULL
);
199 gtk_button_set_alignment(GTK_BUTTON(tcd
->pause_button
), 0.0, 0.0);
200 gtk_widget_show (tcd
->pause_button
);
201 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->pause_button
,6,7,1,2,GTK_FILL
,GTK_FILL
,2,2);
203 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
204 image
= gtk_image_new_from_pixbuf(pixbuf
);
205 tcd
->unpause_button
= gtk_button_new_with_label("unpause");
206 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->unpause_button), image);
207 g_object_set(G_OBJECT(tcd
->unpause_button
), "image", image
, NULL
);
208 gtk_button_set_alignment(GTK_BUTTON(tcd
->unpause_button
), 0.0, 0.0);
209 gtk_widget_show (tcd
->unpause_button
);
210 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->unpause_button
,6,7,2,3,GTK_FILL
,GTK_FILL
,2,2);
212 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStop_xpm
);
213 image
= gtk_image_new_from_pixbuf(pixbuf
);
214 tcd
->stop_button
= gtk_button_new_with_label("stop");
215 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->stop_button), image);
216 g_object_set(G_OBJECT(tcd
->stop_button
), "image", image
, NULL
);
217 gtk_button_set_alignment(GTK_BUTTON(tcd
->stop_button
), 0.0, 0.0);
218 gtk_widget_show (tcd
->stop_button
);
219 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->stop_button
,6,7,3,4,GTK_FILL
,GTK_FILL
,2,2);
222 * First half of the filter window
223 * - textual entry of filter expression
224 * - processing button
226 tcd
->username_label
= gtk_label_new("Username:");
227 gtk_widget_show (tcd
->username_label
);
228 tcd
->username_entry
= gtk_entry_new();
229 gtk_entry_set_text(GTK_ENTRY(tcd
->username_entry
),"root");
230 gtk_widget_show (tcd
->username_entry
);
231 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->username_label
,0,2,0,1,GTK_FILL
,GTK_FILL
,2,2);
232 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);
236 tcd
->password_label
= gtk_label_new("Password:");
237 gtk_widget_show (tcd
->password_label
);
238 tcd
->password_entry
= gtk_entry_new();
239 gtk_entry_set_visibility(GTK_ENTRY(tcd
->password_entry
), FALSE
);
240 gtk_widget_show (tcd
->password_entry
);
241 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->password_label
,0,2,1,2,GTK_FILL
,GTK_FILL
,2,2);
242 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);
245 tcd
->channel_dir_label
= gtk_label_new("Channel directory:");
246 gtk_widget_show (tcd
->channel_dir_label
);
247 tcd
->channel_dir_entry
= gtk_entry_new();
248 gtk_entry_set_text(GTK_ENTRY(tcd
->channel_dir_entry
),"/mnt/relayfs/ltt");
249 gtk_widget_show (tcd
->channel_dir_entry
);
250 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->channel_dir_label
,0,2,2,3,GTK_FILL
,GTK_FILL
,2,2);
251 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);
253 tcd
->trace_dir_label
= gtk_label_new("Trace directory:");
254 gtk_widget_show (tcd
->trace_dir_label
);
255 tcd
->trace_dir_entry
= gtk_entry_new();
256 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_dir_entry
),"/tmp/trace1");
257 gtk_widget_show (tcd
->trace_dir_entry
);
258 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_dir_label
,0,2,3,4,GTK_FILL
,GTK_FILL
,2,2);
259 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);
261 tcd
->trace_name_label
= gtk_label_new("Trace name:");
262 gtk_widget_show (tcd
->trace_name_label
);
263 tcd
->trace_name_entry
= gtk_entry_new();
264 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_name_entry
),"trace");
265 gtk_widget_show (tcd
->trace_name_entry
);
266 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_name_label
,0,2,4,5,GTK_FILL
,GTK_FILL
,2,2);
267 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);
269 tcd
->trace_mode_label
= gtk_label_new("Trace mode ");
270 gtk_widget_show (tcd
->trace_mode_label
);
271 tcd
->trace_mode_combo
= gtk_combo_box_new_text();
272 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
274 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
276 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd
->trace_mode_combo
), 0);
277 gtk_widget_show (tcd
->trace_mode_combo
);
278 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_mode_label
,0,2,5,6,GTK_FILL
,GTK_FILL
,2,2);
279 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);
281 tcd
->start_daemon_label
= gtk_label_new("Start daemon ");
282 gtk_widget_show (tcd
->start_daemon_label
);
283 tcd
->start_daemon_check
= gtk_check_button_new();
284 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
), TRUE
);
285 gtk_widget_show (tcd
->start_daemon_check
);
286 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_label
,0,2,6,7,GTK_FILL
,GTK_FILL
,2,2);
287 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_check
,2,6,6,7,GTK_FILL
,GTK_FILL
,0,0);
289 tcd
->append_label
= gtk_label_new("Append to trace ");
290 gtk_widget_show (tcd
->append_label
);
291 tcd
->append_check
= gtk_check_button_new();
292 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->append_check
), FALSE
);
293 gtk_widget_show (tcd
->append_check
);
294 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_label
,0,2,7,8,GTK_FILL
,GTK_FILL
,2,2);
295 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_check
,2,6,7,8,GTK_FILL
,GTK_FILL
,0,0);
298 tcd
->optional_label
= gtk_label_new("Optional fields ");
299 gtk_widget_show (tcd
->optional_label
);
300 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->optional_label
,0,6,8,9,GTK_FILL
,GTK_FILL
,2,2);
302 tcd
->subbuf_size_label
= gtk_label_new("Subbuffer size:");
303 gtk_widget_show (tcd
->subbuf_size_label
);
304 tcd
->subbuf_size_entry
= gtk_entry_new();
305 gtk_widget_show (tcd
->subbuf_size_entry
);
306 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_size_label
,0,2,9,10,GTK_FILL
,GTK_FILL
,2,2);
307 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);
309 tcd
->subbuf_num_label
= gtk_label_new("Number of subbuffers:");
310 gtk_widget_show (tcd
->subbuf_num_label
);
311 tcd
->subbuf_num_entry
= gtk_entry_new();
312 gtk_widget_show (tcd
->subbuf_num_entry
);
313 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_num_label
,0,2,10,11,GTK_FILL
,GTK_FILL
,2,2);
314 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);
316 tcd
->lttd_threads_label
= gtk_label_new("Number of lttd threads:");
317 gtk_widget_show (tcd
->lttd_threads_label
);
318 tcd
->lttd_threads_entry
= gtk_entry_new();
319 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_threads_entry
), "1");
320 gtk_widget_show (tcd
->lttd_threads_entry
);
321 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_threads_label
,0,2,11,12,GTK_FILL
,GTK_FILL
,2,2);
322 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);
324 tcd
->lttctl_path_label
= gtk_label_new("path to lttctl:");
325 gtk_widget_show (tcd
->lttctl_path_label
);
326 tcd
->lttctl_path_entry
= gtk_entry_new();
327 gtk_entry_set_text(GTK_ENTRY(tcd
->lttctl_path_entry
),PACKAGE_BIN_DIR
"/lttctl");
328 gtk_widget_show (tcd
->lttctl_path_entry
);
329 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttctl_path_label
,0,2,12,13,GTK_FILL
,GTK_FILL
,2,2);
330 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);
333 tcd
->lttd_path_label
= gtk_label_new("path to lttd:");
334 gtk_widget_show (tcd
->lttd_path_label
);
335 tcd
->lttd_path_entry
= gtk_entry_new();
336 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_path_entry
),PACKAGE_BIN_DIR
"/lttd");
337 gtk_widget_show (tcd
->lttd_path_entry
);
338 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_path_label
,0,2,13,14,GTK_FILL
,GTK_FILL
,2,2);
339 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);
342 tcd
->fac_path_label
= gtk_label_new("path to facilities:");
343 gtk_widget_show (tcd
->fac_path_label
);
344 tcd
->fac_path_entry
= gtk_entry_new();
345 gtk_entry_set_text(GTK_ENTRY(tcd
->fac_path_entry
),PACKAGE_DATA_DIR
"/" "ltt-control" "/facilities");
346 gtk_widget_set_size_request(tcd
->fac_path_entry
, 250, -1);
347 gtk_widget_show (tcd
->fac_path_entry
);
348 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->fac_path_label
,0,2,14,15,GTK_FILL
,GTK_FILL
,2,2);
349 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);
351 focus_chain
= g_list_append (focus_chain
, tcd
->username_entry
);
352 focus_chain
= g_list_append (focus_chain
, tcd
->password_entry
);
353 focus_chain
= g_list_append (focus_chain
, tcd
->start_button
);
354 focus_chain
= g_list_append (focus_chain
, tcd
->pause_button
);
355 focus_chain
= g_list_append (focus_chain
, tcd
->unpause_button
);
356 focus_chain
= g_list_append (focus_chain
, tcd
->stop_button
);
357 focus_chain
= g_list_append (focus_chain
, tcd
->channel_dir_entry
);
358 focus_chain
= g_list_append (focus_chain
, tcd
->trace_dir_entry
);
359 focus_chain
= g_list_append (focus_chain
, tcd
->trace_name_entry
);
360 focus_chain
= g_list_append (focus_chain
, tcd
->trace_mode_combo
);
361 focus_chain
= g_list_append (focus_chain
, tcd
->start_daemon_check
);
362 focus_chain
= g_list_append (focus_chain
, tcd
->append_check
);
363 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_size_entry
);
364 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_num_entry
);
365 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_threads_entry
);
366 focus_chain
= g_list_append (focus_chain
, tcd
->lttctl_path_entry
);
367 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_path_entry
);
368 focus_chain
= g_list_append (focus_chain
, tcd
->fac_path_entry
);
370 gtk_container_set_focus_chain(GTK_CONTAINER(tcd
->main_box
), focus_chain
);
372 g_list_free(focus_chain
);
374 g_signal_connect(G_OBJECT(tcd
->start_button
), "clicked",
375 (GCallback
)start_clicked
, tcd
);
376 g_signal_connect(G_OBJECT(tcd
->pause_button
), "clicked",
377 (GCallback
)pause_clicked
, tcd
);
378 g_signal_connect(G_OBJECT(tcd
->unpause_button
), "clicked",
379 (GCallback
)unpause_clicked
, tcd
);
380 g_signal_connect(G_OBJECT(tcd
->stop_button
), "clicked",
381 (GCallback
)stop_clicked
, tcd
);
384 * show main container
386 gtk_widget_show(tcd
->main_box
);
387 gtk_widget_show(tcd
->window
);
390 g_object_set_data_full(
391 G_OBJECT(guicontrol_get_widget(tcd
)),
392 "control_viewer_data",
394 (GDestroyNotify
)gui_control_destructor
);
396 g_control_list
= g_slist_append(
405 * @fn void gui_control_destructor(ControlData*)
407 * Destructor for the filter gui module
408 * @param tcd The module structure
411 gui_control_destructor(ControlData
*tcd
)
415 /* May already been done by GTK window closing */
416 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
))){
417 g_info("widget still exists");
420 // lttvwindow_unregister_traceset_notify(tcd->tab,
421 // filter_traceset_changed,
422 // filter_viewer_data);
424 lttvwindowtraces_background_notify_remove(tcd
);
426 g_control_list
= g_slist_remove(g_control_list
, tcd
);
431 static int execute_command(const gchar
*command
, const gchar
*username
,
432 const gchar
*password
, const gchar
*lttd_path
, const gchar
*fac_path
)
436 pid
= forkpty(&fdpty
, NULL
, NULL
, NULL
);
444 /* discuss with su */
445 struct timeval timeout
;
449 struct pollfd pollfd
;
452 enum read_state
{ GET_LINE
, GET_SEMI
, GET_SPACE
} read_state
= GET_LINE
;
454 retval
= fcntl(fdpty
, F_SETFL
, O_WRONLY
);
456 perror("Error in fcntl");
460 /* Read the output from the child terminal before the prompt. If no data in
461 * 200 ms, we stop reading to give the password */
462 g_info("Reading from child console...");
465 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
467 num_rdy
= poll(&pollfd
, 1, -1);
469 perror("Poll error");
473 /* Timeout : Stop waiting for chars */
474 if(num_rdy
== 0) goto wait_child
;
476 switch(pollfd
.revents
) {
478 g_warning("Error returned in polling fd\n");
482 g_info("Polling FD : hung up.");
486 g_warning("Polling fd tells it is not open");
491 count
= read (fdpty
, buf
, 256);
496 for(i
=0; i
<count
; i
++) {
500 read_state
= GET_SEMI
;
501 g_debug("Tracecontrol input line skip\n");
506 g_debug("Tracecontrol input : marker found\n");
507 read_state
= GET_SPACE
;
512 g_debug("Tracecontrol input space marker found\n");
518 } else if(count
== -1) {
519 perror("Error in read");
525 g_warning("Child hung up too fast");
532 pollfd
.events
= POLLOUT
|POLLERR
|POLLHUP
|POLLNVAL
;
534 num_rdy
= poll(&pollfd
, 1, -1);
536 perror("Poll error");
540 /* Write the password */
541 g_info("Got su prompt, now writing password...");
544 ret
= write(fdpty
, password
, strlen(password
));
545 if(ret
< 0) perror("Error in write");
546 ret
= write(fdpty
, "\n", 1);
547 if(ret
< 0) perror("Error in write");
549 /* Take the output from the terminal and show it on the real console */
550 g_info("Getting data from child terminal...");
554 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
556 num_rdy
= poll(&pollfd
, 1, -1);
558 perror("Poll error");
561 if(num_rdy
== 0) break;
563 if(pollfd
.revents
& (POLLERR
|POLLNVAL
)) {
564 g_warning("Error returned in polling fd\n");
568 if(pollfd
.revents
& (POLLIN
|POLLPRI
) ) {
569 count
= read (fdpty
, buf
, 256);
573 } else if(count
== -1) {
574 perror("Error in read");
579 if(pollfd
.revents
& POLLHUP
) {
580 g_info("Polling FD : hung up.");
584 if(num_hup
> 0) goto wait_child
;
587 g_info("Waiting for child exit...");
589 ret
= waitpid(pid
, &status
, 0);
592 g_warning("An error occured in wait : %s",
595 if(WIFEXITED(status
))
596 if(WEXITSTATUS(status
) != 0) {
597 retval
= WEXITSTATUS(status
);
598 g_warning("An error occured in the su command : %s",
603 g_info("Child exited.");
605 } else if(pid
== 0) {
606 /* Setup environment variables */
607 if(strcmp(lttd_path
, "") != 0)
608 setenv("LTT_DAEMON", lttd_path
, 1);
609 if(strcmp(fac_path
, "") != 0)
610 setenv("LTT_FACILITIES", fac_path
, 1);
612 /* One comment line (must be only one) */
613 g_printf("Executing (as %s) : %s\n", username
, command
);
615 execlp("su", "su", "-p", "-c", command
, username
, NULL
);
616 exit(-1); /* not supposed to happen! */
618 //gint ret = execvp();
622 g_warning("Error happened when forking for su");
631 void start_clicked (GtkButton
*button
, gpointer user_data
)
633 ControlData
*tcd
= (ControlData
*)user_data
;
635 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
636 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
637 const gchar
*channel_dir
=
638 gtk_entry_get_text(GTK_ENTRY(tcd
->channel_dir_entry
));
639 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
640 const gchar
*trace_name
=
641 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
643 const gchar
*trace_mode_sel
;
646 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd
->trace_mode_combo
), &iter
);
648 gtk_combo_box_get_model(GTK_COMBO_BOX(tcd
->trace_mode_combo
)),
649 &iter
, 0, &trace_mode_sel
, -1);
650 //const gchar *trace_mode_sel =
651 //2.6+ gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
652 const gchar
*trace_mode
;
653 if(strcmp(trace_mode_sel
, "normal") == 0)
654 trace_mode
= "normal";
656 trace_mode
= "flight";
658 gboolean start_daemon
=
659 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
));
662 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->append_check
));
664 const gchar
*subbuf_size
=
665 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_size_entry
));
666 const gchar
*subbuf_num
=
667 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_num_entry
));
668 const gchar
*threads_num
=
669 gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_threads_entry
));
670 const gchar
*lttctl_path
=
671 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
672 const gchar
*lttd_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_path_entry
));
673 const gchar
*fac_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->fac_path_entry
));
676 /* Setup arguments to su */
678 gchar args
[MAX_ARGS_LEN
];
679 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
684 strncat(args
, "exec", args_left
);
685 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
688 strncat(args
, " ", args_left
);
689 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
691 if(strcmp(lttctl_path
, "") == 0)
692 strncat(args
, "lttctl", args_left
);
694 strncat(args
, lttctl_path
, args_left
);
695 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
698 strncat(args
, " ", args_left
);
699 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
702 strncat(args
, "-l ", args_left
);
703 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
704 strncat(args
, channel_dir
, args_left
);
705 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
708 strncat(args
, " ", args_left
);
709 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
712 strncat(args
, "-t ", args_left
);
713 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
714 strncat(args
, trace_dir
, args_left
);
715 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
718 strncat(args
, " ", args_left
);
719 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
722 strncat(args
, "-n ", args_left
);
723 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
724 strncat(args
, trace_name
, args_left
);
725 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
728 strncat(args
, " ", args_left
);
729 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
732 strncat(args
, "-m ", args_left
);
733 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
734 strncat(args
, trace_mode
, args_left
);
735 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
738 strncat(args
, " ", args_left
);
739 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
743 strncat(args
, "-d", args_left
);
744 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
746 /* Simply create the channel and then start tracing */
747 strncat(args
, "-b", args_left
);
748 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
752 /* Append to trace ? */
755 strncat(args
, " ", args_left
);
756 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
757 strncat(args
, "-a", args_left
);
758 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
761 /* optional arguments */
763 if(strcmp(subbuf_size
, "") != 0) {
765 strncat(args
, " ", args_left
);
766 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
768 strncat(args
, "-z ", args_left
);
769 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
770 strncat(args
, subbuf_size
, args_left
);
771 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
774 /* number of subbuffers */
775 if(strcmp(subbuf_num
, "") != 0) {
777 strncat(args
, " ", args_left
);
778 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
780 strncat(args
, "-x ", args_left
);
781 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
782 strncat(args
, subbuf_num
, args_left
);
783 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
786 /* number of lttd threads */
787 if(strcmp(threads_num
, "") != 0) {
789 strncat(args
, " ", args_left
);
790 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
792 strncat(args
, "-N ", args_left
);
793 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
794 strncat(args
, threads_num
, args_left
);
795 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
799 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
803 guint msg_left
= 256;
805 strcpy(msg
, "A problem occured when executing the su command : ");
806 msg_left
= 256 - strlen(msg
) - 1;
807 strncat(msg
, strerror(retval
), msg_left
);
808 GtkWidget
*dialogue
=
809 gtk_message_dialog_new(
810 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
811 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
815 gtk_dialog_run(GTK_DIALOG(dialogue
));
816 gtk_widget_destroy(dialogue
);
822 void pause_clicked (GtkButton
*button
, gpointer user_data
)
824 ControlData
*tcd
= (ControlData
*)user_data
;
826 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
827 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
828 const gchar
*trace_name
=
829 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
830 const gchar
*lttd_path
= "";
831 const gchar
*fac_path
= "";
833 const gchar
*lttctl_path
=
834 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
836 /* Setup arguments to su */
838 gchar args
[MAX_ARGS_LEN
];
839 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
844 strncat(args
, "exec", args_left
);
845 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
848 strncat(args
, " ", args_left
);
849 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
851 if(strcmp(lttctl_path
, "") == 0)
852 strncat(args
, "lttctl", args_left
);
854 strncat(args
, lttctl_path
, args_left
);
855 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
858 strncat(args
, " ", args_left
);
859 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
862 strncat(args
, "-n ", args_left
);
863 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
864 strncat(args
, trace_name
, args_left
);
865 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
868 strncat(args
, " ", args_left
);
869 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
871 /* Simply pause tracing */
872 strncat(args
, "-q", args_left
);
873 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
875 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
878 guint msg_left
= 256;
880 strcpy(msg
, "A problem occured when executing the su command : ");
881 msg_left
= 256 - strlen(msg
) - 1;
882 strncat(msg
, strerror(retval
), msg_left
);
883 GtkWidget
*dialogue
=
884 gtk_message_dialog_new(
885 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
886 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
890 gtk_dialog_run(GTK_DIALOG(dialogue
));
891 gtk_widget_destroy(dialogue
);
896 void unpause_clicked (GtkButton
*button
, gpointer user_data
)
898 ControlData
*tcd
= (ControlData
*)user_data
;
900 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
901 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
902 const gchar
*trace_name
=
903 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
904 const gchar
*lttd_path
= "";
905 const gchar
*fac_path
= "";
907 const gchar
*lttctl_path
=
908 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
910 /* Setup arguments to su */
912 gchar args
[MAX_ARGS_LEN
];
913 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
918 strncat(args
, "exec", args_left
);
919 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
922 strncat(args
, " ", args_left
);
923 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
925 if(strcmp(lttctl_path
, "") == 0)
926 strncat(args
, "lttctl", args_left
);
928 strncat(args
, lttctl_path
, args_left
);
929 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
932 strncat(args
, " ", args_left
);
933 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
936 strncat(args
, "-n ", args_left
);
937 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
938 strncat(args
, trace_name
, args_left
);
939 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
942 strncat(args
, " ", args_left
);
943 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
945 /* Simply unpause tracing */
946 strncat(args
, "-s", args_left
);
947 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
949 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
952 guint msg_left
= 256;
954 strcpy(msg
, "A problem occured when executing the su command : ");
955 msg_left
= 256 - strlen(msg
) - 1;
956 strncat(msg
, strerror(retval
), msg_left
);
957 GtkWidget
*dialogue
=
958 gtk_message_dialog_new(
959 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
960 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
964 gtk_dialog_run(GTK_DIALOG(dialogue
));
965 gtk_widget_destroy(dialogue
);
970 void stop_clicked (GtkButton
*button
, gpointer user_data
)
972 ControlData
*tcd
= (ControlData
*)user_data
;
974 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
975 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
976 const gchar
*trace_name
=
977 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
978 const gchar
*lttd_path
= "";
979 const gchar
*fac_path
= "";
981 const gchar
*lttctl_path
=
982 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
983 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
985 /* Setup arguments to su */
987 gchar args
[MAX_ARGS_LEN
];
988 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
993 strncat(args
, "exec", args_left
);
994 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
997 strncat(args
, " ", args_left
);
998 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1000 if(strcmp(lttctl_path
, "") == 0)
1001 strncat(args
, "lttctl", args_left
);
1003 strncat(args
, lttctl_path
, args_left
);
1004 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1007 strncat(args
, " ", args_left
);
1008 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1011 strncat(args
, "-n ", args_left
);
1012 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1013 strncat(args
, trace_name
, args_left
);
1014 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1017 strncat(args
, " ", args_left
);
1018 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1020 /* Simply stop tracing and destroy channel */
1021 strncat(args
, "-R", args_left
);
1022 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1024 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
1027 guint msg_left
= 256;
1029 strcpy(msg
, "A problem occured when executing the su command : ");
1030 msg_left
= 256 - strlen(msg
) - 1;
1031 strncat(msg
, strerror(retval
), msg_left
);
1032 GtkWidget
*dialogue
=
1033 gtk_message_dialog_new(
1034 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1035 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1039 gtk_dialog_run(GTK_DIALOG(dialogue
));
1040 gtk_widget_destroy(dialogue
);
1045 /* Ask to the user if he wants to open the trace in a new window */
1046 GtkWidget
*dialogue
;
1050 dialogue
= gtk_dialog_new_with_buttons("Open trace ?",
1051 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1052 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1053 GTK_STOCK_YES
,GTK_RESPONSE_ACCEPT
,
1054 GTK_STOCK_NO
,GTK_RESPONSE_REJECT
,
1056 label
= gtk_label_new("Do you want to open the trace in LTTV ?");
1057 gtk_widget_show(label
);
1059 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue
)->vbox
),
1062 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
1065 case GTK_RESPONSE_ACCEPT
:
1067 create_main_window_with_trace(trace_dir
);
1070 case GTK_RESPONSE_REJECT
:
1074 gtk_widget_destroy(dialogue
);
1080 * @fn GtkWidget* h_guicontrol(Tab*)
1082 * Control Module's constructor hook
1084 * This constructor is given as a parameter to the menuitem and toolbar button
1085 * registration. It creates the list.
1086 * @param tab A pointer to the parent window.
1087 * @return The widget created.
1090 h_guicontrol(Tab
*tab
)
1092 ControlData
* f
= gui_control(tab
) ;
1098 * @fn static void init()
1100 * This function initializes the Filter Viewer functionnality through the
1103 static void init() {
1105 lttvwindow_register_constructor("guicontrol",
1107 "Insert Tracing Control Module",
1108 hTraceControlInsert_xpm
,
1109 "Insert Tracing Control Module",
1114 * @fn void control_destroy_walk(gpointer,gpointer)
1116 * Initiate the destruction of the current gui module
1117 * on the GTK Interface
1120 control_destroy_walk(gpointer data
, gpointer user_data
)
1122 ControlData
*tcd
= (ControlData
*)data
;
1124 g_debug("traceontrol.c : control_destroy_walk, %p", tcd
);
1126 /* May already have been done by GTK window closing */
1127 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
)))
1128 gtk_widget_destroy(guicontrol_get_widget(tcd
));
1132 * @fn static void destroy()
1133 * @brief plugin's destroy function
1135 * This function releases the memory reserved by the module and unregisters
1136 * everything that has been registered in the gtkTraceSet API.
1138 static void destroy() {
1140 g_slist_foreach(g_control_list
, control_destroy_walk
, NULL
);
1142 lttvwindow_unregister_constructor(h_guicontrol
);
1147 LTTV_MODULE("guitracecontrol", "Trace Control Window", \
1148 "Graphical module that let user control kernel tracing", \
1149 init
, destroy
, "lttvwindow")