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>
38 #include "hTraceControlInsert.xpm"
39 #include "TraceControlStart.xpm"
40 #include "TraceControlPause.xpm"
41 #include "TraceControlStop.xpm"
43 #include <sys/types.h>
54 #define MAX_ARGS_LEN PATH_MAX * 10
56 GSList
*g_control_list
= NULL
;
58 /*! \file lttv/modules/gui/tracecontrol/tracecontrol.c
59 * \brief Graphic trace start/stop control interface.
61 * This plugin interacts with lttctl to start/stop tracing. It needs to take the
62 * root password to be able to interact with lttctl.
66 typedef struct _ControlData ControlData
;
71 GtkWidget
*guicontrol_get_widget(ControlData
*tcd
);
72 ControlData
*gui_control(GObject
*obj
);
73 void gui_control_destructor(ControlData
*tcd
);
74 GtkWidget
* h_guicontrol(GObject
*obj
);
75 void control_destroy_walk(gpointer data
, gpointer user_data
);
81 static void start_clicked (GtkButton
*button
, gpointer user_data
);
82 static void pause_clicked (GtkButton
*button
, gpointer user_data
);
83 static void unpause_clicked (GtkButton
*button
, gpointer user_data
);
84 static void stop_clicked (GtkButton
*button
, gpointer user_data
);
88 * @struct _ControlData
90 * @brief Main structure of gui control
93 Tab
*tab
; /**< current tab of module */
95 GtkWidget
*window
; /**< window */
97 GtkWidget
*main_box
; /**< main container */
98 GtkWidget
*start_button
;
99 GtkWidget
*pause_button
;
100 GtkWidget
*unpause_button
;
101 GtkWidget
*stop_button
;
102 GtkWidget
*username_label
;
103 GtkWidget
*username_entry
;
104 GtkWidget
*password_label
;
105 GtkWidget
*password_entry
;
106 GtkWidget
*channel_dir_label
;
107 GtkWidget
*channel_dir_entry
;
108 GtkWidget
*trace_dir_label
;
109 GtkWidget
*trace_dir_entry
;
110 GtkWidget
*trace_name_label
;
111 GtkWidget
*trace_name_entry
;
112 GtkWidget
*trace_mode_label
;
113 GtkWidget
*trace_mode_combo
;
114 GtkWidget
*start_daemon_label
;
115 GtkWidget
*start_daemon_check
;
116 GtkWidget
*append_label
;
117 GtkWidget
*append_check
;
118 GtkWidget
*optional_label
;
119 GtkWidget
*subbuf_size_label
;
120 GtkWidget
*subbuf_size_entry
;
121 GtkWidget
*subbuf_num_label
;
122 GtkWidget
*subbuf_num_entry
;
123 GtkWidget
*lttd_threads_label
;
124 GtkWidget
*lttd_threads_entry
;
125 GtkWidget
*lttctl_path_label
;
126 GtkWidget
*lttctl_path_entry
;
127 GtkWidget
*lttd_path_label
;
128 GtkWidget
*lttd_path_entry
;
129 GtkWidget
*fac_path_label
;
130 GtkWidget
*fac_path_entry
;
134 * @fn GtkWidget* guicontrol_get_widget(ControlData*)
136 * This function returns the current main widget
137 * used by this module
138 * @param tcd the module struct
139 * @return The main widget
142 guicontrol_get_widget(ControlData
*tcd
)
148 * @fn ControlData* gui_control(Tab*)
150 * Constructor is used to create ControlData data structure.
151 * @param tab The tab structure used by the widget
152 * @return The Filter viewer data created.
155 gui_control(GObject
*obj
)
157 Tab
*tab
= g_object_get_data(obj
, "Tab");
158 g_debug("filter::gui_control()");
161 GtkCellRenderer
*renderer
;
162 GtkTreeViewColumn
*column
;
164 ControlData
* tcd
= g_new(ControlData
,1);
168 tcd
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
169 gtk_window_set_title(GTK_WINDOW(tcd
->window
), "LTTng Trace Control");
171 * Initiating GtkTable layout
172 * starts with 2 rows and 5 columns and
173 * expands when expressions added
175 tcd
->main_box
= gtk_table_new(14,7,FALSE
);
176 gtk_table_set_row_spacings(GTK_TABLE(tcd
->main_box
),5);
177 gtk_table_set_col_spacings(GTK_TABLE(tcd
->main_box
),5);
179 gtk_container_add(GTK_CONTAINER(tcd
->window
), GTK_WIDGET(tcd
->main_box
));
181 GList
*focus_chain
= NULL
;
184 * start/pause/stop buttons
188 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStart_xpm
);
189 image
= gtk_image_new_from_pixbuf(pixbuf
);
190 tcd
->start_button
= gtk_button_new_with_label("start");
191 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->start_button), image);
192 g_object_set(G_OBJECT(tcd
->start_button
), "image", image
, NULL
);
193 gtk_button_set_alignment(GTK_BUTTON(tcd
->start_button
), 0.0, 0.0);
194 gtk_widget_show (tcd
->start_button
);
195 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_button
,6,7,0,1,GTK_FILL
,GTK_FILL
,2,2);
197 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
198 image
= gtk_image_new_from_pixbuf(pixbuf
);
199 tcd
->pause_button
= gtk_button_new_with_label("pause");
200 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->pause_button), image);
201 g_object_set(G_OBJECT(tcd
->pause_button
), "image", image
, NULL
);
202 gtk_button_set_alignment(GTK_BUTTON(tcd
->pause_button
), 0.0, 0.0);
203 gtk_widget_show (tcd
->pause_button
);
204 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->pause_button
,6,7,1,2,GTK_FILL
,GTK_FILL
,2,2);
206 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm
);
207 image
= gtk_image_new_from_pixbuf(pixbuf
);
208 tcd
->unpause_button
= gtk_button_new_with_label("unpause");
209 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->unpause_button), image);
210 g_object_set(G_OBJECT(tcd
->unpause_button
), "image", image
, NULL
);
211 gtk_button_set_alignment(GTK_BUTTON(tcd
->unpause_button
), 0.0, 0.0);
212 gtk_widget_show (tcd
->unpause_button
);
213 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->unpause_button
,6,7,2,3,GTK_FILL
,GTK_FILL
,2,2);
215 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStop_xpm
);
216 image
= gtk_image_new_from_pixbuf(pixbuf
);
217 tcd
->stop_button
= gtk_button_new_with_label("stop");
218 //2.6 gtk_button_set_image(GTK_BUTTON(tcd->stop_button), image);
219 g_object_set(G_OBJECT(tcd
->stop_button
), "image", image
, NULL
);
220 gtk_button_set_alignment(GTK_BUTTON(tcd
->stop_button
), 0.0, 0.0);
221 gtk_widget_show (tcd
->stop_button
);
222 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->stop_button
,6,7,3,4,GTK_FILL
,GTK_FILL
,2,2);
225 * First half of the filter window
226 * - textual entry of filter expression
227 * - processing button
229 tcd
->username_label
= gtk_label_new("Username:");
230 gtk_widget_show (tcd
->username_label
);
231 tcd
->username_entry
= gtk_entry_new();
232 gtk_entry_set_text(GTK_ENTRY(tcd
->username_entry
),"root");
233 gtk_widget_show (tcd
->username_entry
);
234 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->username_label
,0,2,0,1,GTK_FILL
,GTK_FILL
,2,2);
235 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);
239 tcd
->password_label
= gtk_label_new("Password:");
240 gtk_widget_show (tcd
->password_label
);
241 tcd
->password_entry
= gtk_entry_new();
242 gtk_entry_set_visibility(GTK_ENTRY(tcd
->password_entry
), FALSE
);
243 gtk_widget_show (tcd
->password_entry
);
244 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->password_label
,0,2,1,2,GTK_FILL
,GTK_FILL
,2,2);
245 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);
248 tcd
->channel_dir_label
= gtk_label_new("Channel directory:");
249 gtk_widget_show (tcd
->channel_dir_label
);
250 tcd
->channel_dir_entry
= gtk_entry_new();
251 gtk_entry_set_text(GTK_ENTRY(tcd
->channel_dir_entry
),"/mnt/relayfs/ltt");
252 gtk_widget_show (tcd
->channel_dir_entry
);
253 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->channel_dir_label
,0,2,2,3,GTK_FILL
,GTK_FILL
,2,2);
254 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);
256 tcd
->trace_dir_label
= gtk_label_new("Trace directory:");
257 gtk_widget_show (tcd
->trace_dir_label
);
258 tcd
->trace_dir_entry
= gtk_entry_new();
259 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_dir_entry
),"/tmp/trace1");
260 gtk_widget_show (tcd
->trace_dir_entry
);
261 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_dir_label
,0,2,3,4,GTK_FILL
,GTK_FILL
,2,2);
262 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);
264 tcd
->trace_name_label
= gtk_label_new("Trace name:");
265 gtk_widget_show (tcd
->trace_name_label
);
266 tcd
->trace_name_entry
= gtk_entry_new();
267 gtk_entry_set_text(GTK_ENTRY(tcd
->trace_name_entry
),"trace");
268 gtk_widget_show (tcd
->trace_name_entry
);
269 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_name_label
,0,2,4,5,GTK_FILL
,GTK_FILL
,2,2);
270 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);
272 tcd
->trace_mode_label
= gtk_label_new("Trace mode ");
273 gtk_widget_show (tcd
->trace_mode_label
);
274 tcd
->trace_mode_combo
= gtk_combo_box_new_text();
275 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
277 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd
->trace_mode_combo
),
279 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd
->trace_mode_combo
), 0);
280 gtk_widget_show (tcd
->trace_mode_combo
);
281 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->trace_mode_label
,0,2,5,6,GTK_FILL
,GTK_FILL
,2,2);
282 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);
284 tcd
->start_daemon_label
= gtk_label_new("Start daemon ");
285 gtk_widget_show (tcd
->start_daemon_label
);
286 tcd
->start_daemon_check
= gtk_check_button_new();
287 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
), TRUE
);
288 gtk_widget_show (tcd
->start_daemon_check
);
289 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_label
,0,2,6,7,GTK_FILL
,GTK_FILL
,2,2);
290 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->start_daemon_check
,2,6,6,7,GTK_FILL
,GTK_FILL
,0,0);
292 tcd
->append_label
= gtk_label_new("Append to trace ");
293 gtk_widget_show (tcd
->append_label
);
294 tcd
->append_check
= gtk_check_button_new();
295 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd
->append_check
), FALSE
);
296 gtk_widget_show (tcd
->append_check
);
297 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_label
,0,2,7,8,GTK_FILL
,GTK_FILL
,2,2);
298 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->append_check
,2,6,7,8,GTK_FILL
,GTK_FILL
,0,0);
301 tcd
->optional_label
= gtk_label_new("Optional fields ");
302 gtk_widget_show (tcd
->optional_label
);
303 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->optional_label
,0,6,8,9,GTK_FILL
,GTK_FILL
,2,2);
305 tcd
->subbuf_size_label
= gtk_label_new("Subbuffer size:");
306 gtk_widget_show (tcd
->subbuf_size_label
);
307 tcd
->subbuf_size_entry
= gtk_entry_new();
308 gtk_widget_show (tcd
->subbuf_size_entry
);
309 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_size_label
,0,2,9,10,GTK_FILL
,GTK_FILL
,2,2);
310 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);
312 tcd
->subbuf_num_label
= gtk_label_new("Number of subbuffers:");
313 gtk_widget_show (tcd
->subbuf_num_label
);
314 tcd
->subbuf_num_entry
= gtk_entry_new();
315 gtk_widget_show (tcd
->subbuf_num_entry
);
316 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->subbuf_num_label
,0,2,10,11,GTK_FILL
,GTK_FILL
,2,2);
317 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);
319 tcd
->lttd_threads_label
= gtk_label_new("Number of lttd threads:");
320 gtk_widget_show (tcd
->lttd_threads_label
);
321 tcd
->lttd_threads_entry
= gtk_entry_new();
322 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_threads_entry
), "1");
323 gtk_widget_show (tcd
->lttd_threads_entry
);
324 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_threads_label
,0,2,11,12,GTK_FILL
,GTK_FILL
,2,2);
325 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);
327 tcd
->lttctl_path_label
= gtk_label_new("path to lttctl:");
328 gtk_widget_show (tcd
->lttctl_path_label
);
329 tcd
->lttctl_path_entry
= gtk_entry_new();
330 gtk_entry_set_text(GTK_ENTRY(tcd
->lttctl_path_entry
),PACKAGE_BIN_DIR
"/lttctl");
331 gtk_widget_show (tcd
->lttctl_path_entry
);
332 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttctl_path_label
,0,2,12,13,GTK_FILL
,GTK_FILL
,2,2);
333 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);
336 tcd
->lttd_path_label
= gtk_label_new("path to lttd:");
337 gtk_widget_show (tcd
->lttd_path_label
);
338 tcd
->lttd_path_entry
= gtk_entry_new();
339 gtk_entry_set_text(GTK_ENTRY(tcd
->lttd_path_entry
),PACKAGE_BIN_DIR
"/lttd");
340 gtk_widget_show (tcd
->lttd_path_entry
);
341 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->lttd_path_label
,0,2,13,14,GTK_FILL
,GTK_FILL
,2,2);
342 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);
345 tcd
->fac_path_label
= gtk_label_new("path to facilities:");
346 gtk_widget_show (tcd
->fac_path_label
);
347 tcd
->fac_path_entry
= gtk_entry_new();
348 gtk_entry_set_text(GTK_ENTRY(tcd
->fac_path_entry
),PACKAGE_DATA_DIR
"/" "ltt-control" "/facilities");
349 gtk_widget_set_size_request(tcd
->fac_path_entry
, 250, -1);
350 gtk_widget_show (tcd
->fac_path_entry
);
351 gtk_table_attach( GTK_TABLE(tcd
->main_box
),tcd
->fac_path_label
,0,2,14,15,GTK_FILL
,GTK_FILL
,2,2);
352 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);
354 focus_chain
= g_list_append (focus_chain
, tcd
->username_entry
);
355 focus_chain
= g_list_append (focus_chain
, tcd
->password_entry
);
356 focus_chain
= g_list_append (focus_chain
, tcd
->start_button
);
357 focus_chain
= g_list_append (focus_chain
, tcd
->pause_button
);
358 focus_chain
= g_list_append (focus_chain
, tcd
->unpause_button
);
359 focus_chain
= g_list_append (focus_chain
, tcd
->stop_button
);
360 focus_chain
= g_list_append (focus_chain
, tcd
->channel_dir_entry
);
361 focus_chain
= g_list_append (focus_chain
, tcd
->trace_dir_entry
);
362 focus_chain
= g_list_append (focus_chain
, tcd
->trace_name_entry
);
363 focus_chain
= g_list_append (focus_chain
, tcd
->trace_mode_combo
);
364 focus_chain
= g_list_append (focus_chain
, tcd
->start_daemon_check
);
365 focus_chain
= g_list_append (focus_chain
, tcd
->append_check
);
366 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_size_entry
);
367 focus_chain
= g_list_append (focus_chain
, tcd
->subbuf_num_entry
);
368 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_threads_entry
);
369 focus_chain
= g_list_append (focus_chain
, tcd
->lttctl_path_entry
);
370 focus_chain
= g_list_append (focus_chain
, tcd
->lttd_path_entry
);
371 focus_chain
= g_list_append (focus_chain
, tcd
->fac_path_entry
);
373 gtk_container_set_focus_chain(GTK_CONTAINER(tcd
->main_box
), focus_chain
);
375 g_list_free(focus_chain
);
377 g_signal_connect(G_OBJECT(tcd
->start_button
), "clicked",
378 (GCallback
)start_clicked
, tcd
);
379 g_signal_connect(G_OBJECT(tcd
->pause_button
), "clicked",
380 (GCallback
)pause_clicked
, tcd
);
381 g_signal_connect(G_OBJECT(tcd
->unpause_button
), "clicked",
382 (GCallback
)unpause_clicked
, tcd
);
383 g_signal_connect(G_OBJECT(tcd
->stop_button
), "clicked",
384 (GCallback
)stop_clicked
, tcd
);
387 * show main container
389 gtk_widget_show(tcd
->main_box
);
390 gtk_widget_show(tcd
->window
);
393 g_object_set_data_full(
394 G_OBJECT(guicontrol_get_widget(tcd
)),
395 "control_viewer_data",
397 (GDestroyNotify
)gui_control_destructor
);
399 g_control_list
= g_slist_append(
408 * @fn void gui_control_destructor(ControlData*)
410 * Destructor for the filter gui module
411 * @param tcd The module structure
414 gui_control_destructor(ControlData
*tcd
)
418 /* May already been done by GTK window closing */
419 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
))){
420 g_info("widget still exists");
423 // lttvwindow_unregister_traceset_notify(tcd->tab,
424 // filter_traceset_changed,
425 // filter_viewer_data);
427 lttvwindowtraces_background_notify_remove(tcd
);
429 g_control_list
= g_slist_remove(g_control_list
, tcd
);
434 static int execute_command(const gchar
*command
, const gchar
*username
,
435 const gchar
*password
, const gchar
*lttd_path
, const gchar
*fac_path
)
439 pid
= forkpty(&fdpty
, NULL
, NULL
, NULL
);
447 /* discuss with su */
448 struct timeval timeout
;
452 struct pollfd pollfd
;
455 enum read_state
{ GET_LINE
, GET_SEMI
, GET_SPACE
} read_state
= GET_LINE
;
457 retval
= fcntl(fdpty
, F_SETFL
, O_WRONLY
);
459 perror("Error in fcntl");
463 /* Read the output from the child terminal before the prompt. If no data in
464 * 200 ms, we stop reading to give the password */
465 g_info("Reading from child console...");
468 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
470 num_rdy
= poll(&pollfd
, 1, -1);
472 perror("Poll error");
476 /* Timeout : Stop waiting for chars */
477 if(num_rdy
== 0) goto wait_child
;
479 switch(pollfd
.revents
) {
481 g_warning("Error returned in polling fd\n");
485 g_info("Polling FD : hung up.");
489 g_warning("Polling fd tells it is not open");
494 count
= read (fdpty
, buf
, 256);
499 for(i
=0; i
<count
; i
++) {
503 read_state
= GET_SEMI
;
504 g_debug("Tracecontrol input line skip\n");
509 g_debug("Tracecontrol input : marker found\n");
510 read_state
= GET_SPACE
;
515 g_debug("Tracecontrol input space marker found\n");
521 } else if(count
== -1) {
522 perror("Error in read");
528 g_warning("Child hung up too fast");
535 pollfd
.events
= POLLOUT
|POLLERR
|POLLHUP
|POLLNVAL
;
537 num_rdy
= poll(&pollfd
, 1, -1);
539 perror("Poll error");
543 /* Write the password */
544 g_info("Got su prompt, now writing password...");
547 ret
= write(fdpty
, password
, strlen(password
));
548 if(ret
< 0) perror("Error in write");
549 ret
= write(fdpty
, "\n", 1);
550 if(ret
< 0) perror("Error in write");
552 /* Take the output from the terminal and show it on the real console */
553 g_info("Getting data from child terminal...");
557 pollfd
.events
= POLLIN
|POLLPRI
|POLLERR
|POLLHUP
|POLLNVAL
;
559 num_rdy
= poll(&pollfd
, 1, -1);
561 perror("Poll error");
564 if(num_rdy
== 0) break;
566 if(pollfd
.revents
& (POLLERR
|POLLNVAL
)) {
567 g_warning("Error returned in polling fd\n");
571 if(pollfd
.revents
& (POLLIN
|POLLPRI
) ) {
572 count
= read (fdpty
, buf
, 256);
576 } else if(count
== -1) {
577 perror("Error in read");
582 if(pollfd
.revents
& POLLHUP
) {
583 g_info("Polling FD : hung up.");
587 if(num_hup
> 0) goto wait_child
;
590 g_info("Waiting for child exit...");
592 ret
= waitpid(pid
, &status
, 0);
595 g_warning("An error occured in wait : %s",
598 if(WIFEXITED(status
))
599 if(WEXITSTATUS(status
) != 0) {
600 retval
= WEXITSTATUS(status
);
601 g_warning("An error occured in the su command : %s",
606 g_info("Child exited.");
608 } else if(pid
== 0) {
609 /* Setup environment variables */
610 if(strcmp(lttd_path
, "") != 0)
611 setenv("LTT_DAEMON", lttd_path
, 1);
612 if(strcmp(fac_path
, "") != 0)
613 setenv("LTT_FACILITIES", fac_path
, 1);
615 /* One comment line (must be only one) */
616 g_printf("Executing (as %s) : %s\n", username
, command
);
618 execlp("su", "su", "-p", "-c", command
, username
, NULL
);
619 exit(-1); /* not supposed to happen! */
621 //gint ret = execvp();
625 g_warning("Error happened when forking for su");
634 void start_clicked (GtkButton
*button
, gpointer user_data
)
636 ControlData
*tcd
= (ControlData
*)user_data
;
638 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
639 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
640 const gchar
*channel_dir
=
641 gtk_entry_get_text(GTK_ENTRY(tcd
->channel_dir_entry
));
642 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
643 const gchar
*trace_name
=
644 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
646 const gchar
*trace_mode_sel
;
649 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(tcd
->trace_mode_combo
), &iter
);
651 gtk_combo_box_get_model(GTK_COMBO_BOX(tcd
->trace_mode_combo
)),
652 &iter
, 0, &trace_mode_sel
, -1);
653 //const gchar *trace_mode_sel =
654 //2.6+ gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
655 const gchar
*trace_mode
;
656 if(strcmp(trace_mode_sel
, "normal") == 0)
657 trace_mode
= "normal";
659 trace_mode
= "flight";
661 gboolean start_daemon
=
662 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->start_daemon_check
));
665 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd
->append_check
));
667 const gchar
*subbuf_size
=
668 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_size_entry
));
669 const gchar
*subbuf_num
=
670 gtk_entry_get_text(GTK_ENTRY(tcd
->subbuf_num_entry
));
671 const gchar
*threads_num
=
672 gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_threads_entry
));
673 const gchar
*lttctl_path
=
674 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
675 const gchar
*lttd_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->lttd_path_entry
));
676 const gchar
*fac_path
= gtk_entry_get_text(GTK_ENTRY(tcd
->fac_path_entry
));
679 /* Setup arguments to su */
681 gchar args
[MAX_ARGS_LEN
];
682 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
687 strncat(args
, "exec", args_left
);
688 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
691 strncat(args
, " ", args_left
);
692 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
694 if(strcmp(lttctl_path
, "") == 0)
695 strncat(args
, "lttctl", args_left
);
697 strncat(args
, lttctl_path
, args_left
);
698 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
701 strncat(args
, " ", args_left
);
702 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
705 strncat(args
, "-l ", args_left
);
706 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
707 strncat(args
, channel_dir
, args_left
);
708 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
711 strncat(args
, " ", args_left
);
712 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
715 strncat(args
, "-t ", args_left
);
716 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
717 strncat(args
, trace_dir
, args_left
);
718 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
721 strncat(args
, " ", args_left
);
722 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
725 strncat(args
, "-n ", args_left
);
726 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
727 strncat(args
, trace_name
, args_left
);
728 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
731 strncat(args
, " ", args_left
);
732 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
735 strncat(args
, "-m ", args_left
);
736 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
737 strncat(args
, trace_mode
, args_left
);
738 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
741 strncat(args
, " ", args_left
);
742 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
746 strncat(args
, "-d", args_left
);
747 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
749 /* Simply create the channel and then start tracing */
750 strncat(args
, "-b", args_left
);
751 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
755 /* Append to trace ? */
758 strncat(args
, " ", args_left
);
759 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
760 strncat(args
, "-a", args_left
);
761 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
764 /* optional arguments */
766 if(strcmp(subbuf_size
, "") != 0) {
768 strncat(args
, " ", args_left
);
769 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
771 strncat(args
, "-z ", args_left
);
772 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
773 strncat(args
, subbuf_size
, args_left
);
774 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
777 /* number of subbuffers */
778 if(strcmp(subbuf_num
, "") != 0) {
780 strncat(args
, " ", args_left
);
781 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
783 strncat(args
, "-x ", args_left
);
784 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
785 strncat(args
, subbuf_num
, args_left
);
786 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
789 /* number of lttd threads */
790 if(strcmp(threads_num
, "") != 0) {
792 strncat(args
, " ", args_left
);
793 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
795 strncat(args
, "-N ", args_left
);
796 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
797 strncat(args
, threads_num
, args_left
);
798 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
802 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
806 guint msg_left
= 256;
808 strcpy(msg
, "A problem occured when executing the su command : ");
809 msg_left
= 256 - strlen(msg
) - 1;
810 strncat(msg
, strerror(retval
), msg_left
);
811 GtkWidget
*dialogue
=
812 gtk_message_dialog_new(
813 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
814 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
818 gtk_dialog_run(GTK_DIALOG(dialogue
));
819 gtk_widget_destroy(dialogue
);
825 void pause_clicked (GtkButton
*button
, gpointer user_data
)
827 ControlData
*tcd
= (ControlData
*)user_data
;
829 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
830 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
831 const gchar
*trace_name
=
832 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
833 const gchar
*lttd_path
= "";
834 const gchar
*fac_path
= "";
836 const gchar
*lttctl_path
=
837 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
839 /* Setup arguments to su */
841 gchar args
[MAX_ARGS_LEN
];
842 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
847 strncat(args
, "exec", 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;
854 if(strcmp(lttctl_path
, "") == 0)
855 strncat(args
, "lttctl", args_left
);
857 strncat(args
, lttctl_path
, args_left
);
858 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
861 strncat(args
, " ", args_left
);
862 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
865 strncat(args
, "-n ", args_left
);
866 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
867 strncat(args
, trace_name
, args_left
);
868 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
871 strncat(args
, " ", args_left
);
872 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
874 /* Simply pause tracing */
875 strncat(args
, "-q", args_left
);
876 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
878 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
881 guint msg_left
= 256;
883 strcpy(msg
, "A problem occured when executing the su command : ");
884 msg_left
= 256 - strlen(msg
) - 1;
885 strncat(msg
, strerror(retval
), msg_left
);
886 GtkWidget
*dialogue
=
887 gtk_message_dialog_new(
888 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
889 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
893 gtk_dialog_run(GTK_DIALOG(dialogue
));
894 gtk_widget_destroy(dialogue
);
899 void unpause_clicked (GtkButton
*button
, gpointer user_data
)
901 ControlData
*tcd
= (ControlData
*)user_data
;
903 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
904 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
905 const gchar
*trace_name
=
906 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
907 const gchar
*lttd_path
= "";
908 const gchar
*fac_path
= "";
910 const gchar
*lttctl_path
=
911 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
913 /* Setup arguments to su */
915 gchar args
[MAX_ARGS_LEN
];
916 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
921 strncat(args
, "exec", args_left
);
922 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
925 strncat(args
, " ", args_left
);
926 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
928 if(strcmp(lttctl_path
, "") == 0)
929 strncat(args
, "lttctl", args_left
);
931 strncat(args
, lttctl_path
, args_left
);
932 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
935 strncat(args
, " ", args_left
);
936 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
939 strncat(args
, "-n ", args_left
);
940 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
941 strncat(args
, trace_name
, args_left
);
942 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
945 strncat(args
, " ", args_left
);
946 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
948 /* Simply unpause tracing */
949 strncat(args
, "-s", args_left
);
950 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
952 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
955 guint msg_left
= 256;
957 strcpy(msg
, "A problem occured when executing the su command : ");
958 msg_left
= 256 - strlen(msg
) - 1;
959 strncat(msg
, strerror(retval
), msg_left
);
960 GtkWidget
*dialogue
=
961 gtk_message_dialog_new(
962 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
963 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
967 gtk_dialog_run(GTK_DIALOG(dialogue
));
968 gtk_widget_destroy(dialogue
);
973 void stop_clicked (GtkButton
*button
, gpointer user_data
)
975 ControlData
*tcd
= (ControlData
*)user_data
;
977 const gchar
*username
= gtk_entry_get_text(GTK_ENTRY(tcd
->username_entry
));
978 const gchar
*password
= gtk_entry_get_text(GTK_ENTRY(tcd
->password_entry
));
979 const gchar
*trace_name
=
980 gtk_entry_get_text(GTK_ENTRY(tcd
->trace_name_entry
));
981 const gchar
*lttd_path
= "";
982 const gchar
*fac_path
= "";
984 const gchar
*lttctl_path
=
985 gtk_entry_get_text(GTK_ENTRY(tcd
->lttctl_path_entry
));
986 const gchar
*trace_dir
= gtk_entry_get_text(GTK_ENTRY(tcd
->trace_dir_entry
));
988 /* Setup arguments to su */
990 gchar args
[MAX_ARGS_LEN
];
991 gint args_left
= MAX_ARGS_LEN
- 1; /* for \0 */
996 strncat(args
, "exec", args_left
);
997 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1000 strncat(args
, " ", args_left
);
1001 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1003 if(strcmp(lttctl_path
, "") == 0)
1004 strncat(args
, "lttctl", args_left
);
1006 strncat(args
, lttctl_path
, args_left
);
1007 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1010 strncat(args
, " ", args_left
);
1011 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1014 strncat(args
, "-n ", args_left
);
1015 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1016 strncat(args
, trace_name
, args_left
);
1017 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1020 strncat(args
, " ", args_left
);
1021 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1023 /* Simply stop tracing and destroy channel */
1024 strncat(args
, "-R", args_left
);
1025 args_left
= MAX_ARGS_LEN
- strlen(args
) - 1;
1027 int retval
= execute_command(args
, username
, password
, lttd_path
, fac_path
);
1030 guint msg_left
= 256;
1032 strcpy(msg
, "A problem occured when executing the su command : ");
1033 msg_left
= 256 - strlen(msg
) - 1;
1034 strncat(msg
, strerror(retval
), msg_left
);
1035 GtkWidget
*dialogue
=
1036 gtk_message_dialog_new(
1037 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1038 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1042 gtk_dialog_run(GTK_DIALOG(dialogue
));
1043 gtk_widget_destroy(dialogue
);
1048 /* Ask to the user if he wants to open the trace in a new window */
1049 GtkWidget
*dialogue
;
1053 dialogue
= gtk_dialog_new_with_buttons("Open trace ?",
1054 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button
))),
1055 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
1056 GTK_STOCK_YES
,GTK_RESPONSE_ACCEPT
,
1057 GTK_STOCK_NO
,GTK_RESPONSE_REJECT
,
1059 label
= gtk_label_new("Do you want to open the trace in LTTV ?");
1060 gtk_widget_show(label
);
1062 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue
)->vbox
),
1065 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
1068 case GTK_RESPONSE_ACCEPT
:
1070 create_main_window_with_trace(trace_dir
);
1073 case GTK_RESPONSE_REJECT
:
1077 gtk_widget_destroy(dialogue
);
1083 * @fn GtkWidget* h_guicontrol(Tab*)
1085 * Control Module's constructor hook
1087 * This constructor is given as a parameter to the menuitem and toolbar button
1088 * registration. It creates the list.
1089 * @param tab A pointer to the parent window.
1090 * @return The widget created.
1093 h_guicontrol(GObject
*obj
)
1095 ControlData
* f
= gui_control(obj
);
1101 * @fn static void init()
1103 * This function initializes the Filter Viewer functionnality through the
1106 static void init() {
1108 lttvwindow_register_constructor("guicontrol",
1110 "Insert Tracing Control Module",
1111 hTraceControlInsert_xpm
,
1112 "Insert Tracing Control Module",
1117 * @fn void control_destroy_walk(gpointer,gpointer)
1119 * Initiate the destruction of the current gui module
1120 * on the GTK Interface
1123 control_destroy_walk(gpointer data
, gpointer user_data
)
1125 ControlData
*tcd
= (ControlData
*)data
;
1127 g_debug("traceontrol.c : control_destroy_walk, %p", tcd
);
1129 /* May already have been done by GTK window closing */
1130 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd
)))
1131 gtk_widget_destroy(guicontrol_get_widget(tcd
));
1135 * @fn static void destroy()
1136 * @brief plugin's destroy function
1138 * This function releases the memory reserved by the module and unregisters
1139 * everything that has been registered in the gtkTraceSet API.
1141 static void destroy() {
1143 g_slist_foreach(g_control_list
, control_destroy_walk
, NULL
);
1145 lttvwindow_unregister_constructor(h_guicontrol
);
1150 LTTV_MODULE("guitracecontrol", "Trace Control Window", \
1151 "Graphical module that let user control kernel tracing", \
1152 init
, destroy
, "lttvwindow")