0.4
[lttv.git] / ltt / branches / poly / lttv / modules / gui / tracecontrol / tracecontrol.c
CommitLineData
e7c8534e 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>
e7c8534e 32
33#include <lttvwindow/lttvwindow.h>
34#include <lttvwindow/lttvwindowtraces.h>
35
36#include "hTraceControlInsert.xpm"
381229ee 37#include "TraceControlStart.xpm"
38#include "TraceControlPause.xpm"
39#include "TraceControlStop.xpm"
e7c8534e 40
77ef407f 41#include <sys/types.h>
42#include <unistd.h>
43#include <stdlib.h>
ff430216 44#include <pty.h>
45#include <utmp.h>
46#include <sys/wait.h>
86a65fdb 47#include <sys/poll.h>
6cec4cd2 48#include <errno.h>
77ef407f 49
f6f6abf0 50#define MAX_ARGS_LEN PATH_MAX * 10
e7c8534e 51
52GSList *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
62typedef struct _ControlData ControlData;
63
64/*
65 * Prototypes
66 */
67GtkWidget *guicontrol_get_widget(ControlData *tcd);
68ControlData *gui_control(Tab *tab);
69void gui_control_destructor(ControlData *tcd);
70GtkWidget* h_guicontrol(Tab *tab);
71void control_destroy_walk(gpointer data, gpointer user_data);
72
73/*
74 * Callback functions
75 */
76
77ef407f 77static void start_clicked (GtkButton *button, gpointer user_data);
78static void pause_clicked (GtkButton *button, gpointer user_data);
45653836 79static void unpause_clicked (GtkButton *button, gpointer user_data);
77ef407f 80static void stop_clicked (GtkButton *button, gpointer user_data);
e7c8534e 81
ff430216 82
e7c8534e 83/**
84 * @struct _ControlData
85 *
77ef407f 86 * @brief Main structure of gui control
e7c8534e 87 */
88struct _ControlData {
89 Tab *tab; /**< current tab of module */
90
77ef407f 91 GtkWidget *window; /**< window */
e7c8534e 92
77ef407f 93 GtkWidget *main_box; /**< main container */
94 GtkWidget *start_button;
95 GtkWidget *pause_button;
45653836 96 GtkWidget *unpause_button;
77ef407f 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;
45653836 112 GtkWidget *append_label;
113 GtkWidget *append_check;
77ef407f 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;
e7c8534e 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 */
135GtkWidget*
136guicontrol_get_widget(ControlData *tcd)
137{
77ef407f 138 return tcd->window;
e7c8534e 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 */
148ControlData*
149gui_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
77ef407f 161 tcd->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
162 gtk_window_set_title(GTK_WINDOW(tcd->window), "LTTng Trace Control");
e7c8534e 163 /*
164 * Initiating GtkTable layout
165 * starts with 2 rows and 5 columns and
166 * expands when expressions added
167 */
77ef407f 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);
e7c8534e 171
77ef407f 172 gtk_container_add(GTK_CONTAINER(tcd->window), GTK_WIDGET(tcd->main_box));
e7c8534e 173
ff430216 174 GList *focus_chain = NULL;
175
381229ee 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);
77ef407f 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);
381229ee 188
189 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlPause_xpm);
190 image = gtk_image_new_from_pixbuf(pixbuf);
77ef407f 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);
381229ee 196
45653836 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
381229ee 205 pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)TraceControlStop_xpm);
206 image = gtk_image_new_from_pixbuf(pixbuf);
77ef407f 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);
45653836 211 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->stop_button,6,7,3,4,GTK_FILL,GTK_FILL,2,2);
381229ee 212
e7c8534e 213 /*
214 * First half of the filter window
215 * - textual entry of filter expression
216 * - processing button
217 */
77ef407f 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),
381229ee 265 "normal");
77ef407f 266 gtk_combo_box_append_text(GTK_COMBO_BOX(tcd->trace_mode_combo),
381229ee 267 "flight recorder");
77ef407f 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);
45653836 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
77ef407f 289
290 tcd->optional_label = gtk_label_new("Optional fields ");
291 gtk_widget_show (tcd->optional_label);
45653836 292 gtk_table_attach( GTK_TABLE(tcd->main_box),tcd->optional_label,0,6,8,9,GTK_FILL,GTK_FILL,2,2);
77ef407f 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);
45653836 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);
77ef407f 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);
45653836 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);
77ef407f 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();
ff430216 311 gtk_entry_set_text(GTK_ENTRY(tcd->lttctl_path_entry),PACKAGE_BIN_DIR "/lttctl");
77ef407f 312 gtk_widget_show (tcd->lttctl_path_entry);
45653836 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);
77ef407f 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();
ff430216 320 gtk_entry_set_text(GTK_ENTRY(tcd->lttd_path_entry),PACKAGE_BIN_DIR "/lttd");
77ef407f 321 gtk_widget_show (tcd->lttd_path_entry);
45653836 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);
381229ee 324
325
77ef407f 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();
86a65fdb 329 gtk_entry_set_text(GTK_ENTRY(tcd->fac_path_entry),PACKAGE_DATA_DIR "/" PACKAGE "/facilities");
77ef407f 330 gtk_widget_set_size_request(tcd->fac_path_entry, 250, -1);
331 gtk_widget_show (tcd->fac_path_entry);
45653836 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);
ff430216 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);
45653836 339 focus_chain = g_list_append (focus_chain, tcd->unpause_button);
ff430216 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);
45653836 346 focus_chain = g_list_append (focus_chain, tcd->append_check);
ff430216 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
77ef407f 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);
45653836 359 g_signal_connect(G_OBJECT(tcd->unpause_button), "clicked",
360 (GCallback)unpause_clicked, tcd);
77ef407f 361 g_signal_connect(G_OBJECT(tcd->stop_button), "clicked",
362 (GCallback)stop_clicked, tcd);
e7c8534e 363
364 /*
365 * show main container
366 */
77ef407f 367 gtk_widget_show(tcd->main_box);
368 gtk_widget_show(tcd->window);
e7c8534e 369
370
371 g_object_set_data_full(
77ef407f 372 G_OBJECT(guicontrol_get_widget(tcd)),
373 "control_viewer_data",
e7c8534e 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 */
391void
392gui_control_destructor(ControlData *tcd)
393{
394 Tab *tab = tcd->tab;
395
396 /* May already been done by GTK window closing */
77ef407f 397 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd))){
e7c8534e 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
29e34d6c 412static int execute_command(const gchar *command, const gchar *username,
45653836 413 const gchar *password, const gchar *lttd_path, const gchar *fac_path)
77ef407f 414{
ff430216 415 pid_t pid;
416 int fdpty;
417 pid = forkpty(&fdpty, NULL, NULL, NULL);
29e34d6c 418 int retval = 0;
77ef407f 419
420 if(pid > 0) {
421 /* parent */
ff430216 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;
ff430216 429
86a65fdb 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...");
1f1a8b9c 438 sleep(1); /* make sure the child is ready */
86a65fdb 439 while(1) {
440 pollfd.fd = fdpty;
75e2f396 441 pollfd.events = POLLIN|POLLPRI|POLLERR|POLLHUP|POLLNVAL;
86a65fdb 442
443 num_rdy = poll(&pollfd, 1, 200);
444#if 0
445 if(num_rdy == -1) {
446 perror("Poll error");
447 goto wait_child;
448 }
449#endif //0
450
451 /* Timeout : stop waiting for chars */
452 if(num_rdy == 0) break;
453
454 switch(pollfd.revents) {
455 case POLLERR:
456 g_warning("Error returned in polling fd\n");
457 num_hup++;
458 break;
459 case POLLHUP:
460 g_info("Polling FD : hung up.");
461 num_hup++;
462 break;
463 case POLLNVAL:
464 g_warning("Polling fd tells it is not open");
465 num_hup++;
466 break;
467 case POLLPRI:
468 case POLLIN:
469 count = read (fdpty, buf, 256);
470 if(count > 0) {
471 buf[count] = '\0';
472 printf("%s", buf);
473 } else if(count == -1) {
474 perror("Error in read");
475 goto wait_child;
476 }
477 break;
478 }
479 if(num_hup > 0) {
480 g_warning("Child hung up too fast");
481 goto wait_child;
482 }
483 }
484
485 /* Write the password */
ff430216 486 g_info("Got su prompt, now writing password...");
ff430216 487 int ret;
488 ret = write(fdpty, password, strlen(password));
489 if(ret < 0) perror("Error in write");
490 ret = write(fdpty, "\n", 1);
491 if(ret < 0) perror("Error in write");
492 fsync(fdpty);
493
86a65fdb 494 /* Take the output from the terminal and show it on the real console */
495 g_info("Getting data from child terminal...");
496 while(1) {
497 int num_hup = 0;
498 pollfd.fd = fdpty;
75e2f396 499 pollfd.events = POLLIN|POLLPRI|POLLERR|POLLHUP|POLLNVAL;
86a65fdb 500
501 num_rdy = poll(&pollfd, 1, -1);
502#if 0
503 if(num_rdy == -1) {
504 perror("Poll error");
505 goto wait_child;
506 }
507#endif //0
508 if(num_rdy == 0) break;
509
510 switch(pollfd.revents) {
511 case POLLERR:
512 g_warning("Error returned in polling fd\n");
513 num_hup++;
514 break;
515 case POLLHUP:
516 g_info("Polling FD : hung up.");
517 num_hup++;
518 break;
519 case POLLNVAL:
520 g_warning("Polling fd tells it is not open");
521 num_hup++;
522 break;
523 case POLLPRI:
524 case POLLIN:
525 count = read (fdpty, buf, 256);
526 if(count > 0) {
527 buf[count] = '\0';
528 printf("%s", buf);
529 } else if(count == -1) {
530 perror("Error in read");
531 goto wait_child;
532 }
533 break;
ff430216 534 }
86a65fdb 535 if(num_hup > 0) goto wait_child;
536 }
537wait_child:
538 g_info("Waiting for child exit...");
539
540 ret = waitpid(pid, &status, 0);
6cec4cd2 541
542 if(ret == -1) {
543 g_warning("An error occured in wait : %s",
544 strerror(errno));
545 } else {
546 if(WIFEXITED(status))
547 if(WEXITSTATUS(status) != 0) {
548 retval = WEXITSTATUS(status);
549 g_warning("An error occured in the su command : %s",
550 strerror(retval));
551 }
552 }
77ef407f 553
86a65fdb 554 g_info("Child exited.");
77ef407f 555
556 } else if(pid == 0) {
f6f6abf0 557 /* Setup environment variables */
77ef407f 558 if(strcmp(lttd_path, "") != 0)
559 setenv("LTT_DAEMON", lttd_path, 1);
560 if(strcmp(fac_path, "") != 0)
561 setenv("LTT_FACILITIES", fac_path, 1);
f6f6abf0 562
45653836 563 g_message("Executing (as %s) : %s\n", username, command);
ff430216 564
45653836 565 execlp("su", "su", "-p", "-c", command, username, NULL);
566 exit(-1); /* not supposed to happen! */
567
568 //gint ret = execvp();
569
570 } else {
571 /* error */
572 g_warning("Error happened when forking for su");
573 }
86a65fdb 574
29e34d6c 575 return retval;
45653836 576}
86a65fdb 577
86a65fdb 578
45653836 579/* Callbacks */
f6f6abf0 580
45653836 581void start_clicked (GtkButton *button, gpointer user_data)
582{
583 ControlData *tcd = (ControlData*)user_data;
f6f6abf0 584
45653836 585 const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
586 const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
587 const gchar *channel_dir =
588 gtk_entry_get_text(GTK_ENTRY(tcd->channel_dir_entry));
589 const gchar *trace_dir = gtk_entry_get_text(GTK_ENTRY(tcd->trace_dir_entry));
590 const gchar *trace_name =
591 gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
592
593 const gchar *trace_mode_sel =
594 gtk_combo_box_get_active_text(GTK_COMBO_BOX(tcd->trace_mode_combo));
595 const gchar *trace_mode;
596 if(strcmp(trace_mode_sel, "normal") == 0)
597 trace_mode = "normal";
598 else
599 trace_mode = "flight";
600
601 gboolean start_daemon =
602 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd->start_daemon_check));
f6f6abf0 603
45653836 604 gboolean append =
605 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcd->append_check));
606
607 const gchar *subbuf_size =
608 gtk_entry_get_text(GTK_ENTRY(tcd->subbuf_size_entry));
609 const gchar *subbuf_num =
610 gtk_entry_get_text(GTK_ENTRY(tcd->subbuf_num_entry));
611 const gchar *lttctl_path =
612 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
613 const gchar *lttd_path = gtk_entry_get_text(GTK_ENTRY(tcd->lttd_path_entry));
614 const gchar *fac_path = gtk_entry_get_text(GTK_ENTRY(tcd->fac_path_entry));
615
616
617 /* Setup arguments to su */
618 /* child */
619 gchar args[MAX_ARGS_LEN];
620 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
621
622 args[0] = '\0';
623
624 /* Command */
625 strncat(args, "exec", args_left);
626 args_left = MAX_ARGS_LEN - strlen(args) - 1;
627
628 /* space */
629 strncat(args, " ", args_left);
630 args_left = MAX_ARGS_LEN - strlen(args) - 1;
631
632 if(strcmp(lttctl_path, "") == 0)
633 strncat(args, "lttctl", args_left);
634 else
635 strncat(args, lttctl_path, args_left);
636 args_left = MAX_ARGS_LEN - strlen(args) - 1;
637
638 /* space */
639 strncat(args, " ", args_left);
640 args_left = MAX_ARGS_LEN - strlen(args) - 1;
641
642 /* channel dir */
643 strncat(args, "-l ", args_left);
644 args_left = MAX_ARGS_LEN - strlen(args) - 1;
645 strncat(args, channel_dir, args_left);
646 args_left = MAX_ARGS_LEN - strlen(args) - 1;
647
648 /* space */
649 strncat(args, " ", args_left);
650 args_left = MAX_ARGS_LEN - strlen(args) - 1;
651
652 /* trace dir */
653 strncat(args, "-t ", args_left);
654 args_left = MAX_ARGS_LEN - strlen(args) - 1;
655 strncat(args, trace_dir, args_left);
656 args_left = MAX_ARGS_LEN - strlen(args) - 1;
657
658 /* space */
659 strncat(args, " ", args_left);
660 args_left = MAX_ARGS_LEN - strlen(args) - 1;
661
662 /* name */
663 strncat(args, "-n ", args_left);
664 args_left = MAX_ARGS_LEN - strlen(args) - 1;
665 strncat(args, trace_name, args_left);
666 args_left = MAX_ARGS_LEN - strlen(args) - 1;
667
668 /* space */
669 strncat(args, " ", args_left);
670 args_left = MAX_ARGS_LEN - strlen(args) - 1;
671
672 /* trace mode */
673 strncat(args, "-m ", args_left);
674 args_left = MAX_ARGS_LEN - strlen(args) - 1;
675 strncat(args, trace_mode, args_left);
676 args_left = MAX_ARGS_LEN - strlen(args) - 1;
677
678 /* space */
679 strncat(args, " ", args_left);
680 args_left = MAX_ARGS_LEN - strlen(args) - 1;
681
682 /* Start daemon ? */
683 if(start_daemon) {
684 strncat(args, "-d", args_left);
f6f6abf0 685 args_left = MAX_ARGS_LEN - strlen(args) - 1;
45653836 686 } else {
687 /* Simply create the channel and then start tracing */
688 strncat(args, "-b", args_left);
f6f6abf0 689 args_left = MAX_ARGS_LEN - strlen(args) - 1;
45653836 690 }
691
f6f6abf0 692
45653836 693 /* Append to trace ? */
694 if(append) {
f6f6abf0 695 /* space */
696 strncat(args, " ", args_left);
697 args_left = MAX_ARGS_LEN - strlen(args) - 1;
45653836 698 strncat(args, "-a", args_left);
f6f6abf0 699 args_left = MAX_ARGS_LEN - strlen(args) - 1;
45653836 700 }
701
702 /* optional arguments */
703 /* subbuffer size */
704 if(strcmp(subbuf_size, "") != 0) {
f6f6abf0 705 /* space */
706 strncat(args, " ", args_left);
707 args_left = MAX_ARGS_LEN - strlen(args) - 1;
708
45653836 709 strncat(args, "-z ", args_left);
f6f6abf0 710 args_left = MAX_ARGS_LEN - strlen(args) - 1;
45653836 711 strncat(args, subbuf_size, args_left);
f6f6abf0 712 args_left = MAX_ARGS_LEN - strlen(args) - 1;
45653836 713 }
f6f6abf0 714
45653836 715 /* number of subbuffers */
716 if(strcmp(subbuf_num, "") != 0) {
f6f6abf0 717 /* space */
718 strncat(args, " ", args_left);
719 args_left = MAX_ARGS_LEN - strlen(args) - 1;
720
45653836 721 strncat(args, "-x ", args_left);
722 args_left = MAX_ARGS_LEN - strlen(args) - 1;
723 strncat(args, subbuf_num, args_left);
724 args_left = MAX_ARGS_LEN - strlen(args) - 1;
725 }
ff430216 726
77ef407f 727
29e34d6c 728 int retval = execute_command(args, username, password, lttd_path, fac_path);
729
730 if(retval) {
731 gchar msg[256];
732 guint msg_left = 256;
733
734 strcpy(msg, "A problem occured when executing the su command : ");
735 msg_left = 256 - strlen(msg) - 1;
736 strncat(msg, strerror(retval), msg_left);
737 GtkWidget *dialogue =
738 gtk_message_dialog_new(
739 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
740 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
741 GTK_MESSAGE_ERROR,
742 GTK_BUTTONS_OK,
743 msg);
744 gtk_dialog_run(GTK_DIALOG(dialogue));
745 gtk_widget_destroy(dialogue);
746 }
77ef407f 747
748}
749
750
751void pause_clicked (GtkButton *button, gpointer user_data)
752{
753 ControlData *tcd = (ControlData*)user_data;
754
45653836 755 const gchar *username = gtk_entry_get_text(GTK_ENTRY(tcd->username_entry));
756 const gchar *password = gtk_entry_get_text(GTK_ENTRY(tcd->password_entry));
757 const gchar *trace_name =
758 gtk_entry_get_text(GTK_ENTRY(tcd->trace_name_entry));
759 const gchar *lttd_path = "";
760 const gchar *fac_path = "";
761
762 const gchar *lttctl_path =
763 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
77ef407f 764
45653836 765 /* Setup arguments to su */
766 /* child */
767 gchar args[MAX_ARGS_LEN];
768 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
769
770 args[0] = '\0';
771
772 /* Command */
773 strncat(args, "exec", args_left);
774 args_left = MAX_ARGS_LEN - strlen(args) - 1;
775
776 /* space */
777 strncat(args, " ", args_left);
778 args_left = MAX_ARGS_LEN - strlen(args) - 1;
779
780 if(strcmp(lttctl_path, "") == 0)
781 strncat(args, "lttctl", args_left);
782 else
783 strncat(args, lttctl_path, args_left);
784 args_left = MAX_ARGS_LEN - strlen(args) - 1;
785
786 /* space */
787 strncat(args, " ", args_left);
788 args_left = MAX_ARGS_LEN - strlen(args) - 1;
789
790 /* name */
791 strncat(args, "-n ", args_left);
792 args_left = MAX_ARGS_LEN - strlen(args) - 1;
793 strncat(args, trace_name, args_left);
794 args_left = MAX_ARGS_LEN - strlen(args) - 1;
795
796 /* space */
797 strncat(args, " ", args_left);
798 args_left = MAX_ARGS_LEN - strlen(args) - 1;
799
800 /* Simply pause tracing */
801 strncat(args, "-q", args_left);
802 args_left = MAX_ARGS_LEN - strlen(args) - 1;
803
29e34d6c 804 int retval = execute_command(args, username, password, lttd_path, fac_path);
805 if(retval) {
806 gchar msg[256];
807 guint msg_left = 256;
808
809 strcpy(msg, "A problem occured when executing the su command : ");
810 msg_left = 256 - strlen(msg) - 1;
811 strncat(msg, strerror(retval), msg_left);
812 GtkWidget *dialogue =
813 gtk_message_dialog_new(
814 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
815 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
816 GTK_MESSAGE_ERROR,
817 GTK_BUTTONS_OK,
818 msg);
819 gtk_dialog_run(GTK_DIALOG(dialogue));
820 gtk_widget_destroy(dialogue);
821 }
822
45653836 823}
824
825void unpause_clicked (GtkButton *button, gpointer user_data)
826{
827 ControlData *tcd = (ControlData*)user_data;
828
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 = "";
835
836 const gchar *lttctl_path =
837 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
838
839 /* Setup arguments to su */
840 /* child */
841 gchar args[MAX_ARGS_LEN];
842 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
843
844 args[0] = '\0';
845
846 /* Command */
847 strncat(args, "exec", args_left);
848 args_left = MAX_ARGS_LEN - strlen(args) - 1;
849
850 /* space */
851 strncat(args, " ", args_left);
852 args_left = MAX_ARGS_LEN - strlen(args) - 1;
853
854 if(strcmp(lttctl_path, "") == 0)
855 strncat(args, "lttctl", args_left);
856 else
857 strncat(args, lttctl_path, args_left);
858 args_left = MAX_ARGS_LEN - strlen(args) - 1;
859
860 /* space */
861 strncat(args, " ", args_left);
862 args_left = MAX_ARGS_LEN - strlen(args) - 1;
863
864 /* name */
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;
869
870 /* space */
871 strncat(args, " ", args_left);
872 args_left = MAX_ARGS_LEN - strlen(args) - 1;
873
874 /* Simply unpause tracing */
875 strncat(args, "-s", args_left);
876 args_left = MAX_ARGS_LEN - strlen(args) - 1;
877
29e34d6c 878 int retval = execute_command(args, username, password, lttd_path, fac_path);
879 if(retval) {
880 gchar msg[256];
881 guint msg_left = 256;
882
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,
890 GTK_MESSAGE_ERROR,
891 GTK_BUTTONS_OK,
892 msg);
893 gtk_dialog_run(GTK_DIALOG(dialogue));
894 gtk_widget_destroy(dialogue);
895 }
896
77ef407f 897}
898
899void stop_clicked (GtkButton *button, gpointer user_data)
900{
901 ControlData *tcd = (ControlData*)user_data;
902
45653836 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 = "";
909
910 const gchar *lttctl_path =
911 gtk_entry_get_text(GTK_ENTRY(tcd->lttctl_path_entry));
8321ae6a 912 const gchar *trace_dir = gtk_entry_get_text(GTK_ENTRY(tcd->trace_dir_entry));
45653836 913
914 /* Setup arguments to su */
915 /* child */
916 gchar args[MAX_ARGS_LEN];
917 gint args_left = MAX_ARGS_LEN - 1; /* for \0 */
918
919 args[0] = '\0';
920
921 /* Command */
922 strncat(args, "exec", args_left);
923 args_left = MAX_ARGS_LEN - strlen(args) - 1;
924
925 /* space */
926 strncat(args, " ", args_left);
927 args_left = MAX_ARGS_LEN - strlen(args) - 1;
928
929 if(strcmp(lttctl_path, "") == 0)
930 strncat(args, "lttctl", args_left);
931 else
932 strncat(args, lttctl_path, args_left);
933 args_left = MAX_ARGS_LEN - strlen(args) - 1;
934
935 /* space */
936 strncat(args, " ", args_left);
937 args_left = MAX_ARGS_LEN - strlen(args) - 1;
938
939 /* name */
940 strncat(args, "-n ", args_left);
941 args_left = MAX_ARGS_LEN - strlen(args) - 1;
942 strncat(args, trace_name, args_left);
943 args_left = MAX_ARGS_LEN - strlen(args) - 1;
944
945 /* space */
946 strncat(args, " ", args_left);
947 args_left = MAX_ARGS_LEN - strlen(args) - 1;
948
949 /* Simply stop tracing and destroy channel */
950 strncat(args, "-R", args_left);
951 args_left = MAX_ARGS_LEN - strlen(args) - 1;
952
29e34d6c 953 int retval = execute_command(args, username, password, lttd_path, fac_path);
954 if(retval) {
955 gchar msg[256];
956 guint msg_left = 256;
957
958 strcpy(msg, "A problem occured when executing the su command : ");
959 msg_left = 256 - strlen(msg) - 1;
960 strncat(msg, strerror(retval), msg_left);
961 GtkWidget *dialogue =
962 gtk_message_dialog_new(
963 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
964 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
965 GTK_MESSAGE_ERROR,
966 GTK_BUTTONS_OK,
967 msg);
968 gtk_dialog_run(GTK_DIALOG(dialogue));
969 gtk_widget_destroy(dialogue);
970 return;
971 }
972
77ef407f 973
8321ae6a 974 /* Ask to the user if he wants to open the trace in a new window */
975 GtkWidget *dialogue;
976 GtkWidget *label;
977 gint id;
978
979 dialogue = gtk_dialog_new_with_buttons("Open trace ?",
980 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))),
981 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
982 GTK_STOCK_YES,GTK_RESPONSE_ACCEPT,
983 GTK_STOCK_NO,GTK_RESPONSE_REJECT,
984 NULL);
985 label = gtk_label_new("Do you want to open the trace in LTTV ?");
986 gtk_widget_show(label);
987
988 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialogue)->vbox),
989 label);
990
991 id = gtk_dialog_run(GTK_DIALOG(dialogue));
992
993 switch(id){
994 case GTK_RESPONSE_ACCEPT:
995 {
996 create_main_window_with_trace(trace_dir);
997 }
998 break;
999 case GTK_RESPONSE_REJECT:
1000 default:
1001 break;
1002 }
1003 gtk_widget_destroy(dialogue);
1004
77ef407f 1005}
1006
e7c8534e 1007
1008/**
1009 * @fn GtkWidget* h_guicontrol(Tab*)
1010 *
1011 * Control Module's constructor hook
1012 *
1013 * This constructor is given as a parameter to the menuitem and toolbar button
1014 * registration. It creates the list.
1015 * @param tab A pointer to the parent window.
1016 * @return The widget created.
1017 */
1018GtkWidget *
1019h_guicontrol(Tab *tab)
1020{
1021 ControlData* f = gui_control(tab) ;
1022
1023 return NULL;
1024}
1025
1026/**
1027 * @fn static void init()
1028 *
1029 * This function initializes the Filter Viewer functionnality through the
1030 * gtkTraceSet API.
1031 */
1032static void init() {
1033
1034 lttvwindow_register_constructor("guicontrol",
1035 "/",
1036 "Insert Tracing Control Module",
1037 hTraceControlInsert_xpm,
1038 "Insert Tracing Control Module",
1039 h_guicontrol);
1040}
1041
1042/**
1043 * @fn void control_destroy_walk(gpointer,gpointer)
1044 *
1045 * Initiate the destruction of the current gui module
1046 * on the GTK Interface
1047 */
1048void
1049control_destroy_walk(gpointer data, gpointer user_data)
1050{
1051 ControlData *tcd = (ControlData*)data;
1052
1053 g_debug("traceontrol.c : control_destroy_walk, %p", tcd);
1054
1055 /* May already have been done by GTK window closing */
1056 if(GTK_IS_WIDGET(guicontrol_get_widget(tcd)))
1057 gtk_widget_destroy(guicontrol_get_widget(tcd));
1058}
1059
1060/**
1061 * @fn static void destroy()
1062 * @brief plugin's destroy function
1063 *
1064 * This function releases the memory reserved by the module and unregisters
1065 * everything that has been registered in the gtkTraceSet API.
1066 */
1067static void destroy() {
1068
1069 g_slist_foreach(g_control_list, control_destroy_walk, NULL );
1070
1071 lttvwindow_unregister_constructor(h_guicontrol);
1072
1073}
1074
1075
1076LTTV_MODULE("guitracecontrol", "Trace Control Window", \
1077 "Graphical module that let user control kernel tracing", \
1078 init, destroy, "lttvwindow")
1079
This page took 0.067083 seconds and 4 git commands to generate.