Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / libanjuta / anjuta-launcher.c
blob9c721e2876526bb796029d50b6c47435fc61c5c1
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(__FreeBSD__)
40 # include <libutil.h>
41 #elif defined(__OpenBSD__) || defined(__NetBSD__)
42 # include <util.h>
43 #elif !defined(__sun)
44 # include <pty.h>
45 #endif
47 #include "anjuta-utils-priv.h"
49 #include <assert.h>
50 #include <termios.h>
52 #include <string.h>
53 #include <time.h>
54 #include <glib/gi18n.h>
55 #include <glib.h>
57 #include "anjuta-utils.h"
58 #include "anjuta-marshal.h"
59 #include "resources.h"
60 #include "anjuta-launcher.h"
61 #include "anjuta-debug.h"
63 #define ANJUTA_PIXMAP_PASSWORD "password.png"
64 #define FILE_BUFFER_SIZE 1024
65 #define FILE_INPUT_BUFFER_SIZE 1048576
66 #ifndef __MAX_BAUD
67 # if defined(B460800)
68 # define __MAX_BAUD B460800
69 # elif defined(B307200)
70 # define __MAX_BAUD B307200
71 # elif defined(B256000)
72 # define __MAX_BAUD B256000
73 # else
74 # define __MAX_BAUD B230400
75 # endif
76 #endif
79 static gboolean
80 anjuta_launcher_pty_check_child_exit_code (AnjutaLauncher *launcher,
81 const gchar* line);
83 struct _AnjutaLauncherPriv
86 * Busy flag is TRUE if the Launcher
87 * is currently executing a child.
89 gboolean busy;
91 /* These flags are used to synchronize the IO operations. */
92 gboolean stdout_is_done;
93 gboolean stderr_is_done;
95 /* GIO channels */
96 GIOChannel *stdout_channel;
97 GIOChannel *stderr_channel;
98 /*GIOChannel *stdin_channel;*/
99 GIOChannel *pty_channel;
101 /* GIO watch handles */
102 guint stdout_watch;
103 guint stderr_watch;
104 guint pty_watch;
106 /* Output line buffers */
107 gchar *stdout_buffer;
108 gchar *stderr_buffer;
110 /* Output of the pty is constantly stored here.*/
111 gchar *pty_output_buffer;
113 /* Terminal echo */
114 gboolean terminal_echo_on;
116 /* The child */
117 pid_t child_pid;
118 guint source;
119 gint child_status;
120 gboolean child_has_terminated;
122 /* Synchronization in progress */
123 gboolean in_cleanup;
124 guint completion_check_timeout;
126 /* Terminate child on child exit */
127 gboolean terminate_on_exit;
129 /* Start time of execution */
130 time_t start_time;
132 /* Should the outputs be buffered */
133 gboolean buffered_output;
135 /* Should we check for password prompts in stdout and pty */
136 gboolean check_for_passwd_prompt;
138 /* Output callback */
139 AnjutaLauncherOutputCallback output_callback;
141 /* Callback data */
142 gpointer callback_data;
144 /* Encondig */
145 gboolean custom_encoding;
146 gchar* encoding;
148 /* Env */
149 GHashTable* env;
152 enum
154 /* OUTPUT_ARRIVED_SIGNAL, */
155 CHILD_EXITED_SIGNAL,
156 BUSY_SIGNAL,
157 LAST_SIGNAL
160 static void anjuta_launcher_class_init (AnjutaLauncherClass * klass);
161 static void anjuta_launcher_init (AnjutaLauncher * obj);
162 static gboolean anjuta_launcher_call_execution_done (gpointer data);
163 static gboolean anjuta_launcher_check_for_execution_done (gpointer data);
164 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
165 gboolean emit_signal);
167 static gboolean is_password_prompt(const gchar* line);
169 static guint launcher_signals[LAST_SIGNAL] = { 0 };
170 static AnjutaLauncherClass *parent_class;
172 static void
173 anjuta_launcher_initialize (AnjutaLauncher *obj)
175 /* Busy flag */
176 obj->priv->busy = FALSE;
178 /* These flags are used to synchronize the IO operations. */
179 obj->priv->stdout_is_done = FALSE;
180 obj->priv->stderr_is_done = FALSE;
182 /* GIO channels */
183 obj->priv->stdout_channel = NULL;
184 obj->priv->stderr_channel = NULL;
185 obj->priv->pty_channel = NULL;
187 /* Output line buffers */
188 obj->priv->stdout_buffer = NULL;
189 obj->priv->stderr_buffer = NULL;
191 /* Pty buffer */
192 obj->priv->pty_output_buffer = NULL;
194 obj->priv->terminal_echo_on = TRUE;
196 /* The child */
197 obj->priv->child_pid = 0;
198 obj->priv->child_status = -1;
199 obj->priv->child_has_terminated = TRUE;
200 obj->priv->source = 0;
202 /* Synchronization in progress */
203 obj->priv->in_cleanup = FALSE;
204 obj->priv->completion_check_timeout = -1;
206 /* Terminate child on child exit */
207 obj->priv->terminate_on_exit = FALSE;
209 /* Start time of execution */
210 obj->priv->start_time = 0;
212 obj->priv->buffered_output = TRUE;
213 obj->priv->check_for_passwd_prompt = TRUE;
215 /* Output callback */
216 obj->priv->output_callback = NULL;
217 obj->priv->callback_data = NULL;
219 /* Encoding */
220 obj->priv->custom_encoding = FALSE;
221 obj->priv->encoding = NULL;
223 /* Env */
224 obj->priv->env = g_hash_table_new_full (g_str_hash, g_str_equal,
225 g_free, g_free);
228 GType
229 anjuta_launcher_get_type ()
231 static GType obj_type = 0;
233 if (!obj_type)
235 static const GTypeInfo obj_info =
237 sizeof (AnjutaLauncherClass),
238 (GBaseInitFunc) NULL,
239 (GBaseFinalizeFunc) NULL,
240 (GClassInitFunc) anjuta_launcher_class_init,
241 (GClassFinalizeFunc) NULL,
242 NULL, /* class_data */
243 sizeof (AnjutaLauncher),
244 0, /* n_preallocs */
245 (GInstanceInitFunc) anjuta_launcher_init,
246 NULL /* value_table */
248 obj_type = g_type_register_static (G_TYPE_OBJECT,
249 "AnjutaLauncher", &obj_info, 0);
251 return obj_type;
254 static void
255 anjuta_launcher_dispose (GObject *obj)
257 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
258 if (anjuta_launcher_is_busy (launcher))
260 g_source_remove (launcher->priv->source);
261 launcher->priv->source = 0;
263 anjuta_launcher_execution_done_cleanup (launcher, FALSE);
265 launcher->priv->busy = FALSE;
268 G_OBJECT_CLASS (parent_class)->dispose (obj);
271 static void
272 anjuta_launcher_finalize (GObject *obj)
274 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
275 if (launcher->priv->custom_encoding && launcher->priv->encoding)
276 g_free (launcher->priv->encoding);
278 g_hash_table_destroy (launcher->priv->env);
280 g_free (launcher->priv);
281 G_OBJECT_CLASS (parent_class)->finalize (obj);
284 static void
285 anjuta_launcher_class_init (AnjutaLauncherClass * klass)
287 GObjectClass *object_class;
288 g_return_if_fail (klass != NULL);
289 object_class = (GObjectClass *) klass;
291 /* DEBUG_PRINT ("Initializing launcher class"); */
293 parent_class = g_type_class_peek_parent (klass);
296 * AnjutaLauncher::child-exited
297 * @launcher: a #AnjutaLancher object.
298 * @child_pid: process ID of the child
299 * @status: status as returned by waitpid function
300 * @time: time in seconds taken by the child
302 * Emitted when the child has exited and all i/o channels have
303 * been closed. If the terminate on exit flag is set, the i/o
304 * channels are automatically closed when the child exit.
305 * You need to use WEXITSTATUS and friend to get the child exit
306 * code from the status returned.
308 launcher_signals[CHILD_EXITED_SIGNAL] =
309 g_signal_new ("child-exited",
310 G_TYPE_FROM_CLASS (object_class),
311 G_SIGNAL_RUN_FIRST,
312 G_STRUCT_OFFSET (AnjutaLauncherClass,
313 child_exited),
314 NULL, NULL,
315 anjuta_cclosure_marshal_VOID__INT_INT_ULONG,
316 G_TYPE_NONE, 3, G_TYPE_INT,
317 G_TYPE_INT, G_TYPE_ULONG);
320 * AnjutaLauncher::busy
321 * @launcher: a #AnjutaLancher object.
322 * @busy: TRUE is a child is currently running
324 * Emitted when a child starts after a call to one execute function
325 * (busy is TRUE) or when a child exits and all i/o channels are
326 * closed (busy is FALSE).
328 launcher_signals[BUSY_SIGNAL] =
329 g_signal_new ("busy",
330 G_TYPE_FROM_CLASS (object_class),
331 G_SIGNAL_RUN_FIRST,
332 G_STRUCT_OFFSET (AnjutaLauncherClass,
333 busy),
334 NULL, NULL,
335 anjuta_cclosure_marshal_VOID__BOOLEAN,
336 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
338 object_class->dispose = anjuta_launcher_dispose;
339 object_class->finalize = anjuta_launcher_finalize;
342 static void
343 anjuta_launcher_init (AnjutaLauncher * obj)
345 g_return_if_fail (obj != NULL);
346 obj->priv = g_new0 (AnjutaLauncherPriv, 1);
347 anjuta_launcher_initialize (obj);
351 * anjuta_launcher_is_busy:
352 * @launcher: a #AnjutaLancher object.
354 * Tells if the laucher is currently executing any command.
356 * Return value: TRUE if launcher is busy, otherwisee FALSE.
358 gboolean
359 anjuta_launcher_is_busy (AnjutaLauncher *launcher)
361 return launcher->priv->busy;
364 static void
365 anjuta_launcher_set_busy (AnjutaLauncher *launcher, gboolean flag)
367 gboolean old_busy = launcher->priv->busy;
368 launcher->priv->busy = flag;
369 if (old_busy != flag)
370 g_signal_emit_by_name (G_OBJECT (launcher), "busy", flag);
374 * anjuta_launcher_send_stdin:
375 * @launcher: a #AnjutaLancher object.
376 * @input_str: The string to send to STDIN of the process.
378 * Sends a string to Standard input of the process currently being executed.
380 void
381 anjuta_launcher_send_stdin (AnjutaLauncher *launcher, const gchar * input_str)
383 g_return_if_fail (launcher);
384 g_return_if_fail (input_str);
386 anjuta_launcher_send_ptyin (launcher, input_str);
390 * anjuta_launcher_send_stdin:
391 * @launcher: a #AnjutaLancher object.
393 * Sends a EOF to Standard input of the process currently being executed.
396 void
397 anjuta_launcher_send_stdin_eof (AnjutaLauncher *launcher)
399 GError* err = NULL;
400 g_io_channel_shutdown (launcher->priv->pty_channel, TRUE,
401 &err);
402 g_io_channel_unref (launcher->priv->pty_channel);
403 launcher->priv->pty_channel = NULL;
405 if (err)
407 g_warning ("g_io_channel_shutdown () failed: %s", err->message);
412 * anjuta_launcher_send_ptyin:
413 * @launcher: a #AnjutaLancher object.
414 * @input_str: The string to send to PTY of the process.
416 * Sends a string to TTY input of the process currently being executed.
417 * Mostly useful for entering passwords and other inputs which are directly
418 * read from TTY input of the process.
420 void
421 anjuta_launcher_send_ptyin (AnjutaLauncher *launcher, const gchar * input_str)
423 gsize bytes_written;
424 GError *err = NULL;
426 if (!input_str || strlen (input_str) == 0) return;
430 g_io_channel_write_chars (launcher->priv->pty_channel,
431 input_str, strlen (input_str),
432 &bytes_written, &err);
433 g_io_channel_flush (launcher->priv->pty_channel, NULL);
434 if (err)
436 g_warning ("Error encountered while writing to PTY!. %s",
437 err->message);
438 g_error_free (err);
440 return;
442 input_str += bytes_written;
444 while (*input_str);
448 * anjuta_launcher_reset:
449 * @launcher: a #AnjutaLancher object.
451 * Resets the launcher and kills (SIGTERM) current process, if it is still
452 * executing.
454 void
455 anjuta_launcher_reset (AnjutaLauncher *launcher)
457 if (anjuta_launcher_is_busy (launcher))
458 kill (launcher->priv->child_pid, SIGTERM);
462 * anjuta_launcher_signal:
463 * @launcher: a #AnjutaLancher object.
464 * @sig: kernel signal ID (e.g. SIGTERM).
466 * Sends a kernel signal to the process that is being executed.
468 void
469 anjuta_launcher_signal (AnjutaLauncher *launcher, int sig)
471 kill (launcher->priv->child_pid, sig);
475 * anjuta_launcher_get_child_pid:
476 * @launcher: a #AnjutaLancher object.
478 * Gets the Process ID of the child being executed.
480 * Return value: Process ID of the child.
482 pid_t
483 anjuta_launcher_get_child_pid (AnjutaLauncher *launcher)
485 if (anjuta_launcher_is_busy (launcher))
486 return launcher->priv->child_pid;
487 else
488 return -1;
491 static void
492 anjuta_launcher_synchronize (AnjutaLauncher *launcher)
494 if (launcher->priv->in_cleanup) return;
496 if (launcher->priv->child_has_terminated &&
497 launcher->priv->stdout_is_done &&
498 launcher->priv->stderr_is_done)
500 if (launcher->priv->completion_check_timeout >= 0)
501 g_source_remove (launcher->priv->completion_check_timeout);
502 launcher->priv->completion_check_timeout =
503 g_timeout_add (50, anjuta_launcher_check_for_execution_done,
504 launcher);
507 /* This case is not very good, but it blocks the whole IDE
508 because we never new if the child has finished */
509 else if (launcher->priv->stdout_is_done &&
510 launcher->priv->stderr_is_done)
512 /* DEBUG_PRINT ("Child has't exited yet waiting for 200ms"); */
513 if (launcher->priv->completion_check_timeout >= 0)
514 g_source_remove (launcher->priv->completion_check_timeout);
515 launcher->priv->completion_check_timeout =
516 g_timeout_add(200, anjuta_launcher_check_for_execution_done,
517 launcher);
519 /* Add this case for gdb. It creates child inheriting gdb
520 * pipes which are not closed if gdb crashes */
521 else if (launcher->priv->child_has_terminated &&
522 launcher->priv->terminate_on_exit)
524 if (launcher->priv->completion_check_timeout >= 0)
525 g_source_remove (launcher->priv->completion_check_timeout);
526 launcher->priv->completion_check_timeout =
527 g_timeout_add(0, anjuta_launcher_call_execution_done,
528 launcher);
532 /* Password dialog */
533 static GtkWidget*
534 create_password_dialog (const gchar* prompt)
536 GtkWidget *dialog;
537 GtkWidget *hbox;
538 GtkWidget *box;
539 GtkWidget *icon;
540 GtkWidget *label;
541 GtkWidget *entry;
543 g_return_val_if_fail (prompt, NULL);
545 dialog = gtk_dialog_new_with_buttons (prompt,
546 NULL, //FIXME: Pass the parent window here
547 // for transient purpose.
548 GTK_DIALOG_DESTROY_WITH_PARENT,
549 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
550 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
551 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
553 gtk_window_set_wmclass (GTK_WINDOW (dialog), "launcher-password-prompt",
554 "anjuta");
555 hbox = gtk_hbox_new (FALSE, 10);
556 gtk_widget_show (hbox);
557 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
559 icon = anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD);
560 gtk_widget_show (icon);
561 gtk_box_pack_start_defaults (GTK_BOX(hbox), icon);
563 if (strlen (prompt) < 20) {
564 box = gtk_hbox_new (FALSE, 5);
565 } else {
566 box = gtk_vbox_new (FALSE, 5);
568 gtk_widget_show (box);
569 gtk_box_pack_start_defaults (GTK_BOX (hbox), box);
571 label = gtk_label_new (_(prompt));
572 gtk_widget_show (label);
573 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
575 entry = gtk_entry_new ();
576 gtk_widget_show (entry);
577 gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
578 gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
580 gtk_widget_ref (entry);
581 g_object_set_data_full (G_OBJECT (dialog), "password_entry",
582 gtk_widget_ref (entry),
583 (GDestroyNotify) gtk_widget_unref);
584 gtk_widget_grab_focus (entry);
585 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
587 return dialog;
590 /* pty buffer check for password authentication */
591 static void
592 anjuta_launcher_check_password_real (AnjutaLauncher *launcher,
593 const gchar* last_line)
595 if (anjuta_launcher_is_busy (launcher) == FALSE)
596 return;
598 if (last_line) {
600 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
601 if (is_password_prompt(last_line)) {
602 /* Password prompt detected */
603 GtkWidget* dialog;
604 gint button;
605 const gchar* passwd;
606 gchar* line;
608 dialog = create_password_dialog (last_line);
609 button = gtk_dialog_run (GTK_DIALOG(dialog));
610 switch (button) {
611 case GTK_RESPONSE_OK:
612 passwd = gtk_entry_get_text (
613 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog),
614 "password_entry")));
615 line = g_strconcat (passwd, "\n", NULL);
616 anjuta_launcher_send_ptyin (launcher, line);
617 g_free (line);
618 break;
619 case GTK_RESPONSE_CANCEL:
620 anjuta_launcher_reset (launcher);
621 break;
622 default:
623 break;
625 gtk_widget_destroy (dialog);
630 static void
631 anjuta_launcher_check_password (AnjutaLauncher *launcher, const gchar *chars)
633 glong start, end;
634 gchar *last_line;
636 if (!chars || strlen(chars) <= 0)
637 return;
639 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
640 start = end = strlen (chars);
641 while (start > 0 && chars[start-1] != '\n') start--;
643 if (end > start)
645 last_line = g_strndup (&chars[start], end - start + 1);
647 /* DEBUG_PRINT ("Last line = %s", last_line); */
648 /* Checks for password, again */
649 anjuta_launcher_check_password_real (launcher, last_line);
650 g_free (last_line);
654 static gboolean
655 is_password_prompt (const gchar* line)
657 const gchar* password = "assword";
658 const gchar* passphrase = "assphrase";
660 if (strlen (line) < strlen (password)
661 || strlen (line) < strlen (passphrase))
662 return FALSE;
664 if (g_strstr_len(line, 80, password) != NULL
665 || g_strstr_len(line, 80, passphrase) != NULL)
667 int i;
668 for (i = strlen(line) - 1; i != 0; --i)
670 if (line[i] == ':')
671 return TRUE;
672 if (g_ascii_isspace(line[i]))
673 continue;
674 else
675 return FALSE;
678 return FALSE;
681 static void
682 anjuta_launcher_buffered_output (AnjutaLauncher *launcher,
683 AnjutaLauncherOutputType output_type,
684 const gchar *chars)
686 gchar *all_lines;
687 gchar *incomplete_line;
688 gchar **buffer;
690 g_return_if_fail (chars != NULL);
691 g_return_if_fail (strlen (chars) > 0);
693 if (launcher->priv->output_callback == NULL)
694 return;
695 if (launcher->priv->buffered_output == FALSE)
697 (launcher->priv->output_callback)(launcher, output_type, chars,
698 launcher->priv->callback_data);
699 return;
701 switch (output_type)
703 case ANJUTA_LAUNCHER_OUTPUT_STDOUT:
704 buffer = &launcher->priv->stdout_buffer;
705 break;
706 case ANJUTA_LAUNCHER_OUTPUT_STDERR:
707 buffer = &launcher->priv->stderr_buffer;
708 break;
709 default:
710 g_warning ("Should not reach here");
711 return;
713 if (*buffer)
714 all_lines = g_strconcat (*buffer, chars, NULL);
715 else
716 all_lines = g_strdup (chars);
718 /* Buffer the last incomplete line */
719 incomplete_line = all_lines + strlen (all_lines);
720 while (incomplete_line > all_lines &&
721 *incomplete_line != '\n')
723 incomplete_line = g_utf8_prev_char (incomplete_line);
725 if (*incomplete_line == '\n')
726 incomplete_line++;
728 /* Update line buffer */
729 g_free(*buffer);
730 *buffer = NULL;
731 if (strlen(incomplete_line))
733 *buffer = g_strdup (incomplete_line);
734 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
736 /* Check for password prompt */
737 if (launcher->priv->check_for_passwd_prompt)
738 anjuta_launcher_check_password (launcher, incomplete_line);
740 /* Deliver complete lines */
741 *incomplete_line = '\0';
742 if (strlen (all_lines) > 0)
743 (launcher->priv->output_callback)(launcher, output_type, all_lines,
744 launcher->priv->callback_data);
745 g_free (all_lines);
748 static gboolean
749 anjuta_launcher_scan_output (GIOChannel *channel, GIOCondition condition,
750 AnjutaLauncher *launcher)
752 gsize n;
753 gchar buffer[FILE_BUFFER_SIZE];
754 gboolean ret = TRUE;
756 if (condition & G_IO_IN)
758 GError *err = NULL;
761 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
762 if (n > 0) /* There is output */
764 gchar *utf8_chars = NULL;
765 buffer[n] = '\0';
766 if (!launcher->priv->custom_encoding)
767 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
768 else
769 utf8_chars = g_strdup(buffer);
770 anjuta_launcher_buffered_output (launcher,
771 ANJUTA_LAUNCHER_OUTPUT_STDOUT,
772 utf8_chars);
773 g_free (utf8_chars);
775 /* Ignore illegal characters */
776 if (err && err->domain == G_CONVERT_ERROR)
778 g_error_free (err);
779 err = NULL;
781 /* The pipe is closed on the other side */
782 /* if not related to non blocking read or interrupted syscall */
783 else if (err && errno != EAGAIN && errno != EINTR)
785 launcher->priv->stdout_is_done = TRUE;
786 anjuta_launcher_synchronize (launcher);
787 ret = FALSE;
789 /* Read next chars if buffer was too small
790 * (the maximum length of one character is 6 bytes) */
791 } while (!err && (n > FILE_BUFFER_SIZE - 7));
792 if (err)
793 g_error_free (err);
795 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
797 DEBUG_PRINT ("launcher.c: STDOUT pipe closed");
798 launcher->priv->stdout_is_done = TRUE;
799 anjuta_launcher_synchronize (launcher);
800 ret = FALSE;
802 return ret;
805 static gboolean
806 anjuta_launcher_scan_error (GIOChannel *channel, GIOCondition condition,
807 AnjutaLauncher *launcher)
809 gsize n;
810 gchar buffer[FILE_BUFFER_SIZE];
811 gboolean ret = TRUE;
813 if (condition & G_IO_IN)
815 GError *err = NULL;
818 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
819 if (n > 0) /* There is stderr output */
821 gchar *utf8_chars;
822 buffer[n] = '\0';
823 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
824 anjuta_launcher_buffered_output (launcher,
825 ANJUTA_LAUNCHER_OUTPUT_STDERR,
826 utf8_chars);
827 g_free (utf8_chars);
829 /* Ignore illegal characters */
830 if (err && err->domain == G_CONVERT_ERROR)
832 g_error_free (err);
833 err = NULL;
835 /* The pipe is closed on the other side */
836 /* if not related to non blocking read or interrupted syscall */
837 else if (err && errno != EAGAIN && errno != EINTR)
840 launcher->priv->stderr_is_done = TRUE;
841 anjuta_launcher_synchronize (launcher);
842 ret = FALSE;
844 /* Read next chars if buffer was too small
845 * (the maximum length of one character is 6 bytes) */
846 } while (!err && (n > FILE_BUFFER_SIZE - 7));
847 if (err)
848 g_error_free (err);
850 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
852 DEBUG_PRINT ("launcher.c: STDERR pipe closed");
853 launcher->priv->stderr_is_done = TRUE;
854 anjuta_launcher_synchronize (launcher);
855 ret = FALSE;
857 return ret;
860 static gboolean
861 anjuta_launcher_scan_pty (GIOChannel *channel, GIOCondition condition,
862 AnjutaLauncher *launcher)
864 gsize n;
865 gchar buffer[FILE_BUFFER_SIZE];
866 gboolean ret = TRUE;
868 if (condition & G_IO_IN)
870 GError *err = NULL;
873 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
874 if (n > 0) /* There is stderr output */
876 gchar *utf8_chars;
877 gchar *old_str = launcher->priv->pty_output_buffer;
878 buffer[n] = '\0';
879 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
880 if (old_str)
882 gchar *str = g_strconcat (old_str, utf8_chars, NULL);
883 launcher->priv->pty_output_buffer = str;
884 g_free (old_str);
886 else
887 launcher->priv->pty_output_buffer = g_strdup (utf8_chars);
888 g_free (utf8_chars);
890 /* Ignore illegal characters */
891 if (err && err->domain == G_CONVERT_ERROR)
893 g_error_free (err);
894 err = NULL;
896 /* The pipe is closed on the other side */
897 /* if not related to non blocking read or interrupted syscall */
898 else if (err && errno != EAGAIN && errno != EINTR)
900 ret = FALSE;
902 /* Read next chars if buffer was too small
903 * (the maximum length of one character is 6 bytes) */
904 } while (!err && (n > FILE_BUFFER_SIZE - 7));
905 if (err)
906 g_error_free (err);
907 if (launcher->priv->check_for_passwd_prompt
908 && launcher->priv->pty_output_buffer
909 && strlen (launcher->priv->pty_output_buffer) > 0)
911 anjuta_launcher_check_password (launcher,
912 launcher->priv->pty_output_buffer);
915 /* In pty case, we handle the cases in different invocations */
916 /* Do not hook up for G_IO_HUP */
917 if (condition & G_IO_ERR)
919 DEBUG_PRINT ("launcher.c: PTY pipe error!");
920 ret = FALSE;
922 return ret;
925 static void
926 anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
927 gboolean emit_signal)
929 gint child_status, child_pid;
930 time_t start_time;
932 if (launcher->priv->in_cleanup)
933 return;
935 launcher->priv->in_cleanup = TRUE;
937 /* Remove pending timeout */
938 if (launcher->priv->completion_check_timeout >= 0)
939 g_source_remove (launcher->priv->completion_check_timeout);
941 /* Make sure all pending I/O are flushed out */
942 while (g_main_context_pending (NULL))
943 g_main_context_iteration (NULL, FALSE);
945 /* Can be called again, while waiting in the previous line
946 * Do nothing if clean up is already done */
947 if (launcher->priv->stdout_channel)
949 g_io_channel_shutdown (launcher->priv->stdout_channel, emit_signal, NULL);
950 g_io_channel_unref (launcher->priv->stdout_channel);
951 g_source_remove (launcher->priv->stdout_watch);
954 if (launcher->priv->stderr_channel)
956 g_io_channel_shutdown (launcher->priv->stderr_channel, emit_signal, NULL);
957 g_io_channel_unref (launcher->priv->stderr_channel);
958 g_source_remove (launcher->priv->stderr_watch);
961 if (launcher->priv->pty_channel)
963 g_io_channel_shutdown (launcher->priv->pty_channel, emit_signal, NULL);
964 g_io_channel_unref (launcher->priv->pty_channel);
966 g_source_remove (launcher->priv->pty_watch);
969 if (launcher->priv->pty_output_buffer)
970 g_free (launcher->priv->pty_output_buffer);
971 if (launcher->priv->stdout_buffer)
972 g_free (launcher->priv->stdout_buffer);
973 if (launcher->priv->stderr_buffer)
974 g_free (launcher->priv->stdout_buffer);
976 /* Save them before we re-initialize */
977 child_status = launcher->priv->child_status;
978 child_pid = launcher->priv->child_pid;
979 start_time = launcher->priv->start_time;
981 if (emit_signal)
982 anjuta_launcher_set_busy (launcher, FALSE);
984 anjuta_launcher_initialize (launcher);
987 /* Call this here, after set_busy (FALSE) so we are able to
988 launch a new child from the terminate function.
989 (by clubfan 2002-04-07)
991 /* DEBUG_PRINT ("Exit status: %d", child_status); */
992 if (emit_signal)
993 g_signal_emit_by_name (launcher, "child-exited", child_pid,
994 child_status,
995 time (NULL) - start_time);
998 /* Using this function is necessary because
999 * anjuta_launcher_execution_done_cleanup needs to be called in the same
1000 * thread than the gtk main loop */
1001 static gboolean
1002 anjuta_launcher_call_execution_done (gpointer data)
1004 AnjutaLauncher *launcher = data;
1006 launcher->priv->completion_check_timeout = -1;
1007 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
1008 return FALSE;
1011 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
1012 static gboolean
1013 anjuta_launcher_check_for_execution_done (gpointer data)
1015 AnjutaLauncher *launcher = data;
1017 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
1018 launcher->priv->stdout_is_done ? 1 : 0,
1019 launcher->priv->stderr_is_done ? 1 : 0);
1021 if (launcher->priv->stdout_is_done == FALSE ||
1022 launcher->priv->stderr_is_done == FALSE)
1023 return TRUE;
1024 if (launcher->priv->child_has_terminated == FALSE)
1026 /* DEBUG_PRINT ("launcher: We missed the exit of the child"); */
1028 launcher->priv->completion_check_timeout = -1;
1029 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
1030 return FALSE;
1033 static void
1034 anjuta_launcher_child_terminated (GPid pid, gint status, gpointer data)
1036 AnjutaLauncher *launcher = data;
1038 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher));
1040 /* Save child exit code */
1041 launcher->priv->child_status = status;
1042 launcher->priv->child_has_terminated = TRUE;
1043 anjuta_launcher_synchronize (launcher);
1047 static gboolean
1048 anjuta_launcher_set_encoding_real (AnjutaLauncher *launcher, const gchar *charset)
1050 GIOStatus s;
1051 gboolean r = TRUE;
1053 g_return_val_if_fail (launcher != NULL, FALSE);
1054 // charset can be NULL
1056 s = g_io_channel_set_encoding (launcher->priv->stderr_channel, charset, NULL);
1057 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1058 s = g_io_channel_set_encoding (launcher->priv->stdout_channel, charset, NULL);
1059 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1060 s = g_io_channel_set_encoding (launcher->priv->pty_channel, charset, NULL);
1061 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1063 if (! r)
1065 g_warning ("launcher.c: Failed to set channel encoding!");
1067 return r;
1072 * anjuta_launcher_set_encoding:
1073 * @launcher: a #AnjutaLancher object.
1074 * @charset: Character set to use for Input/Output with the process.
1076 * Sets the character set to use for Input/Output with the process.
1079 void
1080 anjuta_launcher_set_encoding (AnjutaLauncher *launcher, const gchar *charset)
1082 if (launcher->priv->custom_encoding)
1083 g_free (launcher->priv->encoding);
1085 launcher->priv->custom_encoding = TRUE;
1086 if (charset)
1087 launcher->priv->encoding = g_strdup(charset);
1088 else
1089 launcher->priv->encoding = NULL;
1092 static pid_t
1093 anjuta_launcher_fork (AnjutaLauncher *launcher, gchar *const args[], gchar *const envp[])
1095 char *working_dir;
1096 int pty_master_fd, md;
1097 int stdout_pipe[2], stderr_pipe[2];
1098 pid_t child_pid;
1099 struct termios termios_flags;
1100 gchar * const *env;
1102 working_dir = g_get_current_dir ();
1104 /* The pipes */
1105 pipe (stderr_pipe);
1106 pipe (stdout_pipe);
1108 /* Fork the command */
1109 child_pid = forkpty (&pty_master_fd, NULL, NULL, NULL);
1110 if (child_pid == 0)
1112 close (2);
1113 dup (stderr_pipe[1]);
1114 close (1);
1115 dup (stdout_pipe[1]);
1117 /* Close unnecessary pipes */
1118 close (stderr_pipe[0]);
1119 close (stdout_pipe[0]);
1122 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1123 perror ("Could not set new controlling tty");
1125 /* Set no delays for the write pipes (non_buffered) so
1126 that we get all the outputs immidiately */
1127 if ((md = fcntl (stdout_pipe[1], F_GETFL)) != -1)
1128 fcntl (stdout_pipe[1], F_SETFL, O_SYNC | md);
1129 if ((md = fcntl (stderr_pipe[1], F_GETFL)) != -1)
1130 fcntl (stderr_pipe[1], F_SETFL, O_SYNC | md);
1132 /* Set up environment */
1133 if (envp != NULL)
1135 GString *variable = g_string_new (NULL);
1136 for (env = envp; *env != NULL; env++)
1138 gchar *value = strchr (*env, '=');
1140 if (value == NULL)
1142 g_setenv (*env, NULL, TRUE);
1144 else
1146 g_string_truncate (variable, 0);
1147 g_string_append_len (variable, *env, value - *env);
1148 g_setenv (variable->str, value + 1, TRUE);
1153 execvp (args[0], args);
1154 g_warning (_("Cannot execute command: \"%s\""), args[0]);
1155 perror(_("execvp failed"));
1156 _exit(-1);
1158 g_free (working_dir);
1160 /* Close parent's side pipes */
1161 close (stderr_pipe[1]);
1162 close (stdout_pipe[1]);
1164 if (child_pid < 0)
1166 g_warning ("launcher.c: Fork failed!");
1167 /* Close parent's side pipes */
1168 close (stderr_pipe[0]);
1169 close (stdout_pipe[0]);
1170 return child_pid;
1174 * Set pipes none blocking, so we can read big buffers
1175 * in the callback without having to use FIONREAD
1176 * to make sure the callback doesn't block.
1178 if ((md = fcntl (stdout_pipe[0], F_GETFL)) != -1)
1179 fcntl (stdout_pipe[0], F_SETFL, O_NONBLOCK | md);
1180 if ((md = fcntl (stderr_pipe[0], F_GETFL)) != -1)
1181 fcntl (stderr_pipe[0], F_SETFL, O_NONBLOCK | md);
1182 if ((md = fcntl (pty_master_fd, F_GETFL)) != -1)
1183 fcntl (pty_master_fd, F_SETFL, O_NONBLOCK | md);
1185 launcher->priv->child_pid = child_pid;
1186 launcher->priv->stderr_channel = g_io_channel_unix_new (stderr_pipe[0]);
1187 launcher->priv->stdout_channel = g_io_channel_unix_new (stdout_pipe[0]);
1188 launcher->priv->pty_channel = g_io_channel_unix_new (pty_master_fd);
1190 g_io_channel_set_buffer_size (launcher->priv->pty_channel, FILE_INPUT_BUFFER_SIZE);
1192 if (!launcher->priv->custom_encoding)
1193 g_get_charset ((const gchar**)&launcher->priv->encoding);
1194 anjuta_launcher_set_encoding_real (launcher, launcher->priv->encoding);
1196 tcgetattr(pty_master_fd, &termios_flags);
1197 termios_flags.c_iflag &= ~(IGNPAR | INPCK | INLCR | IGNCR | ICRNL | IXON |
1198 IXOFF | ISTRIP);
1199 termios_flags.c_iflag |= IGNBRK | BRKINT | IMAXBEL | IXANY;
1200 termios_flags.c_oflag &= ~OPOST;
1201 // termios_flags.c_oflag |= 0;
1202 termios_flags.c_cflag &= ~(CSTOPB | PARENB | HUPCL);
1203 termios_flags.c_cflag |= CS8 | CLOCAL;
1205 if (!launcher->priv->terminal_echo_on)
1207 termios_flags.c_lflag &= ~(ECHOKE | ECHOE | ECHO | ECHONL |
1208 #ifdef ECHOPRT
1209 ECHOPRT |
1210 #endif
1211 ECHOCTL | ISIG | ICANON | IEXTEN | NOFLSH | TOSTOP);
1213 // termios_flags.c_lflag |= 0;
1214 termios_flags.c_cc[VMIN] = 0;
1215 cfsetospeed(&termios_flags, __MAX_BAUD);
1216 tcsetattr(pty_master_fd, TCSANOW, &termios_flags);
1218 launcher->priv->stderr_watch =
1219 g_io_add_watch (launcher->priv->stderr_channel,
1220 G_IO_IN | G_IO_ERR | G_IO_HUP,
1221 (GIOFunc)anjuta_launcher_scan_error, launcher);
1222 launcher->priv->stdout_watch =
1223 g_io_add_watch (launcher->priv->stdout_channel,
1224 G_IO_IN | G_IO_ERR | G_IO_HUP,
1225 (GIOFunc)anjuta_launcher_scan_output, launcher);
1226 launcher->priv->pty_watch =
1227 g_io_add_watch (launcher->priv->pty_channel,
1228 G_IO_IN | G_IO_ERR, /* Do not hook up for G_IO_HUP */
1229 (GIOFunc)anjuta_launcher_scan_pty, launcher);
1231 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1232 launcher->priv->source = g_child_watch_add (launcher->priv->child_pid,
1233 anjuta_launcher_child_terminated, launcher);
1234 return child_pid;
1238 * anjuta_launcher_execute_v:
1239 * @launcher: a #AnjutaLancher object.
1240 * @argv: Command args.
1241 * @envp: Additional environment variable.
1242 * @callback: The callback for delivering output from the process.
1243 * @callback_data: Callback data for the above callback.
1245 * The first of the @args is the command itself. The rest are sent to the
1246 * as it's arguments. This function works similar to anjuta_launcher_execute().
1248 * Return value: TRUE if successfully launched, otherwise FALSE.
1250 gboolean
1251 anjuta_launcher_execute_v (AnjutaLauncher *launcher, gchar *const argv[],
1252 gchar *const envp[],
1253 AnjutaLauncherOutputCallback callback,
1254 gpointer callback_data)
1256 if (anjuta_launcher_is_busy (launcher))
1257 return FALSE;
1259 anjuta_launcher_set_busy (launcher, TRUE);
1261 launcher->priv->start_time = time (NULL);
1262 launcher->priv->child_status = 0;
1263 launcher->priv->stdout_is_done = FALSE;
1264 launcher->priv->stderr_is_done = FALSE;
1265 launcher->priv->child_has_terminated = FALSE;
1266 launcher->priv->in_cleanup = FALSE;
1267 launcher->priv->output_callback = callback;
1268 launcher->priv->callback_data = callback_data;
1270 /* On a fork error perform a cleanup and return */
1271 if (anjuta_launcher_fork (launcher, argv, envp) < 0)
1273 anjuta_launcher_initialize (launcher);
1274 return FALSE;
1276 return TRUE;
1280 * anjuta_launcher_execute:
1281 * @launcher: a #AnjutaLancher object.
1282 * @command_str: The command to execute.
1283 * @callback: The callback for delivering output from the process.
1284 * @callback_data: Callback data for the above callback.
1286 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1287 * delivered to the above callback. The data are delivered as they arrive
1288 * from the process and could be of any lenght. If the process asks for
1289 * passwords, the user will be automatically prompted with a dialog to enter
1290 * it. Please note that not all formats of the password are recognized. Those
1291 * with the standard 'assword:' substring in the prompt should work well.
1293 * Return value: TRUE if successfully launched, otherwise FALSE.
1295 gboolean
1296 anjuta_launcher_execute (AnjutaLauncher *launcher, const gchar *command_str,
1297 AnjutaLauncherOutputCallback callback,
1298 gpointer callback_data)
1300 GList *args_list, *args_list_ptr;
1301 gchar **args, **args_ptr;
1302 gboolean ret;
1304 /* Prepare command args */
1305 args_list = anjuta_util_parse_args_from_string (command_str);
1306 args = g_new (char*, g_list_length (args_list) + 1);
1307 args_list_ptr = args_list;
1308 args_ptr = args;
1309 while (args_list_ptr)
1311 *args_ptr = (char*) args_list_ptr->data;
1312 args_list_ptr = g_list_next (args_list_ptr);
1313 args_ptr++;
1315 *args_ptr = NULL;
1317 ret = anjuta_launcher_execute_v (launcher, args, NULL,
1318 callback, callback_data);
1319 g_free (args);
1320 anjuta_util_glist_strings_free (args_list);
1321 return ret;
1325 * anjuta_launcher_set_buffered_output:
1326 * @launcher: a #AnjutaLancher object.
1327 * @buffered: buffer output.
1329 * Sets if output should buffered or not. By default, it is buffered.
1331 * Return value: Previous flag value
1333 gboolean
1334 anjuta_launcher_set_buffered_output (AnjutaLauncher *launcher, gboolean buffered)
1336 gboolean past_value = launcher->priv->buffered_output;
1337 launcher->priv->buffered_output = buffered;
1338 return past_value;
1342 * anjuta_launcher_set_check_passwd_prompt:
1343 * @launcher: a #AnjutaLancher object.
1344 * @check_passwd: check for password.
1346 * Set if output is checked for a password prompti. A special dialog box
1347 * is use to enter it in this case. By default, this behavior is enabled.
1349 * Return value: Previous flag value
1351 gboolean
1352 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher *launcher, gboolean check_passwd)
1354 gboolean past_value = launcher->priv->check_for_passwd_prompt;
1355 launcher->priv->check_for_passwd_prompt = check_passwd;
1356 return past_value;
1360 * anjuta_launcher_set_terminal_echo:
1361 * @launcher: a #AnjutaLancher object.
1362 * @echo_on: Echo ON flag.
1364 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1365 * it is disabled.
1367 * Return value: Previous flag value
1369 gboolean
1370 anjuta_launcher_set_terminal_echo (AnjutaLauncher *launcher,
1371 gboolean echo_on)
1373 gboolean past_value = launcher->priv->terminal_echo_on;
1374 launcher->priv->terminal_echo_on = echo_on;
1375 return past_value;
1379 * anjuta_launcher_set_terminate_on_exit:
1380 * @launcher: a #AnjutaLancher object.
1381 * @terminate_on_exit: terminate on exit flag
1383 * When this flag is set, al i/o channels are closed and the child-exit
1384 * signal is emitted as soon as the child exit. By default, or when this
1385 * flag is clear, the launcher object wait until the i/o channels are
1386 * closed.
1388 * Return value: Previous flag value
1390 gboolean
1391 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher *launcher,
1392 gboolean terminate_on_exit)
1394 gboolean past_value = launcher->priv->terminate_on_exit;
1395 launcher->priv->terminate_on_exit = terminate_on_exit;
1396 return past_value;
1400 * anjuta_launcher_new:
1402 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1403 * it is disabled.
1405 * Return value: a new instance of #AnjutaLancher class.
1407 AnjutaLauncher*
1408 anjuta_launcher_new ()
1410 return g_object_new (ANJUTA_TYPE_LAUNCHER, NULL);