fixes to control flow view GC
[lttv.git] / ltt / branches / poly / lttv / modules / gui / tracecontrol / tracecontrol.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2005 Mathieu Desnoyers
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <glib.h>
24 #include <string.h>
25 #include <gtk/gtk.h>
26 #include <gdk/gdk.h>
27 #include <gdk/gdkkeysyms.h>
28
29 #include <lttv/lttv.h>
30 #include <lttv/module.h>
31 #include <lttv/hook.h>
32
33 #include <lttvwindow/lttvwindow.h>
34 #include <lttvwindow/lttvwindowtraces.h>
35
36 #include "hTraceControlInsert.xpm"
37 #include "TraceControlStart.xpm"
38 #include "TraceControlPause.xpm"
39 #include "TraceControlStop.xpm"
40
41 #include <sys/types.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <pty.h>
45 #include <utmp.h>
46 #include <sys/wait.h>
47 #include <sys/poll.h>
48 #include <errno.h>
49
50 #define MAX_ARGS_LEN PATH_MAX * 10
51
52 GSList *g_control_list = NULL ;
53
54 /*! \file lttv/modules/gui/tracecontrol/tracecontrol.c
55 * \brief Graphic trace start/stop control interface.
56 *
57 * This plugin interacts with lttctl to start/stop tracing. It needs to take the
58 * root password to be able to interact with lttctl.
59 *
60 */
61
62 typedef struct _ControlData ControlData;
63
64 /*
65 * Prototypes
66 */
67 GtkWidget *guicontrol_get_widget(ControlData *tcd);
68 ControlData *gui_control(Tab *tab);
69 void gui_control_destructor(ControlData *tcd);
70 GtkWidget* h_guicontrol(Tab *tab);
71 void control_destroy_walk(gpointer data, gpointer user_data);
72
73 /*
74 * Callback functions
75 */
76
77 static void start_clicked (GtkButton *button, gpointer user_data);
78 static void pause_clicked (GtkButton *button, gpointer user_data);
79 static void unpause_clicked (GtkButton *button, gpointer user_data);
80 static void stop_clicked (GtkButton *button, gpointer user_data);
81
82
83 /**
84 * @struct _ControlData
85 *
86 * @brief Main structure of gui control
87 */
88 struct _ControlData {
89 Tab *tab; /**< current tab of module */
90
91 GtkWidget *window; /**< window */
92
93 GtkWidget *main_box; /**< main container */
94 GtkWidget *start_button;
95 GtkWidget *pause_button;
96 GtkWidget *unpause_button;
97 GtkWidget *stop_button;
98 GtkWidget *username_label;
99 GtkWidget *username_entry;
100 GtkWidget *password_label;
101 GtkWidget *password_entry;
102 GtkWidget *channel_dir_label;
103 GtkWidget *channel_dir_entry;
104 GtkWidget *trace_dir_label;
105 GtkWidget *trace_dir_entry;
106 GtkWidget *trace_name_label;
107 GtkWidget *trace_name_entry;
108 GtkWidget *trace_mode_label;
109 GtkWidget *trace_mode_combo;
110 GtkWidget *start_daemon_label;
111 GtkWidget *start_daemon_check;
112 GtkWidget *append_label;
113 GtkWidget *append_check;
114 GtkWidget *optional_label;
115 GtkWidget *subbuf_size_label;
116 GtkWidget *subbuf_size_entry;
117 GtkWidget *subbuf_num_label;
118 GtkWidget *subbuf_num_entry;
119 GtkWidget *lttctl_path_label;
120 GtkWidget *lttctl_path_entry;
121 GtkWidget *lttd_path_label;
122 GtkWidget *lttd_path_entry;
123 GtkWidget *fac_path_label;
124 GtkWidget *fac_path_entry;
125 };
126
127 /**
128 * @fn GtkWidget* guicontrol_get_widget(ControlData*)
129 *
130 * This function returns the current main widget
131 * used by this module
132 * @param tcd the module struct
133 * @return The main widget
134 */
135 GtkWidget*
136 guicontrol_get_widget(ControlData *tcd)
137 {
138 return tcd->window;
139 }
140
141 /**
142 * @fn ControlData* gui_control(Tab*)
143 *
144 * Constructor is used to create ControlData data structure.
145 * @param tab The tab structure used by the widget
146 * @return The Filter viewer data created.
147 */
148 ControlData*
149 gui_control(Tab *tab)
150 {
151 g_debug("filter::gui_control()");
152
153 unsigned i;
154 GtkCellRenderer *renderer;
155 GtkTreeViewColumn *column;
156
157 ControlData* tcd = g_new(ControlData,1);
158
159 tcd->tab = tab;
160
161 tcd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
162 gtk_window_set_title(GTK_WINDOW(tcd->window), "LTTng Trace Control");
163 /*
164 * Initiating GtkTable layout
165 * starts with 2 rows and 5 columns and
166 * expands when expressions added
167 */
168 tcd->main_box = gtk_table_new(14,7,FALSE);
169 gtk_table_set_row_spacings(GTK_TABLE(tcd->main_box),5);
170 gtk_table_set_col_spacings(GTK_TABLE(tcd->main_box),5);
171
172 gtk_container_add(GTK_CONTAINER(tcd->window), GTK_WIDGET(tcd->main_box));
173
174 GList *focus_chain = NULL;
175
176 /*
177 * start/pause/stop buttons
178 */
179 GdkPixbuf *pixbuf;
180 GtkWidget *image;
181 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStart_xpm);
182 image = gtk_image_new_from_pixbuf(pixbuf);
183 tcd->start_button = gtk_button_new_with_label("start");
184 gtk_button_set_image(GTK_BUTTON(tcd->start_button), image);
185 gtk_button_set_alignment(GTK_BUTTON(tcd->start_button), 0.0, 0.0);
186 gtk_widget_show (tcd->start_button);
187 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->start_button,6,7,0,1,GTK_FILL,GTK_FILL,2,2);
188
189 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm);
190 image = gtk_image_new_from_pixbuf(pixbuf);
191 tcd->pause_button = gtk_button_new_with_label("pause");
192 gtk_button_set_image(GTK_BUTTON(tcd->pause_button), image);
193 gtk_button_set_alignment(GTK_BUTTON(tcd->pause_button), 0.0, 0.0);
194 gtk_widget_show (tcd->pause_button);
195 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->pause_button,6,7,1,2,GTK_FILL,GTK_FILL,2,2);
196
197 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm);
198 image = gtk_image_new_from_pixbuf(pixbuf);
199 tcd->unpause_button = gtk_button_new_with_label("unpause");
200 gtk_button_set_image(GTK_BUTTON(tcd->unpause_button), image);
201 gtk_button_set_alignment(GTK_BUTTON(tcd->unpause_button), 0.0, 0.0);
202 gtk_widget_show (tcd->unpause_button);
203 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->unpause_button,6,7,2,3,GTK_FILL,GTK_FILL,2,2);
204
205 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStop_xpm);
206 image = gtk_image_new_from_pixbuf(pixbuf);
207 tcd->stop_button = gtk_button_new_with_label("stop");
208 gtk_button_set_image(GTK_BUTTON(tcd->stop_button), image);
209 gtk_button_set_alignment(GTK_BUTTON(tcd->stop_button), 0.0, 0.0);
210 gtk_widget_show (tcd->stop_button);
211 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->stop_button,6,7,3,4,GTK_FILL,GTK_FILL,2,2);
212
213 /*
214 * First half of the filter window
215 * - textual entry of filter expression
216 * - processing button
217 */
218 tcd->username_label = gtk_label_new("Username:");
219 gtk_widget_show (tcd->username_label);
220 tcd->username_entry = gtk_entry_new();
221 gtk_entry_set_text(GTK_ENTRY(tcd->username_entry),"root");
222 gtk_widget_show (tcd->username_entry);
223 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->username_label,0,2,0,1,GTK_FILL,GTK_FILL,2,2);
224 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);
225
226
227
228 tcd->password_label = gtk_label_new("Password:");
229 gtk_widget_show (tcd->password_label);
230 tcd->password_entry = gtk_entry_new();
231 gtk_entry_set_visibility(GTK_ENTRY(tcd->password_entry), FALSE);
232 gtk_widget_show (tcd->password_entry);
233 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->password_label,0,2,1,2,GTK_FILL,GTK_FILL,2,2);
234 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);
235
236
237 tcd->channel_dir_label = gtk_label_new("Channel directory:");
238 gtk_widget_show (tcd->channel_dir_label);
239 tcd->channel_dir_entry = gtk_entry_new();
240 gtk_entry_set_text(GTK_ENTRY(tcd->channel_dir_entry),"/mnt/relayfs/ltt");
241 gtk_widget_show (tcd->channel_dir_entry);
242 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->channel_dir_label,0,2,2,3,GTK_FILL,GTK_FILL,2,2);
243 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);
244
245 tcd->trace_dir_label = gtk_label_new("Trace directory:");
246 gtk_widget_show (tcd->trace_dir_label);
247 tcd->trace_dir_entry = gtk_entry_new();
248 gtk_entry_set_text(GTK_ENTRY(tcd->trace_dir_entry),"/tmp/trace1");
249 gtk_widget_show (tcd->trace_dir_entry);
250 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->trace_dir_label,0,2,3,4,GTK_FILL,GTK_FILL,2,2);
251 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);
252
253 tcd->trace_name_label = gtk_label_new("Trace name:");
254 gtk_widget_show (tcd->trace_name_label);
255 tcd->trace_name_entry = gtk_entry_new();
256 gtk_entry_set_text(GTK_ENTRY(tcd->trace_name_entry),"trace");
257 gtk_widget_show (tcd->trace_name_entry);
258 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->trace_name_label,0,2,4,5,GTK_FILL,GTK_FILL,2,2);
259 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);
260
261 tcd->trace_mode_label = gtk_label_new("Trace mode ");
262 gtk_widget_show (tcd->trace_mode_label);
263 tcd->trace_mode_combo = gtk_combo_box_new_text();
264 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd->trace_mode_combo),
265 "normal");
266 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd->trace_mode_combo),
267 "flight recorder");
268 gtk_combo_box_set_active(GTK_COMBO_BOX(tcd->trace_mode_combo), 0);
269 gtk_widget_show (tcd->trace_mode_combo);
270 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->trace_mode_label,0,2,5,6,GTK_FILL,GTK_FILL,2,2);
271 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);
272
273 tcd->start_daemon_label = gtk_label_new("Start daemon ");
274 gtk_widget_show (tcd->start_daemon_label);
275 tcd->start_daemon_check = gtk_check_button_new();
276 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd->start_daemon_check), TRUE);
277 gtk_widget_show (tcd->start_daemon_check);
278 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->start_daemon_label,0,2,6,7,GTK_FILL,GTK_FILL,2,2);
279 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->start_daemon_check,2,6,6,7,GTK_FILL,GTK_FILL,0,0);
280
281 tcd->append_label = gtk_label_new("Append to trace ");
282 gtk_widget_show (tcd->append_label);
283 tcd->append_check = gtk_check_button_new();
284 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tcd->append_check), FALSE);
285 gtk_widget_show (tcd->append_check);
286 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->append_label,0,2,7,8,GTK_FILL,GTK_FILL,2,2);
287 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->append_check,2,6,7,8,GTK_FILL,GTK_FILL,0,0);
288
289
290 tcd->optional_label = gtk_label_new("Optional fields ");
291 gtk_widget_show (tcd->optional_label);
292 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->optional_label,0,6,8,9,GTK_FILL,GTK_FILL,2,2);
293
294 tcd->subbuf_size_label = gtk_label_new("Subbuffer size:");
295 gtk_widget_show (tcd->subbuf_size_label);
296 tcd->subbuf_size_entry = gtk_entry_new();
297 gtk_widget_show (tcd->subbuf_size_entry);
298 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->subbuf_size_label,0,2,9,10,GTK_FILL,GTK_FILL,2,2);
299 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);
300
301 tcd->subbuf_num_label = gtk_label_new("Number of subbuffers:");
302 gtk_widget_show (tcd->subbuf_num_label);
303 tcd->subbuf_num_entry = gtk_entry_new();
304 gtk_widget_show (tcd->subbuf_num_entry);
305 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->subbuf_num_label,0,2,10,11,GTK_FILL,GTK_FILL,2,2);
306 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);
307
308 tcd->lttctl_path_label = gtk_label_new("path to lttctl:");
309 gtk_widget_show (tcd->lttctl_path_label);
310 tcd->lttctl_path_entry = gtk_entry_new();
311 gtk_entry_set_text(GTK_ENTRY(tcd->lttctl_path_entry),PACKAGE_BIN_DIR "/lttctl");
312 gtk_widget_show (tcd->lttctl_path_entry);
313 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttctl_path_label,0,2,11,12,GTK_FILL,GTK_FILL,2,2);
314 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttctl_path_entry,2,6,11,12,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0);
315
316
317 tcd->lttd_path_label = gtk_label_new("path to lttd:");
318 gtk_widget_show (tcd->lttd_path_label);
319 tcd->lttd_path_entry = gtk_entry_new();
320 gtk_entry_set_text(GTK_ENTRY(tcd->lttd_path_entry),PACKAGE_BIN_DIR "/lttd");
321 gtk_widget_show (tcd->lttd_path_entry);
322 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttd_path_label,0,2,12,13,GTK_FILL,GTK_FILL,2,2);
323 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->lttd_path_entry,2,6,12,13,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0);
324
325
326 tcd->fac_path_label = gtk_label_new("path to facilities:");
327 gtk_widget_show (tcd->fac_path_label);
328 tcd->fac_path_entry = gtk_entry_new();
329 gtk_entry_set_text(GTK_ENTRY(tcd->fac_path_entry),PACKAGE_DATA_DIR "/" PACKAGE "/facilities");
330 gtk_widget_set_size_request(tcd->fac_path_entry, 250, -1);
331 gtk_widget_show (tcd->fac_path_entry);
332 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->fac_path_label,0,2,13,14,GTK_FILL,GTK_FILL,2,2);
333 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->fac_path_entry,2,6,13,14,GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL,0,0);
334
335 focus_chain = g_list_append (focus_chain, tcd->username_entry);
336 focus_chain = g_list_append (focus_chain, tcd->password_entry);
337 focus_chain = g_list_append (focus_chain, tcd->start_button);
338 focus_chain = g_list_append (focus_chain, tcd->pause_button);
339 focus_chain = g_list_append (focus_chain, tcd->unpause_button);
340 focus_chain = g_list_append (focus_chain, tcd->stop_button);
341 focus_chain = g_list_append (focus_chain, tcd->channel_dir_entry);
342 focus_chain = g_list_append (focus_chain, tcd->trace_dir_entry);
343 focus_chain = g_list_append (focus_chain, tcd->trace_name_entry);
344 focus_chain = g_list_append (focus_chain, tcd->trace_mode_combo);
345 focus_chain = g_list_append (focus_chain, tcd->start_daemon_check);
346 focus_chain = g_list_append (focus_chain, tcd->append_check);
347 focus_chain = g_list_append (focus_chain, tcd->subbuf_size_entry);
348 focus_chain = g_list_append (focus_chain, tcd->subbuf_num_entry);
349 focus_chain = g_list_append (focus_chain, tcd->lttctl_path_entry);
350 focus_chain = g_list_append (focus_chain, tcd->lttd_path_entry);
351 focus_chain = g_list_append (focus_chain, tcd->fac_path_entry);
352
353 gtk_container_set_focus_chain(GTK_CONTAINER(tcd->main_box), focus_chain);
354
355 g_signal_connect(G_OBJECT(tcd->start_button), "clicked",
356 (GCallback)start_clicked, tcd);
357 g_signal_connect(G_OBJECT(tcd->pause_button), "clicked",
358 (GCallback)pause_clicked, tcd);
359 g_signal_connect(G_OBJECT(tcd->unpause_button), "clicked",
360 (GCallback)unpause_clicked, tcd);
361 g_signal_connect(G_OBJECT(tcd->stop_button), "clicked",
362 (GCallback)stop_clicked, tcd);
363
364 /*
365 * show main container
366 */
367 gtk_widget_show(tcd->main_box);
368 gtk_widget_show(tcd->window);
369
370
371 g_object_set_data_full(
372 G_OBJECT(guicontrol_get_widget(tcd)),
373 "control_viewer_data",
374 tcd,
375 (GDestroyNotify)gui_control_destructor);
376
377 g_control_list = g_slist_append(
378 g_control_list,
379 tcd);
380
381 return tcd;
382 }
383
384
385 /**
386 * @fn void gui_control_destructor(ControlData*)
387 *
388 * Destructor for the filter gui module
389 * @param tcd The module structure
390 */
391 void
392 gui_control_destructor(ControlData *tcd)
393 {
394 Tab *tab = tcd->tab;
395
396 /* May already been done by GTK window closing */
397 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd))){
398 g_info("widget still exists");
399 }
400 // if(tab != NULL) {
401 // lttvwindow_unregister_traceset_notify(tcd->tab,
402 // filter_traceset_changed,
403 // filter_viewer_data);
404 // }
405 lttvwindowtraces_background_notify_remove(tcd);
406
407 g_control_list = g_slist_remove(g_control_list, tcd);
408
409 g_free(tcd);
410 }
411
412 static int execute_command(const gchar *command, const gchar *username,
413 const gchar *password, const gchar *lttd_path, const gchar *fac_path)
414 {
415 pid_t pid;
416 int fdpty;
417 pid = forkpty(&fdpty, NULL, NULL, NULL);
418 int retval = 0;
419
420 if(pid > 0) {
421 /* parent */
422 gchar buf[256];
423 int status;
424 ssize_t count;
425 /* discuss with su */
426 struct timeval timeout;
427 timeout.tv_sec = 1;
428 timeout.tv_usec = 0;
429
430 struct pollfd pollfd;
431 int num_rdy;
432 int num_hup = 0;
433
434
435 /* Read the output from the child terminal before the prompt. If no data in
436 * 200 ms, we stop reading to give the password */
437 g_info("Reading from child console...");
438 while(1) {
439 pollfd.fd = fdpty;
440 pollfd.events = POLLIN|POLLPRI;
441
442 num_rdy = poll(&pollfd, 1, 200);
443 #if 0
444 if(num_rdy == -1) {
445 perror("Poll error");
446 goto wait_child;
447 }
448 #endif //0
449
450 /* Timeout : stop waiting for chars */
451 if(num_rdy == 0) break;
452
453 switch(pollfd.revents) {
454 case POLLERR:
455 g_warning("Error returned in polling fd\n");
456 num_hup++;
457 break;
458 case POLLHUP:
459 g_info("Polling FD : hung up.");
460 num_hup++;
461 break;
462 case POLLNVAL:
463 g_warning("Polling fd tells it is not open");
464 num_hup++;
465 break;
466 case POLLPRI:
467 case POLLIN:
468 count = read (fdpty, buf, 256);
469 if(count > 0) {
470 buf[count] = '\0';
471 printf("%s", buf);
472 } else if(count == -1) {
473 perror("Error in read");
474 goto wait_child;
475 }
476 break;
477 }
478 if(num_hup > 0) {
479 g_warning("Child hung up too fast");
480 goto wait_child;
481 }
482 }
483
484 /* Write the password */
485 g_info("Got su prompt, now writing password...");
486 int ret;
487 ret = write(fdpty, password, strlen(password));
488 if(ret < 0) perror("Error in write");
489 ret = write(fdpty, "\n", 1);
490 if(ret < 0) perror("Error in write");
491 fsync(fdpty);
492
493 /* Take the output from the terminal and show it on the real console */
494 g_info("Getting data from child terminal...");
495 while(1) {
496 int num_hup = 0;
497 pollfd.fd = fdpty;
498 pollfd.events = POLLIN|POLLPRI;
499
500 num_rdy = poll(&pollfd, 1, -1);
501 #if 0
502 if(num_rdy == -1) {
503 perror("Poll error");
504 goto wait_child;
505 }
506 #endif //0
507 if(num_rdy == 0) break;
508
509 switch(pollfd.revents) {
510 case POLLERR:
511 g_warning("Error returned in polling fd\n");
512 num_hup++;
513 break;
514 case POLLHUP:
515 g_info("Polling FD : hung up.");
516 num_hup++;
517 break;
518 case POLLNVAL:
519 g_warning("Polling fd tells it is not open");
520 num_hup++;
521 break;
522 case POLLPRI:
523 case POLLIN:
524 count = read (fdpty, buf, 256);
525 if(count > 0) {
526 buf[count] = '\0';
527 printf("%s", buf);
528 } else if(count == -1) {
529 perror("Error in read");
530 goto wait_child;
531 }
532 break;
533 }
534 if(num_hup > 0) goto wait_child;
535 }
536 wait_child:
537 g_info("Waiting for child exit...");
538
539 ret = waitpid(pid, &status, 0);
540
541 if(ret == -1) {
542 g_warning("An error occured in wait : %s",
543 strerror(errno));
544 } else {
545 if(WIFEXITED(status))
546 if(WEXITSTATUS(status) != 0) {
547 retval = WEXITSTATUS(status);
548 g_warning("An error occured in the su command : %s",
549 strerror(retval));
550 }
551 }
552
553 g_info("Child exited.");
554
555 } else if(pid == 0) {
556 /* Setup environment variables */
557 if(strcmp(lttd_path, "") != 0)
558 setenv("LTT_DAEMON", lttd_path, 1);
559 if(strcmp(fac_path, "") != 0)
560 setenv("LTT_FACILITIES", fac_path, 1);
561
562 g_message("Executing (as %s) : %s\n", username, command);
563
564 execlp("su", "su", "-p", "-c", command, username, NULL);
565 exit(-1); /* not supposed to happen! */
566
567 //gint ret = execvp();
568
569 } else {
570 /* error */
571 g_warning("Error happened when forking for su");
572 }
573
574 return retval;
575 }
576
577
578 /* Callbacks */
579
580 void start_clicked (GtkButton *button, gpointer user_data)
581 {
582 ControlData *tcd = (ControlData*)user_data;
583
584 const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
585 const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
586 const gchar *channel_dir =
587 gtk_entry_get_text(GTK_ENTRY(tcd->channel_dir_entry));
588 const gchar *trace_dir = gtk_entry_get_text(GTK_ENTRY(tcd->trace_dir_entry));
589 const gchar *trace_name =
590 gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
591
592 const gchar *trace_mode_sel =
593 gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
594 const gchar *trace_mode;
595 if(strcmp(trace_mode_sel, "normal") == 0)
596 trace_mode = "normal";
597 else
598 trace_mode = "flight";
599
600 gboolean start_daemon =
601 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd->start_daemon_check));
602
603 gboolean append =
604 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd->append_check));
605
606 const gchar *subbuf_size =
607 gtk_entry_get_text(GTK_ENTRY(tcd->subbuf_size_entry));
608 const gchar *subbuf_num =
609 gtk_entry_get_text(GTK_ENTRY(tcd->subbuf_num_entry));
610 const gchar *lttctl_path =
611 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
612 const gchar *lttd_path = gtk_entry_get_text(GTK_ENTRY(tcd->lttd_path_entry));
613 const gchar *fac_path = gtk_entry_get_text(GTK_ENTRY(tcd->fac_path_entry));
614
615
616 /* Setup arguments to su */
617 /* child */
618 gchar args[MAX_ARGS_LEN];
619 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
620
621 args[0] = '\0';
622
623 /* Command */
624 strncat(args, "exec", args_left);
625 args_left = MAX_ARGS_LEN - strlen(args) - 1;
626
627 /* space */
628 strncat(args, " ", args_left);
629 args_left = MAX_ARGS_LEN - strlen(args) - 1;
630
631 if(strcmp(lttctl_path, "") == 0)
632 strncat(args, "lttctl", args_left);
633 else
634 strncat(args, lttctl_path, args_left);
635 args_left = MAX_ARGS_LEN - strlen(args) - 1;
636
637 /* space */
638 strncat(args, " ", args_left);
639 args_left = MAX_ARGS_LEN - strlen(args) - 1;
640
641 /* channel dir */
642 strncat(args, "-l ", args_left);
643 args_left = MAX_ARGS_LEN - strlen(args) - 1;
644 strncat(args, channel_dir, args_left);
645 args_left = MAX_ARGS_LEN - strlen(args) - 1;
646
647 /* space */
648 strncat(args, " ", args_left);
649 args_left = MAX_ARGS_LEN - strlen(args) - 1;
650
651 /* trace dir */
652 strncat(args, "-t ", args_left);
653 args_left = MAX_ARGS_LEN - strlen(args) - 1;
654 strncat(args, trace_dir, args_left);
655 args_left = MAX_ARGS_LEN - strlen(args) - 1;
656
657 /* space */
658 strncat(args, " ", args_left);
659 args_left = MAX_ARGS_LEN - strlen(args) - 1;
660
661 /* name */
662 strncat(args, "-n ", args_left);
663 args_left = MAX_ARGS_LEN - strlen(args) - 1;
664 strncat(args, trace_name, args_left);
665 args_left = MAX_ARGS_LEN - strlen(args) - 1;
666
667 /* space */
668 strncat(args, " ", args_left);
669 args_left = MAX_ARGS_LEN - strlen(args) - 1;
670
671 /* trace mode */
672 strncat(args, "-m ", args_left);
673 args_left = MAX_ARGS_LEN - strlen(args) - 1;
674 strncat(args, trace_mode, args_left);
675 args_left = MAX_ARGS_LEN - strlen(args) - 1;
676
677 /* space */
678 strncat(args, " ", args_left);
679 args_left = MAX_ARGS_LEN - strlen(args) - 1;
680
681 /* Start daemon ? */
682 if(start_daemon) {
683 strncat(args, "-d", args_left);
684 args_left = MAX_ARGS_LEN - strlen(args) - 1;
685 } else {
686 /* Simply create the channel and then start tracing */
687 strncat(args, "-b", args_left);
688 args_left = MAX_ARGS_LEN - strlen(args) - 1;
689 }
690
691
692 /* Append to trace ? */
693 if(append) {
694 /* space */
695 strncat(args, " ", args_left);
696 args_left = MAX_ARGS_LEN - strlen(args) - 1;
697 strncat(args, "-a", args_left);
698 args_left = MAX_ARGS_LEN - strlen(args) - 1;
699 }
700
701 /* optional arguments */
702 /* subbuffer size */
703 if(strcmp(subbuf_size, "") != 0) {
704 /* space */
705 strncat(args, " ", args_left);
706 args_left = MAX_ARGS_LEN - strlen(args) - 1;
707
708 strncat(args, "-z ", args_left);
709 args_left = MAX_ARGS_LEN - strlen(args) - 1;
710 strncat(args, subbuf_size, args_left);
711 args_left = MAX_ARGS_LEN - strlen(args) - 1;
712 }
713
714 /* number of subbuffers */
715 if(strcmp(subbuf_num, "") != 0) {
716 /* space */
717 strncat(args, " ", args_left);
718 args_left = MAX_ARGS_LEN - strlen(args) - 1;
719
720 strncat(args, "-x ", args_left);
721 args_left = MAX_ARGS_LEN - strlen(args) - 1;
722 strncat(args, subbuf_num, args_left);
723 args_left = MAX_ARGS_LEN - strlen(args) - 1;
724 }
725
726
727 int retval = execute_command(args, username, password, lttd_path, fac_path);
728
729 if(retval) {
730 gchar msg[256];
731 guint msg_left = 256;
732
733 strcpy(msg, "A problem occured when executing the su command : ");
734 msg_left = 256 - strlen(msg) - 1;
735 strncat(msg, strerror(retval), msg_left);
736 GtkWidget *dialogue =
737 gtk_message_dialog_new(
738 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
739 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
740 GTK_MESSAGE_ERROR,
741 GTK_BUTTONS_OK,
742 msg);
743 gtk_dialog_run(GTK_DIALOG(dialogue));
744 gtk_widget_destroy(dialogue);
745 }
746
747 }
748
749
750 void pause_clicked (GtkButton *button, gpointer user_data)
751 {
752 ControlData *tcd = (ControlData*)user_data;
753
754 const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
755 const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
756 const gchar *trace_name =
757 gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
758 const gchar *lttd_path = "";
759 const gchar *fac_path = "";
760
761 const gchar *lttctl_path =
762 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
763
764 /* Setup arguments to su */
765 /* child */
766 gchar args[MAX_ARGS_LEN];
767 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
768
769 args[0] = '\0';
770
771 /* Command */
772 strncat(args, "exec", args_left);
773 args_left = MAX_ARGS_LEN - strlen(args) - 1;
774
775 /* space */
776 strncat(args, " ", args_left);
777 args_left = MAX_ARGS_LEN - strlen(args) - 1;
778
779 if(strcmp(lttctl_path, "") == 0)
780 strncat(args, "lttctl", args_left);
781 else
782 strncat(args, lttctl_path, args_left);
783 args_left = MAX_ARGS_LEN - strlen(args) - 1;
784
785 /* space */
786 strncat(args, " ", args_left);
787 args_left = MAX_ARGS_LEN - strlen(args) - 1;
788
789 /* name */
790 strncat(args, "-n ", args_left);
791 args_left = MAX_ARGS_LEN - strlen(args) - 1;
792 strncat(args, trace_name, args_left);
793 args_left = MAX_ARGS_LEN - strlen(args) - 1;
794
795 /* space */
796 strncat(args, " ", args_left);
797 args_left = MAX_ARGS_LEN - strlen(args) - 1;
798
799 /* Simply pause tracing */
800 strncat(args, "-q", args_left);
801 args_left = MAX_ARGS_LEN - strlen(args) - 1;
802
803 int retval = execute_command(args, username, password, lttd_path, fac_path);
804 if(retval) {
805 gchar msg[256];
806 guint msg_left = 256;
807
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,
815 GTK_MESSAGE_ERROR,
816 GTK_BUTTONS_OK,
817 msg);
818 gtk_dialog_run(GTK_DIALOG(dialogue));
819 gtk_widget_destroy(dialogue);
820 }
821
822 }
823
824 void unpause_clicked (GtkButton *button, gpointer user_data)
825 {
826 ControlData *tcd = (ControlData*)user_data;
827
828 const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
829 const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
830 const gchar *trace_name =
831 gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
832 const gchar *lttd_path = "";
833 const gchar *fac_path = "";
834
835 const gchar *lttctl_path =
836 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
837
838 /* Setup arguments to su */
839 /* child */
840 gchar args[MAX_ARGS_LEN];
841 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
842
843 args[0] = '\0';
844
845 /* Command */
846 strncat(args, "exec", args_left);
847 args_left = MAX_ARGS_LEN - strlen(args) - 1;
848
849 /* space */
850 strncat(args, " ", args_left);
851 args_left = MAX_ARGS_LEN - strlen(args) - 1;
852
853 if(strcmp(lttctl_path, "") == 0)
854 strncat(args, "lttctl", args_left);
855 else
856 strncat(args, lttctl_path, args_left);
857 args_left = MAX_ARGS_LEN - strlen(args) - 1;
858
859 /* space */
860 strncat(args, " ", args_left);
861 args_left = MAX_ARGS_LEN - strlen(args) - 1;
862
863 /* name */
864 strncat(args, "-n ", args_left);
865 args_left = MAX_ARGS_LEN - strlen(args) - 1;
866 strncat(args, trace_name, args_left);
867 args_left = MAX_ARGS_LEN - strlen(args) - 1;
868
869 /* space */
870 strncat(args, " ", args_left);
871 args_left = MAX_ARGS_LEN - strlen(args) - 1;
872
873 /* Simply unpause tracing */
874 strncat(args, "-s", args_left);
875 args_left = MAX_ARGS_LEN - strlen(args) - 1;
876
877 int retval = execute_command(args, username, password, lttd_path, fac_path);
878 if(retval) {
879 gchar msg[256];
880 guint msg_left = 256;
881
882 strcpy(msg, "A problem occured when executing the su command : ");
883 msg_left = 256 - strlen(msg) - 1;
884 strncat(msg, strerror(retval), msg_left);
885 GtkWidget *dialogue =
886 gtk_message_dialog_new(
887 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
888 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
889 GTK_MESSAGE_ERROR,
890 GTK_BUTTONS_OK,
891 msg);
892 gtk_dialog_run(GTK_DIALOG(dialogue));
893 gtk_widget_destroy(dialogue);
894 }
895
896 }
897
898 void stop_clicked (GtkButton *button, gpointer user_data)
899 {
900 ControlData *tcd = (ControlData*)user_data;
901
902 const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
903 const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
904 const gchar *trace_name =
905 gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
906 const gchar *lttd_path = "";
907 const gchar *fac_path = "";
908
909 const gchar *lttctl_path =
910 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
911 const gchar *trace_dir = gtk_entry_get_text(GTK_ENTRY(tcd->trace_dir_entry));
912
913 /* Setup arguments to su */
914 /* child */
915 gchar args[MAX_ARGS_LEN];
916 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
917
918 args[0] = '\0';
919
920 /* Command */
921 strncat(args, "exec", args_left);
922 args_left = MAX_ARGS_LEN - strlen(args) - 1;
923
924 /* space */
925 strncat(args, " ", args_left);
926 args_left = MAX_ARGS_LEN - strlen(args) - 1;
927
928 if(strcmp(lttctl_path, "") == 0)
929 strncat(args, "lttctl", args_left);
930 else
931 strncat(args, lttctl_path, args_left);
932 args_left = MAX_ARGS_LEN - strlen(args) - 1;
933
934 /* space */
935 strncat(args, " ", args_left);
936 args_left = MAX_ARGS_LEN - strlen(args) - 1;
937
938 /* name */
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;
943
944 /* space */
945 strncat(args, " ", args_left);
946 args_left = MAX_ARGS_LEN - strlen(args) - 1;
947
948 /* Simply stop tracing and destroy channel */
949 strncat(args, "-R", args_left);
950 args_left = MAX_ARGS_LEN - strlen(args) - 1;
951
952 int retval = execute_command(args, username, password, lttd_path, fac_path);
953 if(retval) {
954 gchar msg[256];
955 guint msg_left = 256;
956
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,
964 GTK_MESSAGE_ERROR,
965 GTK_BUTTONS_OK,
966 msg);
967 gtk_dialog_run(GTK_DIALOG(dialogue));
968 gtk_widget_destroy(dialogue);
969 return;
970 }
971
972
973 /* Ask to the user if he wants to open the trace in a new window */
974 GtkWidget *dialogue;
975 GtkWidget *label;
976 gint id;
977
978 dialogue = gtk_dialog_new_with_buttons("Open trace ?",
979 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
980 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
981 GTK_STOCK_YES,GTK_RESPONSE_ACCEPT,
982 GTK_STOCK_NO,GTK_RESPONSE_REJECT,
983 NULL);
984 label = gtk_label_new("Do you want to open the trace in LTTV ?");
985 gtk_widget_show(label);
986
987 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue)->vbox),
988 label);
989
990 id = gtk_dialog_run(GTK_DIALOG(dialogue));
991
992 switch(id){
993 case GTK_RESPONSE_ACCEPT:
994 {
995 create_main_window_with_trace(trace_dir);
996 }
997 break;
998 case GTK_RESPONSE_REJECT:
999 default:
1000 break;
1001 }
1002 gtk_widget_destroy(dialogue);
1003
1004 }
1005
1006
1007 /**
1008 * @fn GtkWidget* h_guicontrol(Tab*)
1009 *
1010 * Control Module's constructor hook
1011 *
1012 * This constructor is given as a parameter to the menuitem and toolbar button
1013 * registration. It creates the list.
1014 * @param tab A pointer to the parent window.
1015 * @return The widget created.
1016 */
1017 GtkWidget *
1018 h_guicontrol(Tab *tab)
1019 {
1020 ControlData* f = gui_control(tab) ;
1021
1022 return NULL;
1023 }
1024
1025 /**
1026 * @fn static void init()
1027 *
1028 * This function initializes the Filter Viewer functionnality through the
1029 * gtkTraceSet API.
1030 */
1031 static void init() {
1032
1033 lttvwindow_register_constructor("guicontrol",
1034 "/",
1035 "Insert Tracing Control Module",
1036 hTraceControlInsert_xpm,
1037 "Insert Tracing Control Module",
1038 h_guicontrol);
1039 }
1040
1041 /**
1042 * @fn void control_destroy_walk(gpointer,gpointer)
1043 *
1044 * Initiate the destruction of the current gui module
1045 * on the GTK Interface
1046 */
1047 void
1048 control_destroy_walk(gpointer data, gpointer user_data)
1049 {
1050 ControlData *tcd = (ControlData*)data;
1051
1052 g_debug("traceontrol.c : control_destroy_walk, %p", tcd);
1053
1054 /* May already have been done by GTK window closing */
1055 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd)))
1056 gtk_widget_destroy(guicontrol_get_widget(tcd));
1057 }
1058
1059 /**
1060 * @fn static void destroy()
1061 * @brief plugin's destroy function
1062 *
1063 * This function releases the memory reserved by the module and unregisters
1064 * everything that has been registered in the gtkTraceSet API.
1065 */
1066 static void destroy() {
1067
1068 g_slist_foreach(g_control_list, control_destroy_walk, NULL );
1069
1070 lttvwindow_unregister_constructor(h_guicontrol);
1071
1072 }
1073
1074
1075 LTTV_MODULE("guitracecontrol", "Trace Control Window", \
1076 "Graphical module that let user control kernel tracing", \
1077 init, destroy, "lttvwindow")
1078
This page took 0.076961 seconds and 4 git commands to generate.