Added initial Spanish translation
[anjuta-git-plugin.git] / libanjuta / anjuta-launcher.c
bloba5159d648fbbc6179224d615fed69356816012d3
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-launcher.c
4 * Copyright (C) 2003 Naba Kumar <naba@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /**
22 * SECTION:anjuta-launcher
23 * @short_description: External process launcher with async input/output
24 * @see_also:
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-launcher.h
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #include <errno.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <signal.h>
39 #if !defined(__sun) && !defined(__NetBSD__)
40 # ifndef FREEBSD
41 # include <pty.h>
42 # else
43 # include <libutil.h>
44 # endif
45 #endif
46 #include "anjuta-utils-priv.h"
48 #include <assert.h>
49 #include <termios.h>
51 #include <string.h>
52 #include <time.h>
53 #include <glib/gi18n.h>
54 #include <glib.h>
56 #include <libgnome/gnome-macros.h>
58 #include "anjuta-children.h"
59 #include "anjuta-utils.h"
60 #include "anjuta-marshal.h"
61 #include "resources.h"
62 #include "anjuta-launcher.h"
63 #include "anjuta-debug.h"
65 #define ANJUTA_PIXMAP_PASSWORD "password.png"
66 #define FILE_BUFFER_SIZE 1024
67 #ifndef __MAX_BAUD
68 #ifdef __CYGWIN__
69 #define __MAX_BAUD B256000
70 #else
71 #define __MAX_BAUD B460800
72 #endif
73 #endif
76 static gboolean
77 anjuta_launcher_pty_check_child_exit_code (AnjutaLauncher *launcher,
78 const gchar* line);
80 struct _AnjutaLauncherPriv
83 * Busy flag is TRUE if the Launcher
84 * is currently executing a child.
86 gboolean busy;
88 /* These flags are used to synchronize the IO operations. */
89 gboolean stdout_is_done;
90 gboolean stderr_is_done;
92 /* GIO channels */
93 GIOChannel *stdout_channel;
94 GIOChannel *stderr_channel;
95 /*GIOChannel *stdin_channel;*/
96 GIOChannel *pty_channel;
98 /* GIO watch handles */
99 guint stdout_watch;
100 guint stderr_watch;
101 guint pty_watch;
103 /* Output line buffers */
104 gchar *stdout_buffer;
105 gchar *stderr_buffer;
107 /* Output of the pty is constantly stored here.*/
108 gchar *pty_output_buffer;
110 /* Terminal echo */
111 gboolean terminal_echo_on;
113 /* The child */
114 pid_t child_pid;
115 gint child_status;
116 gboolean child_has_terminated;
118 /* Synchronization in progress */
119 gboolean in_synchronization;
120 guint completion_check_timeout;
122 /* Terminate child on child exit */
123 gboolean terminate_on_exit;
125 /* Start time of execution */
126 time_t start_time;
128 /* Should the outputs be buffered */
129 gboolean buffered_output;
131 /* Should we check for password prompts in stdout and pty */
132 gboolean check_for_passwd_prompt;
134 /* Output callback */
135 AnjutaLauncherOutputCallback output_callback;
137 /* Callback data */
138 gpointer callback_data;
141 enum
143 /* OUTPUT_ARRIVED_SIGNAL, */
144 CHILD_EXITED_SIGNAL,
145 BUSY_SIGNAL,
146 LAST_SIGNAL
149 static void anjuta_launcher_class_init (AnjutaLauncherClass * klass);
150 static void anjuta_launcher_init (AnjutaLauncher * obj);
151 static gboolean anjuta_launcher_call_execution_done (gpointer data);
152 static gboolean anjuta_launcher_check_for_execution_done (gpointer data);
153 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
154 gboolean emit_signal);
156 static gboolean is_password_prompt(const gchar* line);
158 static guint launcher_signals[LAST_SIGNAL] = { 0 };
159 static AnjutaLauncherClass *parent_class;
161 static void
162 anjuta_launcher_initialize (AnjutaLauncher *obj)
164 /* Busy flag */
165 obj->priv->busy = FALSE;
167 /* These flags are used to synchronize the IO operations. */
168 obj->priv->stdout_is_done = FALSE;
169 obj->priv->stderr_is_done = FALSE;
171 /* GIO channels */
172 obj->priv->stdout_channel = NULL;
173 obj->priv->stderr_channel = NULL;
174 obj->priv->pty_channel = NULL;
176 /* Output line buffers */
177 obj->priv->stdout_buffer = NULL;
178 obj->priv->stderr_buffer = NULL;
180 /* Pty buffer */
181 obj->priv->pty_output_buffer = NULL;
183 obj->priv->terminal_echo_on = TRUE;
185 /* The child */
186 obj->priv->child_pid = 0;
187 obj->priv->child_status = -1;
188 obj->priv->child_has_terminated = TRUE;
190 /* Synchronization in progress */
191 obj->priv->in_synchronization = FALSE;
192 obj->priv->completion_check_timeout = -1;
194 /* Terminate child on child exit */
195 obj->priv->terminate_on_exit = FALSE;
197 /* Start time of execution */
198 obj->priv->start_time = 0;
200 obj->priv->buffered_output = TRUE;
201 obj->priv->check_for_passwd_prompt = TRUE;
203 /* Output callback */
204 obj->priv->output_callback = NULL;
205 obj->priv->callback_data = NULL;
208 GType
209 anjuta_launcher_get_type ()
211 static GType obj_type = 0;
213 if (!obj_type)
215 static const GTypeInfo obj_info =
217 sizeof (AnjutaLauncherClass),
218 (GBaseInitFunc) NULL,
219 (GBaseFinalizeFunc) NULL,
220 (GClassInitFunc) anjuta_launcher_class_init,
221 (GClassFinalizeFunc) NULL,
222 NULL, /* class_data */
223 sizeof (AnjutaLauncher),
224 0, /* n_preallocs */
225 (GInstanceInitFunc) anjuta_launcher_init,
226 NULL /* value_table */
228 obj_type = g_type_register_static (G_TYPE_OBJECT,
229 "AnjutaLauncher", &obj_info, 0);
231 return obj_type;
234 static void
235 anjuta_launcher_dispose (GObject *obj)
237 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
238 if (anjuta_launcher_is_busy (launcher))
240 pid_t child_pid_save = launcher->priv->child_pid;
241 anjuta_children_unregister (child_pid_save);
242 anjuta_launcher_execution_done_cleanup (launcher, FALSE);
244 /* We can not call anjuta_launcher_reset (launcher) to kill the
245 * running child because launcher has been initialized in cleanup
247 kill (child_pid_save, SIGTERM);
248 launcher->priv->busy = FALSE;
250 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
253 static void
254 anjuta_launcher_finalize (GObject *obj)
256 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
257 g_free (launcher->priv);
258 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
261 static void
262 anjuta_launcher_class_init (AnjutaLauncherClass * klass)
264 GObjectClass *object_class;
265 g_return_if_fail (klass != NULL);
266 object_class = (GObjectClass *) klass;
268 /* DEBUG_PRINT ("Initializing launcher class"); */
270 parent_class = g_type_class_peek_parent (klass);
273 * AnjutaLauncher::child-exited
274 * @launcher: a #AnjutaLancher object.
275 * @child_pid: process ID of the child
276 * @status: status as returned by waitpid function
277 * @time: time in seconds taken by the child
279 * Emitted when the child has exited and all i/o channels have
280 * been closed. If the terminate on exit flag is set, the i/o
281 * channels are automatically closed when the child exit.
282 * You need to use WEXITSTATUS and friend to get the child exit
283 * code from the status returned.
285 launcher_signals[CHILD_EXITED_SIGNAL] =
286 g_signal_new ("child-exited",
287 G_TYPE_FROM_CLASS (object_class),
288 G_SIGNAL_RUN_FIRST,
289 G_STRUCT_OFFSET (AnjutaLauncherClass,
290 child_exited),
291 NULL, NULL,
292 anjuta_cclosure_marshal_VOID__INT_INT_ULONG,
293 G_TYPE_NONE, 3, G_TYPE_INT,
294 G_TYPE_INT, G_TYPE_ULONG);
297 * AnjutaLauncher::busy
298 * @launcher: a #AnjutaLancher object.
299 * @busy: TRUE is a child is currently running
301 * Emitted when a child starts after a call to one execute function
302 * (busy is TRUE) or when a child exits and all i/o channels are
303 * closed (busy is FALSE).
305 launcher_signals[BUSY_SIGNAL] =
306 g_signal_new ("busy",
307 G_TYPE_FROM_CLASS (object_class),
308 G_SIGNAL_RUN_FIRST,
309 G_STRUCT_OFFSET (AnjutaLauncherClass,
310 busy),
311 NULL, NULL,
312 anjuta_cclosure_marshal_VOID__BOOLEAN,
313 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
315 object_class->dispose = anjuta_launcher_dispose;
316 object_class->finalize = anjuta_launcher_finalize;
319 static void
320 anjuta_launcher_init (AnjutaLauncher * obj)
322 g_return_if_fail (obj != NULL);
323 obj->priv = g_new0 (AnjutaLauncherPriv, 1);
324 anjuta_launcher_initialize (obj);
328 * anjuta_launcher_is_busy:
329 * @launcher: a #AnjutaLancher object.
331 * Tells if the laucher is currently executing any command.
333 * Return value: TRUE if launcher is busy, otherwisee FALSE.
335 gboolean
336 anjuta_launcher_is_busy (AnjutaLauncher *launcher)
338 return launcher->priv->busy;
341 static void
342 anjuta_launcher_set_busy (AnjutaLauncher *launcher, gboolean flag)
344 gboolean old_busy = launcher->priv->busy;
345 launcher->priv->busy = flag;
346 if (old_busy != flag)
347 g_signal_emit_by_name (G_OBJECT (launcher), "busy", flag);
351 * anjuta_launcher_send_stdin:
352 * @launcher: a #AnjutaLancher object.
353 * @input_str: The string to send to STDIN of the process.
355 * Sends a string to Standard input of the process currently being executed.
357 void
358 anjuta_launcher_send_stdin (AnjutaLauncher *launcher, const gchar * input_str)
360 g_return_if_fail (launcher);
361 g_return_if_fail (input_str);
363 anjuta_launcher_send_ptyin (launcher, input_str);
367 * anjuta_launcher_send_ptyin:
368 * @launcher: a #AnjutaLancher object.
369 * @input_str: The string to send to PTY of the process.
371 * Sends a string to TTY input of the process currently being executed.
372 * Mostly useful for entering passwords and other inputs which are directly
373 * read from TTY input of the process.
375 void
376 anjuta_launcher_send_ptyin (AnjutaLauncher *launcher, const gchar * input_str)
378 gsize bytes_written;
379 GError *err = NULL;
381 if (!input_str || strlen (input_str) == 0) return;
385 g_io_channel_write_chars (launcher->priv->pty_channel,
386 input_str, strlen (input_str),
387 &bytes_written, &err);
388 g_io_channel_flush (launcher->priv->pty_channel, NULL);
389 if (err)
391 g_warning ("Error encountered while writing to PTY!. %s",
392 err->message);
393 g_error_free (err);
395 return;
397 input_str += bytes_written;
399 while (*input_str);
403 * anjuta_launcher_reset:
404 * @launcher: a #AnjutaLancher object.
406 * Resets the launcher and kills (SIGTERM) current process, if it is still
407 * executing.
409 void
410 anjuta_launcher_reset (AnjutaLauncher *launcher)
412 if (anjuta_launcher_is_busy (launcher))
413 kill (launcher->priv->child_pid, SIGTERM);
417 * anjuta_launcher_signal:
418 * @launcher: a #AnjutaLancher object.
419 * @sig: kernel signal ID (e.g. SIGTERM).
421 * Sends a kernel signal to the process that is being executed.
423 void
424 anjuta_launcher_signal (AnjutaLauncher *launcher, int sig)
426 kill (launcher->priv->child_pid, sig);
430 * anjuta_launcher_get_child_pid:
431 * @launcher: a #AnjutaLancher object.
433 * Gets the Process ID of the child being executed.
435 * Return value: Process ID of the child.
437 pid_t
438 anjuta_launcher_get_child_pid (AnjutaLauncher *launcher)
440 if (anjuta_launcher_is_busy (launcher))
441 return launcher->priv->child_pid;
442 else
443 return -1;
446 static void
447 anjuta_launcher_synchronize (AnjutaLauncher *launcher)
449 if (launcher->priv->child_has_terminated &&
450 launcher->priv->stdout_is_done &&
451 launcher->priv->stderr_is_done)
453 launcher->priv->in_synchronization = TRUE;
455 if (launcher->priv->completion_check_timeout >= 0)
456 g_source_remove (launcher->priv->completion_check_timeout);
457 launcher->priv->completion_check_timeout =
458 g_timeout_add (50, anjuta_launcher_check_for_execution_done,
459 launcher);
462 /* This case is not very good, but it blocks the whole IDE
463 because we never new if the child has finished */
464 else if (launcher->priv->stdout_is_done &&
465 launcher->priv->stderr_is_done)
467 /* DEBUG_PRINT ("Child has't exited yet waiting for 200ms"); */
468 if (launcher->priv->completion_check_timeout >= 0)
469 g_source_remove (launcher->priv->completion_check_timeout);
470 launcher->priv->completion_check_timeout =
471 g_timeout_add(200, anjuta_launcher_check_for_execution_done,
472 launcher);
474 /* Add this case for gdb. It creates child inheriting gdb
475 * pipes which are not closed if gdb crashes */
476 else if (launcher->priv->child_has_terminated &&
477 launcher->priv->terminate_on_exit)
479 if (launcher->priv->completion_check_timeout >= 0)
480 g_source_remove (launcher->priv->completion_check_timeout);
481 launcher->priv->completion_check_timeout =
482 g_timeout_add(0, anjuta_launcher_call_execution_done,
483 launcher);
487 /* Password dialog */
488 static GtkWidget*
489 create_password_dialog (const gchar* prompt)
491 GtkWidget *dialog;
492 GtkWidget *hbox;
493 GtkWidget *box;
494 GtkWidget *icon;
495 GtkWidget *label;
496 GtkWidget *entry;
498 g_return_val_if_fail (prompt, NULL);
500 dialog = gtk_dialog_new_with_buttons (prompt,
501 NULL, //FIXME: Pass the parent window here
502 // for transient purpose.
503 GTK_DIALOG_DESTROY_WITH_PARENT,
504 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
505 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
506 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
508 gtk_window_set_wmclass (GTK_WINDOW (dialog), "launcher-password-prompt",
509 "anjuta");
510 hbox = gtk_hbox_new (FALSE, 10);
511 gtk_widget_show (hbox);
512 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
514 icon = anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD);
515 gtk_widget_show (icon);
516 gtk_box_pack_start_defaults (GTK_BOX(hbox), icon);
518 if (strlen (prompt) < 20) {
519 box = gtk_hbox_new (FALSE, 5);
520 } else {
521 box = gtk_vbox_new (FALSE, 5);
523 gtk_widget_show (box);
524 gtk_box_pack_start_defaults (GTK_BOX (hbox), box);
526 label = gtk_label_new (_(prompt));
527 gtk_widget_show (label);
528 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
530 entry = gtk_entry_new ();
531 gtk_widget_show (entry);
532 gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
533 gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
535 gtk_widget_ref (entry);
536 g_object_set_data_full (G_OBJECT (dialog), "password_entry",
537 gtk_widget_ref (entry),
538 (GDestroyNotify) gtk_widget_unref);
539 gtk_widget_grab_focus (entry);
540 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
542 return dialog;
545 /* pty buffer check for password authentication */
546 static void
547 anjuta_launcher_check_password_real (AnjutaLauncher *launcher,
548 const gchar* last_line)
550 if (anjuta_launcher_is_busy (launcher) == FALSE) return;
552 if (last_line) {
554 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
555 if (is_password_prompt(last_line)) {
556 /* Password prompt detected */
557 GtkWidget* dialog;
558 gint button;
559 const gchar* passwd;
560 gchar* line;
562 dialog = create_password_dialog (last_line);
563 button = gtk_dialog_run (GTK_DIALOG(dialog));
564 switch (button) {
565 case GTK_RESPONSE_OK:
566 passwd = gtk_entry_get_text (
567 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog),
568 "password_entry")));
569 line = g_strconcat (passwd, "\n", NULL);
570 anjuta_launcher_send_ptyin (launcher, line);
571 g_free (line);
572 break;
573 case GTK_RESPONSE_CANCEL:
574 anjuta_launcher_send_ptyin (launcher, "<canceled>\n");
575 anjuta_launcher_reset (launcher);
576 break;
577 default:
578 break;
580 gtk_widget_destroy (dialog);
585 static void
586 anjuta_launcher_check_password (AnjutaLauncher *launcher, const gchar *chars)
588 glong start, end;
589 gchar *last_line;
591 if (!chars || strlen(chars) <= 0)
592 return;
594 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
595 start = end = strlen (chars);
596 while (start > 0 && chars[start-1] != '\n') start--;
598 if (end > start)
600 last_line = g_strndup (&chars[start], end - start + 1);
602 /* DEBUG_PRINT ("Last line = %s", last_line); */
603 /* Checks for password, again */
604 anjuta_launcher_check_password_real (launcher, last_line);
605 g_free (last_line);
609 static gboolean
610 is_password_prompt (const gchar* line)
612 gchar* password = "assword";
613 gchar* passphrase = "assphrase";
615 if (strlen (line) < strlen (password)
616 || strlen (line) < strlen (passphrase))
617 return FALSE;
619 if (g_strstr_len(line, 80, password) != NULL
620 || g_strstr_len(line, 80, passphrase) != NULL)
622 int i;
623 for (i = strlen(line) - 1; i != 0; --i)
625 if (line[i] == ':')
626 return TRUE;
627 if (g_ascii_isspace(line[i]))
628 continue;
629 else
630 return FALSE;
633 return FALSE;
636 static void
637 anjuta_launcher_buffered_output (AnjutaLauncher *launcher,
638 AnjutaLauncherOutputType output_type,
639 const gchar *chars)
641 gchar *all_lines;
642 gchar *incomplete_line;
643 gchar **buffer;
645 g_return_if_fail (chars != NULL);
646 g_return_if_fail (strlen (chars) > 0);
648 if (launcher->priv->output_callback == NULL)
649 return;
650 if (launcher->priv->buffered_output == FALSE)
652 (launcher->priv->output_callback)(launcher, output_type, chars,
653 launcher->priv->callback_data);
654 return;
656 switch (output_type)
658 case ANJUTA_LAUNCHER_OUTPUT_STDOUT:
659 buffer = &launcher->priv->stdout_buffer;
660 break;
661 case ANJUTA_LAUNCHER_OUTPUT_STDERR:
662 buffer = &launcher->priv->stderr_buffer;
663 break;
664 default:
665 g_warning ("Should not reach here");
666 return;
668 if (*buffer)
669 all_lines = g_strconcat (*buffer, chars, NULL);
670 else
671 all_lines = g_strdup (chars);
673 /* Buffer the last incomplete line */
674 incomplete_line = all_lines + strlen (all_lines);
675 while (incomplete_line > all_lines &&
676 *incomplete_line != '\n')
678 incomplete_line = g_utf8_prev_char (incomplete_line);
680 if (*incomplete_line == '\n')
681 incomplete_line++;
683 /* Update line buffer */
684 g_free(*buffer);
685 *buffer = NULL;
686 if (strlen(incomplete_line))
688 *buffer = g_strdup (incomplete_line);
689 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
691 /* Check for password prompt */
692 if (launcher->priv->check_for_passwd_prompt)
693 anjuta_launcher_check_password (launcher, incomplete_line);
695 /* Deliver complete lines */
696 *incomplete_line = '\0';
697 if (strlen (all_lines) > 0)
698 (launcher->priv->output_callback)(launcher, output_type, all_lines,
699 launcher->priv->callback_data);
700 g_free (all_lines);
703 static gboolean
704 anjuta_launcher_scan_output (GIOChannel *channel, GIOCondition condition,
705 AnjutaLauncher *launcher)
707 gsize n;
708 gchar buffer[FILE_BUFFER_SIZE];
709 gboolean ret = TRUE;
711 if (condition & G_IO_IN)
713 GError *err = NULL;
716 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
717 if (n > 0 && !err) /* There is output */
719 gchar *utf8_chars;
720 buffer[n] = '\0';
721 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
722 anjuta_launcher_buffered_output (launcher,
723 ANJUTA_LAUNCHER_OUTPUT_STDOUT,
724 utf8_chars);
725 g_free (utf8_chars);
727 /* The pipe is closed on the other side */
728 /* if not related to non blocking read or interrupted syscall */
729 else if (err && errno != EAGAIN && errno != EINTR)
731 /* DEBUG_PRINT ("launcher.c: Error while reading child stdout\n"); */
732 launcher->priv->stdout_is_done = TRUE;
733 anjuta_launcher_synchronize (launcher);
734 ret = FALSE;
736 /* Read next chars if buffer was too small
737 * (the maximum length of one character is 6 bytes) */
738 } while (!err && (n > FILE_BUFFER_SIZE - 7));
739 if (err)
740 g_error_free (err);
742 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
744 /* DEBUG_PRINT ("launcher.c: STDOUT pipe closed"); */
745 launcher->priv->stdout_is_done = TRUE;
746 anjuta_launcher_synchronize (launcher);
747 ret = FALSE;
749 return ret;
752 static gboolean
753 anjuta_launcher_scan_error (GIOChannel *channel, GIOCondition condition,
754 AnjutaLauncher *launcher)
756 gsize n;
757 gchar buffer[FILE_BUFFER_SIZE];
758 gboolean ret = TRUE;
760 if (condition & G_IO_IN)
762 GError *err = NULL;
765 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
766 if (n > 0 && !err) /* There is stderr output */
768 gchar *utf8_chars;
769 buffer[n] = '\0';
770 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
771 anjuta_launcher_buffered_output (launcher,
772 ANJUTA_LAUNCHER_OUTPUT_STDERR,
773 utf8_chars);
774 g_free (utf8_chars);
776 /* The pipe is closed on the other side */
777 /* if not related to non blocking read or interrupted syscall */
778 else if (err && errno != EAGAIN && errno != EINTR)
780 /* DEBUG_PRINT ("launcher.c: Error while reading child stderr");*/
781 launcher->priv->stderr_is_done = TRUE;
782 anjuta_launcher_synchronize (launcher);
783 ret = FALSE;
785 /* Read next chars if buffer was too small
786 * (the maximum length of one character is 6 bytes) */
787 } while (!err && (n > FILE_BUFFER_SIZE - 7));
788 if (err)
789 g_error_free (err);
791 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
793 /* DEBUG_PRINT ("launcher.c: STDERR pipe closed"); */
794 launcher->priv->stderr_is_done = TRUE;
795 anjuta_launcher_synchronize (launcher);
796 ret = FALSE;
798 return ret;
801 static gboolean
802 anjuta_launcher_scan_pty (GIOChannel *channel, GIOCondition condition,
803 AnjutaLauncher *launcher)
805 gsize n;
806 gchar buffer[FILE_BUFFER_SIZE];
807 gboolean ret = TRUE;
809 if (condition & G_IO_IN)
811 GError *err = NULL;
814 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
815 if (n > 0 && !err) /* There is stderr output */
817 gchar *utf8_chars;
818 gchar *old_str = launcher->priv->pty_output_buffer;
819 buffer[n] = '\0';
820 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
821 if (old_str)
823 gchar *str = g_strconcat (old_str, utf8_chars, NULL);
824 launcher->priv->pty_output_buffer = str;
825 g_free (old_str);
827 else
828 launcher->priv->pty_output_buffer = g_strdup (utf8_chars);
829 g_free (utf8_chars);
831 /* The pipe is closed on the other side */
832 /* if not related to non blocking read or interrupted syscall */
833 else if (err && errno != EAGAIN && errno != EINTR)
835 g_warning (_("launcher.c: Error while reading child pty\n"));
836 ret = FALSE;
838 /* Read next chars if buffer was too small
839 * (the maximum length of one character is 6 bytes) */
840 } while (!err && (n > FILE_BUFFER_SIZE - 7));
841 if (err)
842 g_error_free (err);
843 if (launcher->priv->check_for_passwd_prompt
844 && launcher->priv->pty_output_buffer
845 && strlen (launcher->priv->pty_output_buffer) > 0)
847 anjuta_launcher_check_password (launcher,
848 launcher->priv->pty_output_buffer);
851 /* In pty case, we handle the cases in different invocations */
852 /* Do not hook up for G_IO_HUP */
853 if (condition & G_IO_ERR)
855 /* DEBUG_PRINT ("launcher.c: PTY pipe error!"); */
856 ret = FALSE;
858 return ret;
861 static void
862 anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
863 gboolean emit_signal)
865 static gboolean block = FALSE;
866 gint child_status, child_pid;
867 time_t start_time;
869 if (launcher->priv->completion_check_timeout >= 0)
870 g_source_remove (launcher->priv->completion_check_timeout);
872 if (block)
873 return;
875 /* Make sure all pending I/O are flushed out */
876 block = TRUE;
877 while (g_main_context_pending (NULL))
878 g_main_context_iteration (NULL, FALSE);
880 /* Can be called again, while waiting in the previous line
881 * Do nothing if clean up is already done */
882 if (launcher->priv->stdout_channel)
884 g_io_channel_shutdown (launcher->priv->stdout_channel, emit_signal, NULL);
885 g_io_channel_unref (launcher->priv->stdout_channel);
886 g_source_remove (launcher->priv->stdout_watch);
889 if (launcher->priv->stderr_channel)
891 g_io_channel_shutdown (launcher->priv->stderr_channel, emit_signal, NULL);
892 g_io_channel_unref (launcher->priv->stderr_channel);
893 g_source_remove (launcher->priv->stderr_watch);
896 if (launcher->priv->pty_channel)
898 g_io_channel_shutdown (launcher->priv->pty_channel, emit_signal, NULL);
899 g_io_channel_unref (launcher->priv->pty_channel);
901 g_source_remove (launcher->priv->pty_watch);
904 if (launcher->priv->pty_output_buffer)
905 g_free (launcher->priv->pty_output_buffer);
906 if (launcher->priv->stdout_buffer)
907 g_free (launcher->priv->stdout_buffer);
908 if (launcher->priv->stderr_buffer)
909 g_free (launcher->priv->stdout_buffer);
911 /* Save them before we re-initialize */
912 child_status = launcher->priv->child_status;
913 child_pid = launcher->priv->child_pid;
914 start_time = launcher->priv->start_time;
916 if (emit_signal)
917 anjuta_launcher_set_busy (launcher, FALSE);
919 anjuta_launcher_initialize (launcher);
921 /* Call this here, after set_busy (FALSE) so we are able to
922 launch a new child from the terminate function.
923 (by clubfan 2002-04-07)
925 /* DEBUG_PRINT ("Exit status: %d", child_status); */
926 if (emit_signal)
927 g_signal_emit_by_name (launcher, "child-exited", child_pid,
928 child_status,
929 time (NULL) - start_time);
931 block = FALSE;
934 /* Using this function is necessary because
935 * anjuta_launcher_execution_done_cleanup needs to be called in the same
936 * thread than the gtk main loop */
937 static gboolean
938 anjuta_launcher_call_execution_done (gpointer data)
940 AnjutaLauncher *launcher = data;
942 launcher->priv->completion_check_timeout = -1;
943 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
944 return FALSE;
947 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
948 static gboolean
949 anjuta_launcher_check_for_execution_done (gpointer data)
951 AnjutaLauncher *launcher = data;
953 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
954 launcher->priv->stdout_is_done ? 1 : 0,
955 launcher->priv->stderr_is_done ? 1 : 0);
957 if (launcher->priv->stdout_is_done == FALSE ||
958 launcher->priv->stderr_is_done == FALSE)
959 return TRUE;
960 if (launcher->priv->child_has_terminated == FALSE)
962 /* DEBUG_PRINT ("launcher: We missed the exit of the child"); */
963 anjuta_children_recover();
965 launcher->priv->completion_check_timeout = -1;
966 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
967 return FALSE;
970 static void
971 anjuta_launcher_child_terminated (int status, gpointer data)
973 AnjutaLauncher *launcher = data;
975 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher));
977 /* Save child exit code */
978 launcher->priv->child_status = status;
979 launcher->priv->child_has_terminated = TRUE;
980 anjuta_launcher_synchronize (launcher);
984 * anjuta_launcher_set_encoding:
985 * @launcher: a #AnjutaLancher object.
986 * @charset: Character set to use for Input/Output with the process.
988 * Sets the character set to use for Input/Output with the process.
990 * Return value: TRUE if successful, otherwise FALSE.
992 gboolean
993 anjuta_launcher_set_encoding (AnjutaLauncher *launcher, const gchar *charset)
995 GIOStatus s;
996 gboolean r = TRUE;
998 g_return_val_if_fail (launcher != NULL, FALSE);
999 // charset can be NULL
1001 s = g_io_channel_set_encoding (launcher->priv->stderr_channel, charset, NULL);
1002 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1003 s = g_io_channel_set_encoding (launcher->priv->stdout_channel, charset, NULL);
1004 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1005 s = g_io_channel_set_encoding (launcher->priv->pty_channel, charset, NULL);
1006 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1008 if (! r)
1010 g_warning ("launcher.c: Failed to set channel encoding!");
1012 return r;
1015 static pid_t
1016 anjuta_launcher_fork (AnjutaLauncher *launcher, gchar *const args[])
1018 char *working_dir;
1019 int pty_master_fd, md;
1020 int stdout_pipe[2], stderr_pipe[2];
1021 pid_t child_pid;
1022 struct termios termios_flags;
1023 const gchar *charset;
1025 working_dir = g_get_current_dir ();
1027 /* The pipes */
1028 pipe (stderr_pipe);
1029 pipe (stdout_pipe);
1031 /* Fork the command */
1032 child_pid = forkpty (&pty_master_fd, NULL, NULL, NULL);
1033 if (child_pid == 0)
1035 close (2);
1036 dup (stderr_pipe[1]);
1037 close (1);
1038 dup (stdout_pipe[1]);
1040 /* Close unnecessary pipes */
1041 close (stderr_pipe[0]);
1042 close (stdout_pipe[0]);
1045 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1046 perror ("Could not set new controlling tty");
1048 /* Set no delays for the write pipes (non_buffered) so
1049 that we get all the outputs immidiately */
1050 if ((md = fcntl (stdout_pipe[1], F_GETFL)) != -1)
1051 fcntl (stdout_pipe[1], F_SETFL, O_SYNC | md);
1052 if ((md = fcntl (stderr_pipe[1], F_GETFL)) != -1)
1053 fcntl (stderr_pipe[1], F_SETFL, O_SYNC | md);
1055 execvp (args[0], args);
1056 g_warning (_("Cannot execute command: \"%s\""), args[0]);
1057 perror(_("execvp failed"));
1058 _exit(-1);
1060 g_free (working_dir);
1062 /* Close parent's side pipes */
1063 close (stderr_pipe[1]);
1064 close (stdout_pipe[1]);
1066 if (child_pid < 0)
1068 g_warning ("launcher.c: Fork failed!");
1069 /* Close parent's side pipes */
1070 close (stderr_pipe[0]);
1071 close (stdout_pipe[0]);
1072 return child_pid;
1076 * Set pipes none blocking, so we can read big buffers
1077 * in the callback without having to use FIONREAD
1078 * to make sure the callback doesn't block.
1080 if ((md = fcntl (stdout_pipe[0], F_GETFL)) != -1)
1081 fcntl (stdout_pipe[0], F_SETFL, O_NONBLOCK | md);
1082 if ((md = fcntl (stderr_pipe[0], F_GETFL)) != -1)
1083 fcntl (stderr_pipe[0], F_SETFL, O_NONBLOCK | md);
1084 if ((md = fcntl (pty_master_fd, F_GETFL)) != -1)
1085 fcntl (pty_master_fd, F_SETFL, O_NONBLOCK | md);
1087 launcher->priv->child_pid = child_pid;
1088 launcher->priv->stderr_channel = g_io_channel_unix_new (stderr_pipe[0]);
1089 launcher->priv->stdout_channel = g_io_channel_unix_new (stdout_pipe[0]);
1090 launcher->priv->pty_channel = g_io_channel_unix_new (pty_master_fd);
1092 g_get_charset (&charset);
1093 anjuta_launcher_set_encoding (launcher, charset);
1095 tcgetattr(pty_master_fd, &termios_flags);
1096 termios_flags.c_iflag &= ~(IGNPAR | INPCK | INLCR | IGNCR | ICRNL | IXON |
1097 IXOFF | ISTRIP);
1098 termios_flags.c_iflag |= IGNBRK | BRKINT | IMAXBEL | IXANY;
1099 termios_flags.c_oflag &= ~OPOST;
1100 // termios_flags.c_oflag |= 0;
1101 termios_flags.c_cflag &= ~(CSTOPB | CREAD | PARENB | HUPCL);
1102 termios_flags.c_cflag |= CS8 | CLOCAL;
1104 if (!launcher->priv->terminal_echo_on)
1106 termios_flags.c_lflag &= ~(ECHOKE | ECHOE | ECHO | ECHONL |
1107 #ifdef ECHOPRT
1108 ECHOPRT |
1109 #endif
1110 ECHOCTL | ISIG | ICANON | IEXTEN | NOFLSH | TOSTOP);
1112 // termios_flags.c_lflag |= 0;
1113 termios_flags.c_cc[VMIN] = 0;
1114 cfsetospeed(&termios_flags, __MAX_BAUD);
1115 tcsetattr(pty_master_fd, TCSANOW, &termios_flags);
1117 launcher->priv->stderr_watch =
1118 g_io_add_watch (launcher->priv->stderr_channel,
1119 G_IO_IN | G_IO_ERR | G_IO_HUP,
1120 (GIOFunc)anjuta_launcher_scan_error, launcher);
1121 launcher->priv->stdout_watch =
1122 g_io_add_watch (launcher->priv->stdout_channel,
1123 G_IO_IN | G_IO_ERR | G_IO_HUP,
1124 (GIOFunc)anjuta_launcher_scan_output, launcher);
1125 launcher->priv->pty_watch =
1126 g_io_add_watch (launcher->priv->pty_channel,
1127 G_IO_IN | G_IO_ERR, /* Do not hook up for G_IO_HUP */
1128 (GIOFunc)anjuta_launcher_scan_pty, launcher);
1130 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1131 anjuta_children_register (launcher->priv->child_pid,
1132 anjuta_launcher_child_terminated,
1133 launcher);
1134 return child_pid;
1138 * anjuta_launcher_execute_v:
1139 * @launcher: a #AnjutaLancher object.
1140 * @argv: Command args.
1141 * @callback: The callback for delivering output from the process.
1142 * @callback_data: Callback data for the above callback.
1144 * The first of the @args is the command itself. The rest are sent to the
1145 * as it's arguments. This function works similar to anjuta_launcher_execute().
1147 * Return value: TRUE if successfully launched, otherwise FALSE.
1149 gboolean
1150 anjuta_launcher_execute_v (AnjutaLauncher *launcher, gchar *const argv[],
1151 AnjutaLauncherOutputCallback callback,
1152 gpointer callback_data)
1154 if (anjuta_launcher_is_busy (launcher))
1155 return FALSE;
1157 anjuta_launcher_set_busy (launcher, TRUE);
1159 launcher->priv->start_time = time (NULL);
1160 launcher->priv->child_status = 0;
1161 launcher->priv->stdout_is_done = FALSE;
1162 launcher->priv->stderr_is_done = FALSE;
1163 launcher->priv->child_has_terminated = FALSE;
1164 launcher->priv->in_synchronization = FALSE;
1165 launcher->priv->output_callback = callback;
1166 launcher->priv->callback_data = callback_data;
1168 /* On a fork error perform a cleanup and return */
1169 if (anjuta_launcher_fork (launcher, argv) < 0)
1171 anjuta_launcher_initialize (launcher);
1172 return FALSE;
1174 return TRUE;
1178 * anjuta_launcher_execute:
1179 * @launcher: a #AnjutaLancher object.
1180 * @command_str: The command to execute.
1181 * @callback: The callback for delivering output from the process.
1182 * @callback_data: Callback data for the above callback.
1184 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1185 * delivered to the above callback. The data are delivered as they arrive
1186 * from the process and could be of any lenght. If the process asks for
1187 * passwords, the user will be automatically prompted with a dialog to enter
1188 * it. Please note that not all formats of the password are recognized. Those
1189 * with the standard 'assword:' substring in the prompt should work well.
1191 * Return value: TRUE if successfully launched, otherwise FALSE.
1193 gboolean
1194 anjuta_launcher_execute (AnjutaLauncher *launcher, const gchar *command_str,
1195 AnjutaLauncherOutputCallback callback,
1196 gpointer callback_data)
1198 GList *args_list, *args_list_ptr;
1199 gchar **args, **args_ptr;
1200 gboolean ret;
1202 /* Prepare command args */
1203 args_list = anjuta_util_parse_args_from_string (command_str);
1204 args = g_new (char*, g_list_length (args_list) + 1);
1205 args_list_ptr = args_list;
1206 args_ptr = args;
1207 while (args_list_ptr)
1209 *args_ptr = (char*) args_list_ptr->data;
1210 args_list_ptr = g_list_next (args_list_ptr);
1211 args_ptr++;
1213 *args_ptr = NULL;
1215 ret = anjuta_launcher_execute_v (launcher, args,
1216 callback, callback_data);
1217 g_free (args);
1218 anjuta_util_glist_strings_free (args_list);
1219 return ret;
1223 * anjuta_launcher_set_buffered_output:
1224 * @launcher: a #AnjutaLancher object.
1225 * @buffered: buffer output.
1227 * Sets if output should buffered or not. By default, it is buffered.
1229 * Return value: Previous flag value
1231 gboolean
1232 anjuta_launcher_set_buffered_output (AnjutaLauncher *launcher, gboolean buffered)
1234 gboolean past_value = launcher->priv->buffered_output;
1235 launcher->priv->buffered_output = buffered;
1236 return past_value;
1240 * anjuta_launcher_set_check_passwd_prompt:
1241 * @launcher: a #AnjutaLancher object.
1242 * @check_passwd: check for password.
1244 * Set if output is checked for a password prompti. A special dialog box
1245 * is use to enter it in this case. By default, this behavior is enabled.
1247 * Return value: Previous flag value
1249 gboolean
1250 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher *launcher, gboolean check_passwd)
1252 gboolean past_value = launcher->priv->check_for_passwd_prompt;
1253 launcher->priv->check_for_passwd_prompt = check_passwd;
1254 return past_value;
1258 * anjuta_launcher_set_terminal_echo:
1259 * @launcher: a #AnjutaLancher object.
1260 * @echo_on: Echo ON flag.
1262 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1263 * it is disabled.
1265 * Return value: Previous flag value
1267 gboolean
1268 anjuta_launcher_set_terminal_echo (AnjutaLauncher *launcher,
1269 gboolean echo_on)
1271 gboolean past_value = launcher->priv->terminal_echo_on;
1272 launcher->priv->terminal_echo_on = echo_on;
1273 return past_value;
1277 * anjuta_launcher_set_terminate_on_exit:
1278 * @launcher: a #AnjutaLancher object.
1279 * @terminate_on_exit: terminate on exit flag
1281 * When this flag is set, al i/o channels are closed and the child-exit
1282 * signal is emitted as soon as the child exit. By default, or when this
1283 * flag is clear, the launcher object wait until the i/o channels are
1284 * closed.
1286 * Return value: Previous flag value
1288 gboolean
1289 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher *launcher,
1290 gboolean terminate_on_exit)
1292 gboolean past_value = launcher->priv->terminate_on_exit;
1293 launcher->priv->terminate_on_exit = terminate_on_exit;
1294 return past_value;
1298 * anjuta_launcher_new:
1300 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1301 * it is disabled.
1303 * Return value: a new instance of #AnjutaLancher class.
1305 AnjutaLauncher*
1306 anjuta_launcher_new ()
1308 return g_object_new (ANJUTA_TYPE_LAUNCHER, NULL);