Updated Spanish translation
[anjuta-git-plugin.git] / libanjuta / anjuta-launcher.c
blob6f808b29d28295c5df4f5a9f696607f7f125d2f2
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 #define FILE_INPUT_BUFFER_SIZE 1048576
68 #ifndef __MAX_BAUD
69 #ifdef __CYGWIN__
70 #define __MAX_BAUD B256000
71 #else
72 #define __MAX_BAUD B460800
73 #endif
74 #endif
77 static gboolean
78 anjuta_launcher_pty_check_child_exit_code (AnjutaLauncher *launcher,
79 const gchar* line);
81 struct _AnjutaLauncherPriv
84 * Busy flag is TRUE if the Launcher
85 * is currently executing a child.
87 gboolean busy;
89 /* These flags are used to synchronize the IO operations. */
90 gboolean stdout_is_done;
91 gboolean stderr_is_done;
93 /* GIO channels */
94 GIOChannel *stdout_channel;
95 GIOChannel *stderr_channel;
96 /*GIOChannel *stdin_channel;*/
97 GIOChannel *pty_channel;
99 /* GIO watch handles */
100 guint stdout_watch;
101 guint stderr_watch;
102 guint pty_watch;
104 /* Output line buffers */
105 gchar *stdout_buffer;
106 gchar *stderr_buffer;
108 /* Output of the pty is constantly stored here.*/
109 gchar *pty_output_buffer;
111 /* Terminal echo */
112 gboolean terminal_echo_on;
114 /* The child */
115 pid_t child_pid;
116 gint child_status;
117 gboolean child_has_terminated;
119 /* Synchronization in progress */
120 gboolean in_cleanup;
121 guint completion_check_timeout;
123 /* Terminate child on child exit */
124 gboolean terminate_on_exit;
126 /* Start time of execution */
127 time_t start_time;
129 /* Should the outputs be buffered */
130 gboolean buffered_output;
132 /* Should we check for password prompts in stdout and pty */
133 gboolean check_for_passwd_prompt;
135 /* Output callback */
136 AnjutaLauncherOutputCallback output_callback;
138 /* Callback data */
139 gpointer callback_data;
142 enum
144 /* OUTPUT_ARRIVED_SIGNAL, */
145 CHILD_EXITED_SIGNAL,
146 BUSY_SIGNAL,
147 LAST_SIGNAL
150 static void anjuta_launcher_class_init (AnjutaLauncherClass * klass);
151 static void anjuta_launcher_init (AnjutaLauncher * obj);
152 static gboolean anjuta_launcher_call_execution_done (gpointer data);
153 static gboolean anjuta_launcher_check_for_execution_done (gpointer data);
154 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
155 gboolean emit_signal);
157 static gboolean is_password_prompt(const gchar* line);
159 static guint launcher_signals[LAST_SIGNAL] = { 0 };
160 static AnjutaLauncherClass *parent_class;
162 static void
163 anjuta_launcher_initialize (AnjutaLauncher *obj)
165 /* Busy flag */
166 obj->priv->busy = FALSE;
168 /* These flags are used to synchronize the IO operations. */
169 obj->priv->stdout_is_done = FALSE;
170 obj->priv->stderr_is_done = FALSE;
172 /* GIO channels */
173 obj->priv->stdout_channel = NULL;
174 obj->priv->stderr_channel = NULL;
175 obj->priv->pty_channel = NULL;
177 /* Output line buffers */
178 obj->priv->stdout_buffer = NULL;
179 obj->priv->stderr_buffer = NULL;
181 /* Pty buffer */
182 obj->priv->pty_output_buffer = NULL;
184 obj->priv->terminal_echo_on = TRUE;
186 /* The child */
187 obj->priv->child_pid = 0;
188 obj->priv->child_status = -1;
189 obj->priv->child_has_terminated = TRUE;
191 /* Synchronization in progress */
192 obj->priv->in_cleanup = FALSE;
193 obj->priv->completion_check_timeout = -1;
195 /* Terminate child on child exit */
196 obj->priv->terminate_on_exit = FALSE;
198 /* Start time of execution */
199 obj->priv->start_time = 0;
201 obj->priv->buffered_output = TRUE;
202 obj->priv->check_for_passwd_prompt = TRUE;
204 /* Output callback */
205 obj->priv->output_callback = NULL;
206 obj->priv->callback_data = NULL;
209 GType
210 anjuta_launcher_get_type ()
212 static GType obj_type = 0;
214 if (!obj_type)
216 static const GTypeInfo obj_info =
218 sizeof (AnjutaLauncherClass),
219 (GBaseInitFunc) NULL,
220 (GBaseFinalizeFunc) NULL,
221 (GClassInitFunc) anjuta_launcher_class_init,
222 (GClassFinalizeFunc) NULL,
223 NULL, /* class_data */
224 sizeof (AnjutaLauncher),
225 0, /* n_preallocs */
226 (GInstanceInitFunc) anjuta_launcher_init,
227 NULL /* value_table */
229 obj_type = g_type_register_static (G_TYPE_OBJECT,
230 "AnjutaLauncher", &obj_info, 0);
232 return obj_type;
235 static void
236 anjuta_launcher_dispose (GObject *obj)
238 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
239 if (anjuta_launcher_is_busy (launcher))
241 pid_t child_pid_save = launcher->priv->child_pid;
242 anjuta_children_unregister (child_pid_save);
243 anjuta_launcher_execution_done_cleanup (launcher, FALSE);
245 /* We can not call anjuta_launcher_reset (launcher) to kill the
246 * running child because launcher has been initialized in cleanup
248 kill (child_pid_save, SIGTERM);
249 launcher->priv->busy = FALSE;
251 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
254 static void
255 anjuta_launcher_finalize (GObject *obj)
257 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
258 g_free (launcher->priv);
259 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
262 static void
263 anjuta_launcher_class_init (AnjutaLauncherClass * klass)
265 GObjectClass *object_class;
266 g_return_if_fail (klass != NULL);
267 object_class = (GObjectClass *) klass;
269 /* DEBUG_PRINT ("Initializing launcher class"); */
271 parent_class = g_type_class_peek_parent (klass);
274 * AnjutaLauncher::child-exited
275 * @launcher: a #AnjutaLancher object.
276 * @child_pid: process ID of the child
277 * @status: status as returned by waitpid function
278 * @time: time in seconds taken by the child
280 * Emitted when the child has exited and all i/o channels have
281 * been closed. If the terminate on exit flag is set, the i/o
282 * channels are automatically closed when the child exit.
283 * You need to use WEXITSTATUS and friend to get the child exit
284 * code from the status returned.
286 launcher_signals[CHILD_EXITED_SIGNAL] =
287 g_signal_new ("child-exited",
288 G_TYPE_FROM_CLASS (object_class),
289 G_SIGNAL_RUN_FIRST,
290 G_STRUCT_OFFSET (AnjutaLauncherClass,
291 child_exited),
292 NULL, NULL,
293 anjuta_cclosure_marshal_VOID__INT_INT_ULONG,
294 G_TYPE_NONE, 3, G_TYPE_INT,
295 G_TYPE_INT, G_TYPE_ULONG);
298 * AnjutaLauncher::busy
299 * @launcher: a #AnjutaLancher object.
300 * @busy: TRUE is a child is currently running
302 * Emitted when a child starts after a call to one execute function
303 * (busy is TRUE) or when a child exits and all i/o channels are
304 * closed (busy is FALSE).
306 launcher_signals[BUSY_SIGNAL] =
307 g_signal_new ("busy",
308 G_TYPE_FROM_CLASS (object_class),
309 G_SIGNAL_RUN_FIRST,
310 G_STRUCT_OFFSET (AnjutaLauncherClass,
311 busy),
312 NULL, NULL,
313 anjuta_cclosure_marshal_VOID__BOOLEAN,
314 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
316 object_class->dispose = anjuta_launcher_dispose;
317 object_class->finalize = anjuta_launcher_finalize;
320 static void
321 anjuta_launcher_init (AnjutaLauncher * obj)
323 g_return_if_fail (obj != NULL);
324 obj->priv = g_new0 (AnjutaLauncherPriv, 1);
325 anjuta_launcher_initialize (obj);
329 * anjuta_launcher_is_busy:
330 * @launcher: a #AnjutaLancher object.
332 * Tells if the laucher is currently executing any command.
334 * Return value: TRUE if launcher is busy, otherwisee FALSE.
336 gboolean
337 anjuta_launcher_is_busy (AnjutaLauncher *launcher)
339 return launcher->priv->busy;
342 static void
343 anjuta_launcher_set_busy (AnjutaLauncher *launcher, gboolean flag)
345 gboolean old_busy = launcher->priv->busy;
346 launcher->priv->busy = flag;
347 if (old_busy != flag)
348 g_signal_emit_by_name (G_OBJECT (launcher), "busy", flag);
352 * anjuta_launcher_send_stdin:
353 * @launcher: a #AnjutaLancher object.
354 * @input_str: The string to send to STDIN of the process.
356 * Sends a string to Standard input of the process currently being executed.
358 void
359 anjuta_launcher_send_stdin (AnjutaLauncher *launcher, const gchar * input_str)
361 g_return_if_fail (launcher);
362 g_return_if_fail (input_str);
364 anjuta_launcher_send_ptyin (launcher, input_str);
368 * anjuta_launcher_send_stdin:
369 * @launcher: a #AnjutaLancher object.
371 * Sends a EOF to Standard input of the process currently being executed.
374 void
375 anjuta_launcher_send_stdin_eof (AnjutaLauncher *launcher)
377 GError* err = NULL;
378 g_io_channel_shutdown (launcher->priv->pty_channel, TRUE,
379 &err);
380 g_io_channel_unref (launcher->priv->pty_channel);
381 launcher->priv->pty_channel = NULL;
383 if (err)
385 g_warning ("g_io_channel_shutdown () failed: %s", err->message);
390 * anjuta_launcher_send_ptyin:
391 * @launcher: a #AnjutaLancher object.
392 * @input_str: The string to send to PTY of the process.
394 * Sends a string to TTY input of the process currently being executed.
395 * Mostly useful for entering passwords and other inputs which are directly
396 * read from TTY input of the process.
398 void
399 anjuta_launcher_send_ptyin (AnjutaLauncher *launcher, const gchar * input_str)
401 gsize bytes_written;
402 GError *err = NULL;
404 if (!input_str || strlen (input_str) == 0) return;
408 g_io_channel_write_chars (launcher->priv->pty_channel,
409 input_str, strlen (input_str),
410 &bytes_written, &err);
411 g_io_channel_flush (launcher->priv->pty_channel, NULL);
412 if (err)
414 g_warning ("Error encountered while writing to PTY!. %s",
415 err->message);
416 g_error_free (err);
418 return;
420 input_str += bytes_written;
422 while (*input_str);
426 * anjuta_launcher_reset:
427 * @launcher: a #AnjutaLancher object.
429 * Resets the launcher and kills (SIGTERM) current process, if it is still
430 * executing.
432 void
433 anjuta_launcher_reset (AnjutaLauncher *launcher)
435 if (anjuta_launcher_is_busy (launcher))
436 kill (launcher->priv->child_pid, SIGTERM);
440 * anjuta_launcher_signal:
441 * @launcher: a #AnjutaLancher object.
442 * @sig: kernel signal ID (e.g. SIGTERM).
444 * Sends a kernel signal to the process that is being executed.
446 void
447 anjuta_launcher_signal (AnjutaLauncher *launcher, int sig)
449 kill (launcher->priv->child_pid, sig);
453 * anjuta_launcher_get_child_pid:
454 * @launcher: a #AnjutaLancher object.
456 * Gets the Process ID of the child being executed.
458 * Return value: Process ID of the child.
460 pid_t
461 anjuta_launcher_get_child_pid (AnjutaLauncher *launcher)
463 if (anjuta_launcher_is_busy (launcher))
464 return launcher->priv->child_pid;
465 else
466 return -1;
469 static void
470 anjuta_launcher_synchronize (AnjutaLauncher *launcher)
472 if (launcher->priv->in_cleanup) return;
474 if (launcher->priv->child_has_terminated &&
475 launcher->priv->stdout_is_done &&
476 launcher->priv->stderr_is_done)
478 if (launcher->priv->completion_check_timeout >= 0)
479 g_source_remove (launcher->priv->completion_check_timeout);
480 launcher->priv->completion_check_timeout =
481 g_timeout_add (50, anjuta_launcher_check_for_execution_done,
482 launcher);
485 /* This case is not very good, but it blocks the whole IDE
486 because we never new if the child has finished */
487 else if (launcher->priv->stdout_is_done &&
488 launcher->priv->stderr_is_done)
490 /* DEBUG_PRINT ("Child has't exited yet waiting for 200ms"); */
491 if (launcher->priv->completion_check_timeout >= 0)
492 g_source_remove (launcher->priv->completion_check_timeout);
493 launcher->priv->completion_check_timeout =
494 g_timeout_add(200, anjuta_launcher_check_for_execution_done,
495 launcher);
497 /* Add this case for gdb. It creates child inheriting gdb
498 * pipes which are not closed if gdb crashes */
499 else if (launcher->priv->child_has_terminated &&
500 launcher->priv->terminate_on_exit)
502 if (launcher->priv->completion_check_timeout >= 0)
503 g_source_remove (launcher->priv->completion_check_timeout);
504 launcher->priv->completion_check_timeout =
505 g_timeout_add(0, anjuta_launcher_call_execution_done,
506 launcher);
510 /* Password dialog */
511 static GtkWidget*
512 create_password_dialog (const gchar* prompt)
514 GtkWidget *dialog;
515 GtkWidget *hbox;
516 GtkWidget *box;
517 GtkWidget *icon;
518 GtkWidget *label;
519 GtkWidget *entry;
521 g_return_val_if_fail (prompt, NULL);
523 dialog = gtk_dialog_new_with_buttons (prompt,
524 NULL, //FIXME: Pass the parent window here
525 // for transient purpose.
526 GTK_DIALOG_DESTROY_WITH_PARENT,
527 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
528 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
529 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
531 gtk_window_set_wmclass (GTK_WINDOW (dialog), "launcher-password-prompt",
532 "anjuta");
533 hbox = gtk_hbox_new (FALSE, 10);
534 gtk_widget_show (hbox);
535 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
537 icon = anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD);
538 gtk_widget_show (icon);
539 gtk_box_pack_start_defaults (GTK_BOX(hbox), icon);
541 if (strlen (prompt) < 20) {
542 box = gtk_hbox_new (FALSE, 5);
543 } else {
544 box = gtk_vbox_new (FALSE, 5);
546 gtk_widget_show (box);
547 gtk_box_pack_start_defaults (GTK_BOX (hbox), box);
549 label = gtk_label_new (_(prompt));
550 gtk_widget_show (label);
551 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
553 entry = gtk_entry_new ();
554 gtk_widget_show (entry);
555 gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
556 gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
558 gtk_widget_ref (entry);
559 g_object_set_data_full (G_OBJECT (dialog), "password_entry",
560 gtk_widget_ref (entry),
561 (GDestroyNotify) gtk_widget_unref);
562 gtk_widget_grab_focus (entry);
563 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
565 return dialog;
568 /* pty buffer check for password authentication */
569 static void
570 anjuta_launcher_check_password_real (AnjutaLauncher *launcher,
571 const gchar* last_line)
573 if (anjuta_launcher_is_busy (launcher) == FALSE) return;
575 if (last_line) {
577 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
578 if (is_password_prompt(last_line)) {
579 /* Password prompt detected */
580 GtkWidget* dialog;
581 gint button;
582 const gchar* passwd;
583 gchar* line;
585 dialog = create_password_dialog (last_line);
586 button = gtk_dialog_run (GTK_DIALOG(dialog));
587 switch (button) {
588 case GTK_RESPONSE_OK:
589 passwd = gtk_entry_get_text (
590 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog),
591 "password_entry")));
592 line = g_strconcat (passwd, "\n", NULL);
593 anjuta_launcher_send_ptyin (launcher, line);
594 g_free (line);
595 break;
596 case GTK_RESPONSE_CANCEL:
597 anjuta_launcher_send_ptyin (launcher, "<canceled>\n");
598 anjuta_launcher_reset (launcher);
599 break;
600 default:
601 break;
603 gtk_widget_destroy (dialog);
608 static void
609 anjuta_launcher_check_password (AnjutaLauncher *launcher, const gchar *chars)
611 glong start, end;
612 gchar *last_line;
614 if (!chars || strlen(chars) <= 0)
615 return;
617 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
618 start = end = strlen (chars);
619 while (start > 0 && chars[start-1] != '\n') start--;
621 if (end > start)
623 last_line = g_strndup (&chars[start], end - start + 1);
625 /* DEBUG_PRINT ("Last line = %s", last_line); */
626 /* Checks for password, again */
627 anjuta_launcher_check_password_real (launcher, last_line);
628 g_free (last_line);
632 static gboolean
633 is_password_prompt (const gchar* line)
635 gchar* password = "assword";
636 gchar* passphrase = "assphrase";
638 if (strlen (line) < strlen (password)
639 || strlen (line) < strlen (passphrase))
640 return FALSE;
642 if (g_strstr_len(line, 80, password) != NULL
643 || g_strstr_len(line, 80, passphrase) != NULL)
645 int i;
646 for (i = strlen(line) - 1; i != 0; --i)
648 if (line[i] == ':')
649 return TRUE;
650 if (g_ascii_isspace(line[i]))
651 continue;
652 else
653 return FALSE;
656 return FALSE;
659 static void
660 anjuta_launcher_buffered_output (AnjutaLauncher *launcher,
661 AnjutaLauncherOutputType output_type,
662 const gchar *chars)
664 gchar *all_lines;
665 gchar *incomplete_line;
666 gchar **buffer;
668 g_return_if_fail (chars != NULL);
669 g_return_if_fail (strlen (chars) > 0);
671 if (launcher->priv->output_callback == NULL)
672 return;
673 if (launcher->priv->buffered_output == FALSE)
675 (launcher->priv->output_callback)(launcher, output_type, chars,
676 launcher->priv->callback_data);
677 return;
679 switch (output_type)
681 case ANJUTA_LAUNCHER_OUTPUT_STDOUT:
682 buffer = &launcher->priv->stdout_buffer;
683 break;
684 case ANJUTA_LAUNCHER_OUTPUT_STDERR:
685 buffer = &launcher->priv->stderr_buffer;
686 break;
687 default:
688 g_warning ("Should not reach here");
689 return;
691 if (*buffer)
692 all_lines = g_strconcat (*buffer, chars, NULL);
693 else
694 all_lines = g_strdup (chars);
696 /* Buffer the last incomplete line */
697 incomplete_line = all_lines + strlen (all_lines);
698 while (incomplete_line > all_lines &&
699 *incomplete_line != '\n')
701 incomplete_line = g_utf8_prev_char (incomplete_line);
703 if (*incomplete_line == '\n')
704 incomplete_line++;
706 /* Update line buffer */
707 g_free(*buffer);
708 *buffer = NULL;
709 if (strlen(incomplete_line))
711 *buffer = g_strdup (incomplete_line);
712 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
714 /* Check for password prompt */
715 if (launcher->priv->check_for_passwd_prompt)
716 anjuta_launcher_check_password (launcher, incomplete_line);
718 /* Deliver complete lines */
719 *incomplete_line = '\0';
720 if (strlen (all_lines) > 0)
721 (launcher->priv->output_callback)(launcher, output_type, all_lines,
722 launcher->priv->callback_data);
723 g_free (all_lines);
726 static gboolean
727 anjuta_launcher_scan_output (GIOChannel *channel, GIOCondition condition,
728 AnjutaLauncher *launcher)
730 gsize n;
731 gchar buffer[FILE_BUFFER_SIZE];
732 gboolean ret = TRUE;
734 if (condition & G_IO_IN)
736 GError *err = NULL;
739 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
740 if (n > 0 && !err) /* There is output */
742 gchar *utf8_chars;
743 buffer[n] = '\0';
744 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
745 anjuta_launcher_buffered_output (launcher,
746 ANJUTA_LAUNCHER_OUTPUT_STDOUT,
747 utf8_chars);
748 g_free (utf8_chars);
750 /* The pipe is closed on the other side */
751 /* if not related to non blocking read or interrupted syscall */
752 else if (err && errno != EAGAIN && errno != EINTR)
754 /* DEBUG_PRINT ("launcher.c: Error while reading child stdout\n"); */
755 launcher->priv->stdout_is_done = TRUE;
756 anjuta_launcher_synchronize (launcher);
757 ret = FALSE;
759 /* Read next chars if buffer was too small
760 * (the maximum length of one character is 6 bytes) */
761 } while (!err && (n > FILE_BUFFER_SIZE - 7));
762 if (err)
763 g_error_free (err);
765 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
767 /* DEBUG_PRINT ("launcher.c: STDOUT pipe closed"); */
768 launcher->priv->stdout_is_done = TRUE;
769 anjuta_launcher_synchronize (launcher);
770 ret = FALSE;
772 return ret;
775 static gboolean
776 anjuta_launcher_scan_error (GIOChannel *channel, GIOCondition condition,
777 AnjutaLauncher *launcher)
779 gsize n;
780 gchar buffer[FILE_BUFFER_SIZE];
781 gboolean ret = TRUE;
783 if (condition & G_IO_IN)
785 GError *err = NULL;
788 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
789 if (n > 0 && !err) /* There is stderr output */
791 gchar *utf8_chars;
792 buffer[n] = '\0';
793 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
794 anjuta_launcher_buffered_output (launcher,
795 ANJUTA_LAUNCHER_OUTPUT_STDERR,
796 utf8_chars);
797 g_free (utf8_chars);
799 /* The pipe is closed on the other side */
800 /* if not related to non blocking read or interrupted syscall */
801 else if (err && errno != EAGAIN && errno != EINTR)
803 /* DEBUG_PRINT ("launcher.c: Error while reading child stderr");*/
804 launcher->priv->stderr_is_done = TRUE;
805 anjuta_launcher_synchronize (launcher);
806 ret = FALSE;
808 /* Read next chars if buffer was too small
809 * (the maximum length of one character is 6 bytes) */
810 } while (!err && (n > FILE_BUFFER_SIZE - 7));
811 if (err)
812 g_error_free (err);
814 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
816 /* DEBUG_PRINT ("launcher.c: STDERR pipe closed"); */
817 launcher->priv->stderr_is_done = TRUE;
818 anjuta_launcher_synchronize (launcher);
819 ret = FALSE;
821 return ret;
824 static gboolean
825 anjuta_launcher_scan_pty (GIOChannel *channel, GIOCondition condition,
826 AnjutaLauncher *launcher)
828 gsize n;
829 gchar buffer[FILE_BUFFER_SIZE];
830 gboolean ret = TRUE;
832 if (condition & G_IO_IN)
834 GError *err = NULL;
837 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
838 if (n > 0 && !err) /* There is stderr output */
840 gchar *utf8_chars;
841 gchar *old_str = launcher->priv->pty_output_buffer;
842 buffer[n] = '\0';
843 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
844 if (old_str)
846 gchar *str = g_strconcat (old_str, utf8_chars, NULL);
847 launcher->priv->pty_output_buffer = str;
848 g_free (old_str);
850 else
851 launcher->priv->pty_output_buffer = g_strdup (utf8_chars);
852 g_free (utf8_chars);
854 /* The pipe is closed on the other side */
855 /* if not related to non blocking read or interrupted syscall */
856 else if (err && errno != EAGAIN && errno != EINTR)
858 g_warning (_("launcher.c: Error while reading child pty\n"));
859 ret = FALSE;
861 /* Read next chars if buffer was too small
862 * (the maximum length of one character is 6 bytes) */
863 } while (!err && (n > FILE_BUFFER_SIZE - 7));
864 if (err)
865 g_error_free (err);
866 if (launcher->priv->check_for_passwd_prompt
867 && launcher->priv->pty_output_buffer
868 && strlen (launcher->priv->pty_output_buffer) > 0)
870 anjuta_launcher_check_password (launcher,
871 launcher->priv->pty_output_buffer);
874 /* In pty case, we handle the cases in different invocations */
875 /* Do not hook up for G_IO_HUP */
876 if (condition & G_IO_ERR)
878 /* DEBUG_PRINT ("launcher.c: PTY pipe error!"); */
879 ret = FALSE;
881 return ret;
884 static void
885 anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
886 gboolean emit_signal)
888 gint child_status, child_pid;
889 time_t start_time;
891 if (launcher->priv->in_cleanup)
892 return;
894 launcher->priv->in_cleanup = TRUE;
896 /* Remove pending timeout */
897 if (launcher->priv->completion_check_timeout >= 0)
898 g_source_remove (launcher->priv->completion_check_timeout);
900 /* Make sure all pending I/O are flushed out */
901 while (g_main_context_pending (NULL))
902 g_main_context_iteration (NULL, FALSE);
904 /* Can be called again, while waiting in the previous line
905 * Do nothing if clean up is already done */
906 if (launcher->priv->stdout_channel)
908 g_io_channel_shutdown (launcher->priv->stdout_channel, emit_signal, NULL);
909 g_io_channel_unref (launcher->priv->stdout_channel);
910 g_source_remove (launcher->priv->stdout_watch);
913 if (launcher->priv->stderr_channel)
915 g_io_channel_shutdown (launcher->priv->stderr_channel, emit_signal, NULL);
916 g_io_channel_unref (launcher->priv->stderr_channel);
917 g_source_remove (launcher->priv->stderr_watch);
920 if (launcher->priv->pty_channel)
922 g_io_channel_shutdown (launcher->priv->pty_channel, emit_signal, NULL);
923 g_io_channel_unref (launcher->priv->pty_channel);
925 g_source_remove (launcher->priv->pty_watch);
928 if (launcher->priv->pty_output_buffer)
929 g_free (launcher->priv->pty_output_buffer);
930 if (launcher->priv->stdout_buffer)
931 g_free (launcher->priv->stdout_buffer);
932 if (launcher->priv->stderr_buffer)
933 g_free (launcher->priv->stdout_buffer);
935 /* Save them before we re-initialize */
936 child_status = launcher->priv->child_status;
937 child_pid = launcher->priv->child_pid;
938 start_time = launcher->priv->start_time;
940 if (emit_signal)
941 anjuta_launcher_set_busy (launcher, FALSE);
943 anjuta_launcher_initialize (launcher);
945 /* Call this here, after set_busy (FALSE) so we are able to
946 launch a new child from the terminate function.
947 (by clubfan 2002-04-07)
949 /* DEBUG_PRINT ("Exit status: %d", child_status); */
950 if (emit_signal)
951 g_signal_emit_by_name (launcher, "child-exited", child_pid,
952 child_status,
953 time (NULL) - start_time);
955 launcher->priv->in_cleanup = FALSE;
958 /* Using this function is necessary because
959 * anjuta_launcher_execution_done_cleanup needs to be called in the same
960 * thread than the gtk main loop */
961 static gboolean
962 anjuta_launcher_call_execution_done (gpointer data)
964 AnjutaLauncher *launcher = data;
966 launcher->priv->completion_check_timeout = -1;
967 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
968 return FALSE;
971 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
972 static gboolean
973 anjuta_launcher_check_for_execution_done (gpointer data)
975 AnjutaLauncher *launcher = data;
977 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
978 launcher->priv->stdout_is_done ? 1 : 0,
979 launcher->priv->stderr_is_done ? 1 : 0);
981 if (launcher->priv->stdout_is_done == FALSE ||
982 launcher->priv->stderr_is_done == FALSE)
983 return TRUE;
984 if (launcher->priv->child_has_terminated == FALSE)
986 /* DEBUG_PRINT ("launcher: We missed the exit of the child"); */
987 anjuta_children_recover();
989 launcher->priv->completion_check_timeout = -1;
990 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
991 return FALSE;
994 static void
995 anjuta_launcher_child_terminated (int status, gpointer data)
997 AnjutaLauncher *launcher = data;
999 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher));
1001 /* Save child exit code */
1002 launcher->priv->child_status = status;
1003 launcher->priv->child_has_terminated = TRUE;
1004 anjuta_launcher_synchronize (launcher);
1008 * anjuta_launcher_set_encoding:
1009 * @launcher: a #AnjutaLancher object.
1010 * @charset: Character set to use for Input/Output with the process.
1012 * Sets the character set to use for Input/Output with the process.
1014 * Return value: TRUE if successful, otherwise FALSE.
1016 gboolean
1017 anjuta_launcher_set_encoding (AnjutaLauncher *launcher, const gchar *charset)
1019 GIOStatus s;
1020 gboolean r = TRUE;
1022 g_return_val_if_fail (launcher != NULL, FALSE);
1023 // charset can be NULL
1025 s = g_io_channel_set_encoding (launcher->priv->stderr_channel, charset, NULL);
1026 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1027 s = g_io_channel_set_encoding (launcher->priv->stdout_channel, charset, NULL);
1028 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1029 s = g_io_channel_set_encoding (launcher->priv->pty_channel, charset, NULL);
1030 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1032 if (! r)
1034 g_warning ("launcher.c: Failed to set channel encoding!");
1036 return r;
1039 static pid_t
1040 anjuta_launcher_fork (AnjutaLauncher *launcher, gchar *const args[])
1042 char *working_dir;
1043 int pty_master_fd, md;
1044 int stdout_pipe[2], stderr_pipe[2];
1045 pid_t child_pid;
1046 struct termios termios_flags;
1047 const gchar *charset;
1049 working_dir = g_get_current_dir ();
1051 /* The pipes */
1052 pipe (stderr_pipe);
1053 pipe (stdout_pipe);
1055 /* Fork the command */
1056 child_pid = forkpty (&pty_master_fd, NULL, NULL, NULL);
1057 if (child_pid == 0)
1059 close (2);
1060 dup (stderr_pipe[1]);
1061 close (1);
1062 dup (stdout_pipe[1]);
1064 /* Close unnecessary pipes */
1065 close (stderr_pipe[0]);
1066 close (stdout_pipe[0]);
1069 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1070 perror ("Could not set new controlling tty");
1072 /* Set no delays for the write pipes (non_buffered) so
1073 that we get all the outputs immidiately */
1074 if ((md = fcntl (stdout_pipe[1], F_GETFL)) != -1)
1075 fcntl (stdout_pipe[1], F_SETFL, O_SYNC | md);
1076 if ((md = fcntl (stderr_pipe[1], F_GETFL)) != -1)
1077 fcntl (stderr_pipe[1], F_SETFL, O_SYNC | md);
1079 execvp (args[0], args);
1080 g_warning (_("Cannot execute command: \"%s\""), args[0]);
1081 perror(_("execvp failed"));
1082 _exit(-1);
1084 g_free (working_dir);
1086 /* Close parent's side pipes */
1087 close (stderr_pipe[1]);
1088 close (stdout_pipe[1]);
1090 if (child_pid < 0)
1092 g_warning ("launcher.c: Fork failed!");
1093 /* Close parent's side pipes */
1094 close (stderr_pipe[0]);
1095 close (stdout_pipe[0]);
1096 return child_pid;
1100 * Set pipes none blocking, so we can read big buffers
1101 * in the callback without having to use FIONREAD
1102 * to make sure the callback doesn't block.
1104 if ((md = fcntl (stdout_pipe[0], F_GETFL)) != -1)
1105 fcntl (stdout_pipe[0], F_SETFL, O_NONBLOCK | md);
1106 if ((md = fcntl (stderr_pipe[0], F_GETFL)) != -1)
1107 fcntl (stderr_pipe[0], F_SETFL, O_NONBLOCK | md);
1108 if ((md = fcntl (pty_master_fd, F_GETFL)) != -1)
1109 fcntl (pty_master_fd, F_SETFL, O_NONBLOCK | md);
1111 launcher->priv->child_pid = child_pid;
1112 launcher->priv->stderr_channel = g_io_channel_unix_new (stderr_pipe[0]);
1113 launcher->priv->stdout_channel = g_io_channel_unix_new (stdout_pipe[0]);
1114 launcher->priv->pty_channel = g_io_channel_unix_new (pty_master_fd);
1116 g_io_channel_set_buffer_size (launcher->priv->pty_channel, FILE_INPUT_BUFFER_SIZE);
1119 g_get_charset (&charset);
1120 anjuta_launcher_set_encoding (launcher, charset);
1122 tcgetattr(pty_master_fd, &termios_flags);
1123 termios_flags.c_iflag &= ~(IGNPAR | INPCK | INLCR | IGNCR | ICRNL | IXON |
1124 IXOFF | ISTRIP);
1125 termios_flags.c_iflag |= IGNBRK | BRKINT | IMAXBEL | IXANY;
1126 termios_flags.c_oflag &= ~OPOST;
1127 // termios_flags.c_oflag |= 0;
1128 termios_flags.c_cflag &= ~(CSTOPB | CREAD | PARENB | HUPCL);
1129 termios_flags.c_cflag |= CS8 | CLOCAL;
1131 if (!launcher->priv->terminal_echo_on)
1133 termios_flags.c_lflag &= ~(ECHOKE | ECHOE | ECHO | ECHONL |
1134 #ifdef ECHOPRT
1135 ECHOPRT |
1136 #endif
1137 ECHOCTL | ISIG | ICANON | IEXTEN | NOFLSH | TOSTOP);
1139 // termios_flags.c_lflag |= 0;
1140 termios_flags.c_cc[VMIN] = 0;
1141 cfsetospeed(&termios_flags, __MAX_BAUD);
1142 tcsetattr(pty_master_fd, TCSANOW, &termios_flags);
1144 launcher->priv->stderr_watch =
1145 g_io_add_watch (launcher->priv->stderr_channel,
1146 G_IO_IN | G_IO_ERR | G_IO_HUP,
1147 (GIOFunc)anjuta_launcher_scan_error, launcher);
1148 launcher->priv->stdout_watch =
1149 g_io_add_watch (launcher->priv->stdout_channel,
1150 G_IO_IN | G_IO_ERR | G_IO_HUP,
1151 (GIOFunc)anjuta_launcher_scan_output, launcher);
1152 launcher->priv->pty_watch =
1153 g_io_add_watch (launcher->priv->pty_channel,
1154 G_IO_IN | G_IO_ERR, /* Do not hook up for G_IO_HUP */
1155 (GIOFunc)anjuta_launcher_scan_pty, launcher);
1157 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1158 anjuta_children_register (launcher->priv->child_pid,
1159 anjuta_launcher_child_terminated,
1160 launcher);
1161 return child_pid;
1165 * anjuta_launcher_execute_v:
1166 * @launcher: a #AnjutaLancher object.
1167 * @argv: Command args.
1168 * @callback: The callback for delivering output from the process.
1169 * @callback_data: Callback data for the above callback.
1171 * The first of the @args is the command itself. The rest are sent to the
1172 * as it's arguments. This function works similar to anjuta_launcher_execute().
1174 * Return value: TRUE if successfully launched, otherwise FALSE.
1176 gboolean
1177 anjuta_launcher_execute_v (AnjutaLauncher *launcher, gchar *const argv[],
1178 AnjutaLauncherOutputCallback callback,
1179 gpointer callback_data)
1181 if (anjuta_launcher_is_busy (launcher))
1182 return FALSE;
1184 anjuta_launcher_set_busy (launcher, TRUE);
1186 launcher->priv->start_time = time (NULL);
1187 launcher->priv->child_status = 0;
1188 launcher->priv->stdout_is_done = FALSE;
1189 launcher->priv->stderr_is_done = FALSE;
1190 launcher->priv->child_has_terminated = FALSE;
1191 launcher->priv->in_cleanup = FALSE;
1192 launcher->priv->output_callback = callback;
1193 launcher->priv->callback_data = callback_data;
1195 /* On a fork error perform a cleanup and return */
1196 if (anjuta_launcher_fork (launcher, argv) < 0)
1198 anjuta_launcher_initialize (launcher);
1199 return FALSE;
1201 return TRUE;
1205 * anjuta_launcher_execute:
1206 * @launcher: a #AnjutaLancher object.
1207 * @command_str: The command to execute.
1208 * @callback: The callback for delivering output from the process.
1209 * @callback_data: Callback data for the above callback.
1211 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1212 * delivered to the above callback. The data are delivered as they arrive
1213 * from the process and could be of any lenght. If the process asks for
1214 * passwords, the user will be automatically prompted with a dialog to enter
1215 * it. Please note that not all formats of the password are recognized. Those
1216 * with the standard 'assword:' substring in the prompt should work well.
1218 * Return value: TRUE if successfully launched, otherwise FALSE.
1220 gboolean
1221 anjuta_launcher_execute (AnjutaLauncher *launcher, const gchar *command_str,
1222 AnjutaLauncherOutputCallback callback,
1223 gpointer callback_data)
1225 GList *args_list, *args_list_ptr;
1226 gchar **args, **args_ptr;
1227 gboolean ret;
1229 /* Prepare command args */
1230 args_list = anjuta_util_parse_args_from_string (command_str);
1231 args = g_new (char*, g_list_length (args_list) + 1);
1232 args_list_ptr = args_list;
1233 args_ptr = args;
1234 while (args_list_ptr)
1236 *args_ptr = (char*) args_list_ptr->data;
1237 args_list_ptr = g_list_next (args_list_ptr);
1238 args_ptr++;
1240 *args_ptr = NULL;
1242 ret = anjuta_launcher_execute_v (launcher, args,
1243 callback, callback_data);
1244 g_free (args);
1245 anjuta_util_glist_strings_free (args_list);
1246 return ret;
1250 * anjuta_launcher_set_buffered_output:
1251 * @launcher: a #AnjutaLancher object.
1252 * @buffered: buffer output.
1254 * Sets if output should buffered or not. By default, it is buffered.
1256 * Return value: Previous flag value
1258 gboolean
1259 anjuta_launcher_set_buffered_output (AnjutaLauncher *launcher, gboolean buffered)
1261 gboolean past_value = launcher->priv->buffered_output;
1262 launcher->priv->buffered_output = buffered;
1263 return past_value;
1267 * anjuta_launcher_set_check_passwd_prompt:
1268 * @launcher: a #AnjutaLancher object.
1269 * @check_passwd: check for password.
1271 * Set if output is checked for a password prompti. A special dialog box
1272 * is use to enter it in this case. By default, this behavior is enabled.
1274 * Return value: Previous flag value
1276 gboolean
1277 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher *launcher, gboolean check_passwd)
1279 gboolean past_value = launcher->priv->check_for_passwd_prompt;
1280 launcher->priv->check_for_passwd_prompt = check_passwd;
1281 return past_value;
1285 * anjuta_launcher_set_terminal_echo:
1286 * @launcher: a #AnjutaLancher object.
1287 * @echo_on: Echo ON flag.
1289 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1290 * it is disabled.
1292 * Return value: Previous flag value
1294 gboolean
1295 anjuta_launcher_set_terminal_echo (AnjutaLauncher *launcher,
1296 gboolean echo_on)
1298 gboolean past_value = launcher->priv->terminal_echo_on;
1299 launcher->priv->terminal_echo_on = echo_on;
1300 return past_value;
1304 * anjuta_launcher_set_terminate_on_exit:
1305 * @launcher: a #AnjutaLancher object.
1306 * @terminate_on_exit: terminate on exit flag
1308 * When this flag is set, al i/o channels are closed and the child-exit
1309 * signal is emitted as soon as the child exit. By default, or when this
1310 * flag is clear, the launcher object wait until the i/o channels are
1311 * closed.
1313 * Return value: Previous flag value
1315 gboolean
1316 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher *launcher,
1317 gboolean terminate_on_exit)
1319 gboolean past_value = launcher->priv->terminate_on_exit;
1320 launcher->priv->terminate_on_exit = terminate_on_exit;
1321 return past_value;
1325 * anjuta_launcher_new:
1327 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1328 * it is disabled.
1330 * Return value: a new instance of #AnjutaLancher class.
1332 AnjutaLauncher*
1333 anjuta_launcher_new ()
1335 return g_object_new (ANJUTA_TYPE_LAUNCHER, NULL);