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,
24 #include <glib/gprintf.h>
28 #include <gdk/gdkkeysyms.h>
30 #include <lttv/lttv.h>
31 #include <lttv/module.h>
32 #include <lttv/hook.h>
34 #include <lttvwindow/lttvwindow.h>
35 #include <lttvwindow/lttvwindowtraces.h>
36 #include <lttvwindow/callbacks.h>
37 #include <lttvwindow/lttv_plugin_tab.h>
39 #include "hTraceControlInsert.xpm"
40 #include "TraceControlStart.xpm"
41 #include "TraceControlPause.xpm"
42 #include "TraceControlStop.xpm"
44 #include <sys/types.h>
55 #define MAX_ARGS_LEN PATH_MAX * 10
57 GSList
*g_control_list
= NULL
;
59 /*! \file lttv/modules/gui/tracecontrol/tracecontrol.c
60 * \brief Graphic trace start/stop control interface.
62 * This plugin interacts with lttctl to start/stop tracing. It needs to take the
63 * root password to be able to interact with lttctl.
67 typedef struct _ControlData ControlData
;
72 GtkWidget
*guicontrol_get_widget(ControlData
*tcd
);
73 ControlData
*gui_control(LttvPluginTab
*ptab
);
74 void gui_control_destructor(ControlData
*tcd
);
75 GtkWidget
* h_guicontrol(LttvPlugin
*plugin
);
76 void control_destroy_walk(gpointer data
, gpointer user_data
);
82 static void start_clicked (GtkButton
*button
, gpointer user_data
);
83 static void pause_clicked (GtkButton
*button
, gpointer user_data
);
84 static void unpause_clicked (GtkButton
*button
, gpointer user_data
);
85 static void stop_clicked (GtkButton
*button
, gpointer user_data
);
89 * @struct _ControlData
91 * @brief Main structure of gui control
94 Tab
*tab
; /**< current tab of module */
96 GtkWidget
*window
; /**< window */
98 GtkWidget
*main_box
; /**< main container */
99 GtkWidget
*start_button
;
100 GtkWidget
*pause_button
;
101 GtkWidget
*unpause_button
;
102 GtkWidget
*stop_button
;
103 GtkWidget
*username_label
;
104 GtkWidget
*username_entry
;
105 GtkWidget
*password_label
;
106 GtkWidget
*password_entry
;
107 GtkWidget
*channel_dir_label
;
108 GtkWidget
*channel_dir_entry
;
109 GtkWidget
*trace_dir_label
;
110 GtkWidget
*trace_dir_entry
;
111 GtkWidget
*trace_name_label
;
112 GtkWidget
*trace_name_entry
;
113 GtkWidget
*trace_mode_label
;
114 GtkWidget
*trace_mode_combo
;
115 GtkWidget
*start_daemon_label
;
116 GtkWidget
*start_daemon_check
;
117 GtkWidget
*append_label
;
118 GtkWidget
*append_check
;
119 GtkWidget
*optional_label
;
120 GtkWidget
*subbuf_size_label
;
121 GtkWidget
*subbuf_size_entry
;
122 GtkWidget
*subbuf_num_label
;
123 GtkWidget
*subbuf_num_entry
;
124 GtkWidget
*lttd_threads_label
;
125 GtkWidget
*lttd_threads_entry
;
126 GtkWidget
*lttctl_path_label
;
127 GtkWidget
*lttctl_path_entry
;
128 GtkWidget
*lttd_path_label
;
129 GtkWidget
*lttd_path_entry
;
133 * @fn GtkWidget* guicontrol_get_widget(ControlData*)
135 * This function returns the current main widget
136 * used by this module
137 * @param tcd the module struct
138 * @return The main widget
141 guicontrol_get_widget(ControlData
*tcd
)
147 * @fn ControlData* gui_control(Tab*)
149 * Constructor is used to create ControlData data structure.
150 * @param tab The tab structure used by the widget
151 * @return The Filter viewer data created.
154 gui_control(LttvPluginTab
*ptab
)
156 Tab
*tab
= ptab
->tab
;
157 g_debug("filter::gui_control()");
160 GtkCellRenderer
*renderer
;
161 GtkTreeViewColumn
*column
;
163 ControlData
* tcd
= g_new(ControlData
,1);
167 tcd
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
168 gtk_window_set_title(GTK_WINDOW(tcd
->window
), "LTTng Trace Control");
170 * Initiating GtkTable layout
171 * starts with 2 rows and 5 columns and
172 * expands when expressions added
174 tcd
->main_box
= gtk_table_new(14,7,FALSE
);
175 gtk_table_set_row_spacings(GTK_TABLE(tcd
->main_box
),5);
176 gtk_table_set_col_spacings(GTK_TABLE(tcd
->main_box
),5);
178 gtk_container_add(GTK_CONTAINER(tcd
->window
), GTK_WIDGET(tcd
->main_box
));
180 GList
*focus_chain
= NULL
;
183 * start/pause/stop buttons
187 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStart_xpm
);
188 image
= gtk_image_new_from_pixbuf(pixbuf
);
189 tcd
->start_button
= gtk_button_new_with_label("start");
190 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->start_button), image);
191 g_object_set(G_OBJECT(tcd
->start_button
), "image", image
, NULL
);
192 gtk_button_set_alignment(GTK_BUTTON(tcd
->start_button
), 0.0, 0.0);
193 gtk_widget_show (tcd
->start_button
);
194 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_button
,6,7,0,1,GTK_FILL
,GTK_FILL
,2,2);
196 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
197 image
= gtk_image_new_from_pixbuf(pixbuf
);
198 tcd
->pause_button
= gtk_button_new_with_label("pause");
199 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->pause_button), image);
200 g_object_set(G_OBJECT(tcd
->pause_button
), "image", image
, NULL
);
201 gtk_button_set_alignment(GTK_BUTTON(tcd
->pause_button
), 0.0, 0.0);
202 gtk_widget_show (tcd
->pause_button
);
203 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->pause_button
,6,7,1,2,GTK_FILL
,GTK_FILL
,2,2);
205 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
206 image
= gtk_image_new_from_pixbuf(pixbuf
);
207 tcd
->unpause_button
= gtk_button_new_with_label("unpause");
208 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->unpause_button), image);
209 g_object_set(G_OBJECT(tcd
->unpause_button
), "image", image
, NULL
);
210 gtk_button_set_alignment(GTK_BUTTON(tcd
->unpause_button
), 0.0, 0.0);
211 gtk_widget_show (tcd
->unpause_button
);
212 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->unpause_button
,6,7,2,3,GTK_FILL
,GTK_FILL
,2,2);
214 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStop_xpm
);
215 image
= gtk_image_new_from_pixbuf(pixbuf
);
216 tcd
->stop_button
= gtk_button_new_with_label("stop");
217 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->stop_button), image);
218 g_object_set(G_OBJECT(tcd
->stop_button
), "image", image
, NULL
);
219 gtk_button_set_alignment(GTK_BUTTON(tcd
->stop_button
), 0.0, 0.0);
220 gtk_widget_show (tcd
->stop_button
);
221 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->stop_button
,6,7,3,4,GTK_FILL
,GTK_FILL
,2,2);
224 * First half of the filter window
225 * - textual entry of filter expression
226 * - processing button
228 tcd
->username_label
= gtk_label_new("Username:");
229 gtk_widget_show (tcd
->username_label
);
230 tcd
->username_entry
= gtk_entry_new();
231 gtk_entry_set_text(GTK_ENTRY(tcd
->username_entry
),"root");
232 gtk_widget_show (tcd
->username_entry
);
233 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->username_label
,0,2,0,1,GTK_FILL
,GTK_FILL
,2,2);
234 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);
238 tcd
->password_label
= gtk_label_new("Password:");
239 gtk_widget_show (tcd
->password_label
);
240 tcd
->password_entry
= gtk_entry_new();
241 gtk_entry_set_visibility(GTK_ENTRY(tcd
->password_entry
), FALSE
);
242 gtk_widget_show (tcd
->password_entry
);
243 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->password_label
,0,2,1,2,GTK_FILL
,GTK_FILL
,2,2);
244 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);
247 tcd
->channel_dir_label
= gtk_label_new("Channel directory:");
248 gtk_widget_show (tcd
->channel_dir_label
);
249 tcd
->channel_dir_entry
= gtk_entry_new();
250 gtk_entry_set_text(GTK_ENTRY(tcd
->channel_dir_entry
),"/mnt/debugfs/ltt");
251 gtk_widget_show (tcd
->channel_dir_entry
);
252 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->channel_dir_label
,0,2,2,3,GTK_FILL
,GTK_FILL
,2,2);
253 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);
255 tcd
->trace_dir_label
= gtk_label_new("Trace directory:");
256 gtk_widget_show (tcd
->trace_dir_label
);
257 tcd
->trace_dir_entry
= gtk_entry_new();
258 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_dir_entry
),"/tmp/trace1");
259 gtk_widget_show (tcd
->trace_dir_entry
);
260 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_dir_label
,0,2,3,4,GTK_FILL
,GTK_FILL
,2,2);
261 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);
263 tcd
->trace_name_label
= gtk_label_new("Trace name:");
264 gtk_widget_show (tcd
->trace_name_label
);
265 tcd
->trace_name_entry
= gtk_entry_new();
266 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_name_entry
),"trace");
267 gtk_widget_show (tcd
->trace_name_entry
);
268 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_name_label
,0,2,4,5,GTK_FILL
,GTK_FILL
,2,2);
269 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);
271 tcd
->trace_mode_label
= gtk_label_new("Trace mode ");
272 gtk_widget_show (tcd
->trace_mode_label
);
273 tcd
->trace_mode_combo
= gtk_combo_box_new_text();
274 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
276 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
278 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd
->trace_mode_combo
), 0);
279 gtk_widget_show (tcd
->trace_mode_combo
);
280 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_mode_label
,0,2,5,6,GTK_FILL
,GTK_FILL
,2,2);
281 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);
283 tcd
->start_daemon_label
= gtk_label_new("Start daemon ");
284 gtk_widget_show (tcd
->start_daemon_label
);
285 tcd
->start_daemon_check
= gtk_check_button_new();
286 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
), TRUE
);
287 gtk_widget_show (tcd
->start_daemon_check
);
288 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_label
,0,2,6,7,GTK_FILL
,GTK_FILL
,2,2);
289 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_check
,2,6,6,7,GTK_FILL
,GTK_FILL
,0,0);
291 tcd
->append_label
= gtk_label_new("Append to trace ");
292 gtk_widget_show (tcd
->append_label
);
293 tcd
->append_check
= gtk_check_button_new();
294 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->append_check
), FALSE
);
295 gtk_widget_show (tcd
->append_check
);
296 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_label
,0,2,7,8,GTK_FILL
,GTK_FILL
,2,2);
297 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_check
,2,6,7,8,GTK_FILL
,GTK_FILL
,0,0);
300 tcd
->optional_label
= gtk_label_new("Optional fields ");
301 gtk_widget_show (tcd
->optional_label
);
302 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->optional_label
,0,6,8,9,GTK_FILL
,GTK_FILL
,2,2);
304 tcd
->subbuf_size_label
= gtk_label_new("Subbuffer size:");
305 gtk_widget_show (tcd
->subbuf_size_label
);
306 tcd
->subbuf_size_entry
= gtk_entry_new();
307 gtk_widget_show (tcd
->subbuf_size_entry
);
308 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_size_label
,0,2,9,10,GTK_FILL
,GTK_FILL
,2,2);
309 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);
311 tcd
->subbuf_num_label
= gtk_label_new("Number of subbuffers:");
312 gtk_widget_show (tcd
->subbuf_num_label
);
313 tcd
->subbuf_num_entry
= gtk_entry_new();
314 gtk_widget_show (tcd
->subbuf_num_entry
);
315 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_num_label
,0,2,10,11,GTK_FILL
,GTK_FILL
,2,2);
316 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);
318 tcd
->lttd_threads_label
= gtk_label_new("Number of lttd threads:");
319 gtk_widget_show (tcd
->lttd_threads_label
);
320 tcd
->lttd_threads_entry
= gtk_entry_new();
321 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_threads_entry
), "1");
322 gtk_widget_show (tcd
->lttd_threads_entry
);
323 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_threads_label
,0,2,11,12,GTK_FILL
,GTK_FILL
,2,2);
324 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);
326 tcd
->lttctl_path_label
= gtk_label_new("path to lttctl:");
327 gtk_widget_show (tcd
->lttctl_path_label
);
328 tcd
->lttctl_path_entry
= gtk_entry_new();
329 gtk_entry_set_text(GTK_ENTRY(tcd
->lttctl_path_entry
),PACKAGE_BIN_DIR
"/lttctl");
330 gtk_widget_show (tcd
->lttctl_path_entry
);
331 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttctl_path_label
,0,2,12,13,GTK_FILL
,GTK_FILL
,2,2);
332 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);
335 tcd
->lttd_path_label
= gtk_label_new("path to lttd:");
336 gtk_widget_show (tcd
->lttd_path_label
);
337 tcd
->lttd_path_entry
= gtk_entry_new();
338 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_path_entry
),PACKAGE_BIN_DIR
"/lttd");
339 gtk_widget_show (tcd
->lttd_path_entry
);
340 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_path_label
,0,2,13,14,GTK_FILL
,GTK_FILL
,2,2);
341 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);
344 focus_chain
= g_list_append (focus_chain
, tcd
->username_entry
);
345 focus_chain
= g_list_append (focus_chain
, tcd
->password_entry
);
346 focus_chain
= g_list_append (focus_chain
, tcd
->start_button
);
347 focus_chain
= g_list_append (focus_chain
, tcd
->pause_button
);
348 focus_chain
= g_list_append (focus_chain
, tcd
->unpause_button
);
349 focus_chain
= g_list_append (focus_chain
, tcd
->stop_button
);
350 focus_chain
= g_list_append (focus_chain
, tcd
->channel_dir_entry
);
351 focus_chain
= g_list_append (focus_chain
, tcd
->trace_dir_entry
);
352 focus_chain
= g_list_append (focus_chain
, tcd
->trace_name_entry
);
353 focus_chain
= g_list_append (focus_chain
, tcd
->trace_mode_combo
);
354 focus_chain
= g_list_append (focus_chain
, tcd
->start_daemon_check
);
355 focus_chain
= g_list_append (focus_chain
, tcd
->append_check
);
356 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_size_entry
);
357 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_num_entry
);
358 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_threads_entry
);
359 focus_chain
= g_list_append (focus_chain
, tcd
->lttctl_path_entry
);
360 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_path_entry
);
362 gtk_container_set_focus_chain(GTK_CONTAINER(tcd
->main_box
), focus_chain
);
364 g_list_free(focus_chain
);
366 g_signal_connect(G_OBJECT(tcd
->start_button
), "clicked",
367 (GCallback
)start_clicked
, tcd
);
368 g_signal_connect(G_OBJECT(tcd
->pause_button
), "clicked",
369 (GCallback
)pause_clicked
, tcd
);
370 g_signal_connect(G_OBJECT(tcd
->unpause_button
), "clicked",
371 (GCallback
)unpause_clicked
, tcd
);
372 g_signal_connect(G_OBJECT(tcd
->stop_button
), "clicked",
373 (GCallback
)stop_clicked
, tcd
);
376 * show main container
378 gtk_widget_show(tcd
->main_box
);
379 gtk_widget_show(tcd
->window
);
382 g_object_set_data_full(
383 G_OBJECT(guicontrol_get_widget(tcd
)),
384 "control_viewer_data",
386 (GDestroyNotify
)gui_control_destructor
);
388 g_control_list
= g_slist_append(
397 * @fn void gui_control_destructor(ControlData*)
399 * Destructor for the filter gui module
400 * @param tcd The module structure
403 gui_control_destructor(ControlData
*tcd
)
407 /* May already been done by GTK window closing */
408 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
))){
409 g_info("widget still exists");
412 // lttvwindow_unregister_traceset_notify(tcd->tab,
413 // filter_traceset_changed,
414 // filter_viewer_data);
416 lttvwindowtraces_background_notify_remove(tcd
);
418 g_control_list
= g_slist_remove(g_control_list
, tcd
);
423 static int execute_command(const gchar
*command
, const gchar
*username
,
424 const gchar
*password
, const gchar
*lttd_path
)
428 pid
= forkpty(&fdpty
, NULL
, NULL
, NULL
);
436 /* discuss with su */
437 struct timeval timeout
;
441 struct pollfd pollfd
;
444 enum read_state
{ GET_LINE
, GET_SEMI
, GET_SPACE
} read_state
= GET_LINE
;
446 retval
= fcntl(fdpty
, F_SETFL
, O_WRONLY
);
448 perror("Error in fcntl");
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...");
457 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
459 num_rdy
= poll(&pollfd
, 1, -1);
461 perror("Poll error");
465 /* Timeout : Stop waiting for chars */
466 if(num_rdy
== 0) goto wait_child
;
468 switch(pollfd
.revents
) {
470 g_warning("Error returned in polling fd\n");
474 g_info("Polling FD : hung up.");
478 g_warning("Polling fd tells it is not open");
483 count
= read (fdpty
, buf
, 256);
488 for(i
=0; i
<count
; i
++) {
492 read_state
= GET_SEMI
;
493 g_debug("Tracecontrol input line skip\n");
498 g_debug("Tracecontrol input : marker found\n");
499 read_state
= GET_SPACE
;
504 g_debug("Tracecontrol input space marker found\n");
510 } else if(count
== -1) {
511 perror("Error in read");
517 g_warning("Child hung up too fast");
524 pollfd
.events
= POLLOUT
|POLLERR
|POLLHUP
|POLLNVAL
;
526 num_rdy
= poll(&pollfd
, 1, -1);
528 perror("Poll error");
532 /* Write the password */
533 g_info("Got su prompt, now writing password...");
536 ret
= write(fdpty
, password
, strlen(password
));
537 if(ret
< 0) perror("Error in write");
538 ret
= write(fdpty
, "\n", 1);
539 if(ret
< 0) perror("Error in write");
541 /* Take the output from the terminal and show it on the real console */
542 g_info("Getting data from child terminal...");
546 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
548 num_rdy
= poll(&pollfd
, 1, -1);
550 perror("Poll error");
553 if(num_rdy
== 0) break;
555 if(pollfd
.revents
& (POLLERR
|POLLNVAL
)) {
556 g_warning("Error returned in polling fd\n");
560 if(pollfd
.revents
& (POLLIN
|POLLPRI
) ) {
561 count
= read (fdpty
, buf
, 256);
565 } else if(count
== -1) {
566 perror("Error in read");
571 if(pollfd
.revents
& POLLHUP
) {
572 g_info("Polling FD : hung up.");
576 if(num_hup
> 0) goto wait_child
;
579 g_info("Waiting for child exit...");
581 ret
= waitpid(pid
, &status
, 0);
584 g_warning("An error occured in wait : %s",
587 if(WIFEXITED(status
))
588 if(WEXITSTATUS(status
) != 0) {
589 retval
= WEXITSTATUS(status
);
590 g_warning("An error occured in the su command : %s",
595 g_info("Child exited.");
597 } else if(pid
== 0) {
598 /* Setup environment variables */
599 if(strcmp(lttd_path
, "") != 0)
600 setenv("LTT_DAEMON", lttd_path
, 1);
602 /* One comment line (must be only one) */
603 g_printf("Executing (as %s) : %s\n", username
, command
);
605 execlp("su", "su", "-p", "-c", command
, username
, NULL
);
606 exit(-1); /* not supposed to happen! */
608 //gint ret = execvp();
612 g_warning("Error happened when forking for su");
621 void start_clicked (GtkButton
*button
, gpointer user_data
)
623 ControlData
*tcd
= (ControlData
*)user_data
;
625 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
626 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
627 const gchar
*channel_dir
=
628 gtk_entry_get_text(GTK_ENTRY(tcd
->channel_dir_entry
));
629 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
630 const gchar
*trace_name
=
631 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
633 const gchar
*trace_mode_sel
;
636 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd
->trace_mode_combo
), &iter
);
638 gtk_combo_box_get_model(GTK_COMBO_BOX(tcd
->trace_mode_combo
)),
639 &iter
, 0, &trace_mode_sel
, -1);
640 //const gchar *trace_mode_sel =
641 //2.6+ gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
642 const gchar
*trace_mode
;
643 if(strcmp(trace_mode_sel
, "normal") == 0)
644 trace_mode
= "normal";
646 trace_mode
= "flight";
648 gboolean start_daemon
=
649 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
));
652 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->append_check
));
654 const gchar
*subbuf_size
=
655 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_size_entry
));
656 const gchar
*subbuf_num
=
657 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_num_entry
));
658 const gchar
*threads_num
=
659 gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_threads_entry
));
660 const gchar
*lttctl_path
=
661 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
662 const gchar
*lttd_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_path_entry
));
664 /* Setup arguments to su */
666 gchar args
[MAX_ARGS_LEN
];
667 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
672 strncat(args
, "exec", args_left
);
673 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
676 strncat(args
, " ", args_left
);
677 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
679 if(strcmp(lttctl_path
, "") == 0)
680 strncat(args
, "lttctl", args_left
);
682 strncat(args
, lttctl_path
, args_left
);
683 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
686 strncat(args
, " ", args_left
);
687 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
691 strncat(args
, "-C", args_left
);
692 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
694 /* Simply create the channel and then start tracing */
695 //strncat(args, "-b", args_left);
696 //args_left = MAX_ARGS_LEN - strlen(args) - 1;
700 strncat(args
, " ", args_left
);
701 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
704 strncat(args
, "--channel_root ", args_left
);
705 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
706 strncat(args
, channel_dir
, args_left
);
707 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
710 strncat(args
, " ", args_left
);
711 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
714 strncat(args
, "-w ", args_left
);
715 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
716 strncat(args
, trace_dir
, args_left
);
717 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
720 strncat(args
, " ", args_left
);
721 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
723 if(strcmp(trace_mode
, "flight") == 0) {
724 strncat(args
, "-o channel.all.overwrite=1", args_left
);
725 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
727 strncat(args
, "-o channel.all.overwrite=0", args_left
);
728 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
731 /* Append to trace ? */
734 strncat(args
, " ", args_left
);
735 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
736 strncat(args
, "-a", args_left
);
737 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
740 /* optional arguments */
742 if(strcmp(subbuf_size
, "") != 0) {
744 strncat(args
, " ", args_left
);
745 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
747 strncat(args
, "-o channel.all.bufsize=", args_left
);
748 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
749 strncat(args
, subbuf_size
, args_left
);
750 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
753 /* number of subbuffers */
754 if(strcmp(subbuf_num
, "") != 0) {
756 strncat(args
, " ", args_left
);
757 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
759 strncat(args
, "-o channel.all.bufnum=", args_left
);
760 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
761 strncat(args
, subbuf_num
, args_left
);
762 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
765 /* number of lttd threads */
766 if(strcmp(threads_num
, "") != 0) {
768 strncat(args
, " ", args_left
);
769 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
771 strncat(args
, "-n ", args_left
);
772 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
773 strncat(args
, threads_num
, args_left
);
774 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
778 strncat(args
, " ", args_left
);
779 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
782 strncat(args
, trace_name
, args_left
);
783 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
785 int retval
= execute_command(args
, username
, password
, lttd_path
);
789 guint msg_left
= 256;
791 strcpy(msg
, "A problem occured when executing the su command : ");
792 msg_left
= 256 - strlen(msg
) - 1;
793 strncat(msg
, strerror(retval
), msg_left
);
794 GtkWidget
*dialogue
=
795 gtk_message_dialog_new(
796 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
797 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
801 gtk_dialog_run(GTK_DIALOG(dialogue
));
802 gtk_widget_destroy(dialogue
);
808 void pause_clicked (GtkButton
*button
, gpointer user_data
)
810 ControlData
*tcd
= (ControlData
*)user_data
;
812 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
813 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
814 const gchar
*trace_name
=
815 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
816 const gchar
*lttd_path
= "";
818 const gchar
*lttctl_path
=
819 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
821 /* Setup arguments to su */
823 gchar args
[MAX_ARGS_LEN
];
824 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
829 strncat(args
, "exec", args_left
);
830 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
833 strncat(args
, " ", args_left
);
834 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
836 if(strcmp(lttctl_path
, "") == 0)
837 strncat(args
, "lttctl", args_left
);
839 strncat(args
, lttctl_path
, args_left
);
840 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
843 strncat(args
, " ", args_left
);
844 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
846 /* Simply pause tracing */
847 strncat(args
, "-p", args_left
);
848 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
851 strncat(args
, " ", args_left
);
852 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
855 strncat(args
, trace_name
, args_left
);
856 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
858 int retval
= execute_command(args
, username
, password
, lttd_path
);
861 guint msg_left
= 256;
863 strcpy(msg
, "A problem occured when executing the su command : ");
864 msg_left
= 256 - strlen(msg
) - 1;
865 strncat(msg
, strerror(retval
), msg_left
);
866 GtkWidget
*dialogue
=
867 gtk_message_dialog_new(
868 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
869 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
873 gtk_dialog_run(GTK_DIALOG(dialogue
));
874 gtk_widget_destroy(dialogue
);
879 void unpause_clicked (GtkButton
*button
, gpointer user_data
)
881 ControlData
*tcd
= (ControlData
*)user_data
;
883 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
884 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
885 const gchar
*trace_name
=
886 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
887 const gchar
*lttd_path
= "";
889 const gchar
*lttctl_path
=
890 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
892 /* Setup arguments to su */
894 gchar args
[MAX_ARGS_LEN
];
895 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
900 strncat(args
, "exec", args_left
);
901 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
904 strncat(args
, " ", args_left
);
905 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
907 if(strcmp(lttctl_path
, "") == 0)
908 strncat(args
, "lttctl", args_left
);
910 strncat(args
, lttctl_path
, args_left
);
911 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
914 strncat(args
, " ", args_left
);
915 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
917 /* Simply unpause tracing */
918 strncat(args
, "-s", 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;
926 strncat(args
, trace_name
, args_left
);
927 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
929 int retval
= execute_command(args
, username
, password
, lttd_path
);
932 guint msg_left
= 256;
934 strcpy(msg
, "A problem occured when executing the su command : ");
935 msg_left
= 256 - strlen(msg
) - 1;
936 strncat(msg
, strerror(retval
), msg_left
);
937 GtkWidget
*dialogue
=
938 gtk_message_dialog_new(
939 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
940 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
944 gtk_dialog_run(GTK_DIALOG(dialogue
));
945 gtk_widget_destroy(dialogue
);
950 void stop_clicked (GtkButton
*button
, gpointer user_data
)
952 ControlData
*tcd
= (ControlData
*)user_data
;
954 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
955 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
956 const gchar
*trace_name
=
957 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
958 const gchar
*lttd_path
= "";
959 const gchar
*trace_mode
;
960 const gchar
*trace_mode_sel
;
963 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd
->trace_mode_combo
), &iter
);
965 gtk_combo_box_get_model(GTK_COMBO_BOX(tcd
->trace_mode_combo
)),
966 &iter
, 0, &trace_mode_sel
, -1);
967 if(strcmp(trace_mode_sel
, "normal") == 0)
968 trace_mode
= "normal";
970 trace_mode
= "flight";
972 const gchar
*lttctl_path
=
973 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
974 gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
975 GSList
* trace_list
= NULL
;
977 trace_list
= g_slist_append(trace_list
, trace_dir
);
979 /* Setup arguments to su */
981 gchar args
[MAX_ARGS_LEN
];
982 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
987 strncat(args
, "exec", args_left
);
988 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
991 strncat(args
, " ", args_left
);
992 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
994 if(strcmp(lttctl_path
, "") == 0)
995 strncat(args
, "lttctl", args_left
);
997 strncat(args
, lttctl_path
, args_left
);
998 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1001 strncat(args
, " ", args_left
);
1002 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1004 /* Simply stop tracing and destroy channel */
1005 strncat(args
, "-D", args_left
);
1006 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1008 if(strcmp(trace_mode
, "flight") == 0) {
1010 strncat(args
, " ", args_left
);
1011 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1014 strncat(args
, "-w ", args_left
);
1015 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1016 strncat(args
, trace_dir
, args_left
);
1017 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1021 strncat(args
, " ", args_left
);
1022 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1025 strncat(args
, trace_name
, args_left
);
1026 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1028 int retval
= execute_command(args
, username
, password
, lttd_path
);
1031 guint msg_left
= 256;
1033 strcpy(msg
, "A problem occured when executing the su command : ");
1034 msg_left
= 256 - strlen(msg
) - 1;
1035 strncat(msg
, strerror(retval
), msg_left
);
1036 GtkWidget
*dialogue
=
1037 gtk_message_dialog_new(
1038 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1039 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1043 gtk_dialog_run(GTK_DIALOG(dialogue
));
1044 gtk_widget_destroy(dialogue
);
1049 /* Ask to the user if he wants to open the trace in a new window */
1050 GtkWidget
*dialogue
;
1054 dialogue
= gtk_dialog_new_with_buttons("Open trace ?",
1055 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1056 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1057 GTK_STOCK_YES
,GTK_RESPONSE_ACCEPT
,
1058 GTK_STOCK_NO
,GTK_RESPONSE_REJECT
,
1060 label
= gtk_label_new("Do you want to open the trace in LTTV ?");
1061 gtk_widget_show(label
);
1063 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue
)->vbox
),
1066 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
1069 case GTK_RESPONSE_ACCEPT
:
1071 create_main_window_with_trace_list(trace_list
);
1074 case GTK_RESPONSE_REJECT
:
1078 gtk_widget_destroy(dialogue
);
1079 g_slist_free(trace_list
);
1084 * @fn GtkWidget* h_guicontrol(Tab*)
1086 * Control Module's constructor hook
1088 * This constructor is given as a parameter to the menuitem and toolbar button
1089 * registration. It creates the list.
1090 * @param tab A pointer to the parent window.
1091 * @return The widget created.
1094 h_guicontrol(LttvPlugin
*plugin
)
1096 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
1097 ControlData
* f
= gui_control(ptab
);
1103 * @fn static void init()
1105 * This function initializes the Filter Viewer functionnality through the
1108 static void init() {
1110 lttvwindow_register_constructor("guicontrol",
1112 "Insert Tracing Control Module",
1113 hTraceControlInsert_xpm
,
1114 "Insert Tracing Control Module",
1119 * @fn void control_destroy_walk(gpointer,gpointer)
1121 * Initiate the destruction of the current gui module
1122 * on the GTK Interface
1125 control_destroy_walk(gpointer data
, gpointer user_data
)
1127 ControlData
*tcd
= (ControlData
*)data
;
1129 g_debug("traceontrol.c : control_destroy_walk, %p", tcd
);
1131 /* May already have been done by GTK window closing */
1132 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
)))
1133 gtk_widget_destroy(guicontrol_get_widget(tcd
));
1137 * @fn static void destroy()
1138 * @brief plugin's destroy function
1140 * This function releases the memory reserved by the module and unregisters
1141 * everything that has been registered in the gtkTraceSet API.
1143 static void destroy() {
1145 g_slist_foreach(g_control_list
, control_destroy_walk
, NULL
);
1147 lttvwindow_unregister_constructor(h_guicontrol
);
1152 LTTV_MODULE("guitracecontrol", "Trace Control Window", \
1153 "Graphical module that let user control kernel tracing", \
1154 init
, destroy
, "lttvwindow")