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