Rework check_input so that it can work with any widget that gives a string.
[anjuta-git-plugin.git] / libanjuta / anjuta-launcher.c
blobc463f2b1579f4dc87714bbd8254daa2b6e5177eb
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-utils.h"
59 #include "anjuta-marshal.h"
60 #include "resources.h"
61 #include "anjuta-launcher.h"
62 #include "anjuta-debug.h"
64 #define ANJUTA_PIXMAP_PASSWORD "password.png"
65 #define FILE_BUFFER_SIZE 1024
66 #define FILE_INPUT_BUFFER_SIZE 1048576
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 guint source;
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;
141 /* Encondig */
142 gboolean custom_encoding;
143 gchar* encoding;
145 /* Env */
146 GHashTable* env;
149 enum
151 /* OUTPUT_ARRIVED_SIGNAL, */
152 CHILD_EXITED_SIGNAL,
153 BUSY_SIGNAL,
154 LAST_SIGNAL
157 static void anjuta_launcher_class_init (AnjutaLauncherClass * klass);
158 static void anjuta_launcher_init (AnjutaLauncher * obj);
159 static gboolean anjuta_launcher_call_execution_done (gpointer data);
160 static gboolean anjuta_launcher_check_for_execution_done (gpointer data);
161 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
162 gboolean emit_signal);
164 static gboolean is_password_prompt(const gchar* line);
166 static guint launcher_signals[LAST_SIGNAL] = { 0 };
167 static AnjutaLauncherClass *parent_class;
169 static void
170 anjuta_launcher_initialize (AnjutaLauncher *obj)
172 /* Busy flag */
173 obj->priv->busy = FALSE;
175 /* These flags are used to synchronize the IO operations. */
176 obj->priv->stdout_is_done = FALSE;
177 obj->priv->stderr_is_done = FALSE;
179 /* GIO channels */
180 obj->priv->stdout_channel = NULL;
181 obj->priv->stderr_channel = NULL;
182 obj->priv->pty_channel = NULL;
184 /* Output line buffers */
185 obj->priv->stdout_buffer = NULL;
186 obj->priv->stderr_buffer = NULL;
188 /* Pty buffer */
189 obj->priv->pty_output_buffer = NULL;
191 obj->priv->terminal_echo_on = TRUE;
193 /* The child */
194 obj->priv->child_pid = 0;
195 obj->priv->child_status = -1;
196 obj->priv->child_has_terminated = TRUE;
197 obj->priv->source = 0;
199 /* Synchronization in progress */
200 obj->priv->in_cleanup = FALSE;
201 obj->priv->completion_check_timeout = -1;
203 /* Terminate child on child exit */
204 obj->priv->terminate_on_exit = FALSE;
206 /* Start time of execution */
207 obj->priv->start_time = 0;
209 obj->priv->buffered_output = TRUE;
210 obj->priv->check_for_passwd_prompt = TRUE;
212 /* Output callback */
213 obj->priv->output_callback = NULL;
214 obj->priv->callback_data = NULL;
216 /* Encoding */
217 obj->priv->custom_encoding = FALSE;
218 obj->priv->encoding = NULL;
220 /* Env */
221 obj->priv->env = g_hash_table_new_full (g_str_hash, g_str_equal,
222 g_free, g_free);
225 GType
226 anjuta_launcher_get_type ()
228 static GType obj_type = 0;
230 if (!obj_type)
232 static const GTypeInfo obj_info =
234 sizeof (AnjutaLauncherClass),
235 (GBaseInitFunc) NULL,
236 (GBaseFinalizeFunc) NULL,
237 (GClassInitFunc) anjuta_launcher_class_init,
238 (GClassFinalizeFunc) NULL,
239 NULL, /* class_data */
240 sizeof (AnjutaLauncher),
241 0, /* n_preallocs */
242 (GInstanceInitFunc) anjuta_launcher_init,
243 NULL /* value_table */
245 obj_type = g_type_register_static (G_TYPE_OBJECT,
246 "AnjutaLauncher", &obj_info, 0);
248 return obj_type;
251 static void
252 anjuta_launcher_dispose (GObject *obj)
254 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
255 if (anjuta_launcher_is_busy (launcher))
257 g_source_remove (launcher->priv->source);
258 launcher->priv->source = 0;
260 anjuta_launcher_execution_done_cleanup (launcher, FALSE);
262 launcher->priv->busy = FALSE;
265 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
268 static void
269 anjuta_launcher_finalize (GObject *obj)
271 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
272 if (launcher->priv->custom_encoding && launcher->priv->encoding)
273 g_free (launcher->priv->encoding);
275 g_hash_table_destroy (launcher->priv->env);
277 g_free (launcher->priv);
278 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
281 static void
282 anjuta_launcher_class_init (AnjutaLauncherClass * klass)
284 GObjectClass *object_class;
285 g_return_if_fail (klass != NULL);
286 object_class = (GObjectClass *) klass;
288 /* DEBUG_PRINT ("Initializing launcher class"); */
290 parent_class = g_type_class_peek_parent (klass);
293 * AnjutaLauncher::child-exited
294 * @launcher: a #AnjutaLancher object.
295 * @child_pid: process ID of the child
296 * @status: status as returned by waitpid function
297 * @time: time in seconds taken by the child
299 * Emitted when the child has exited and all i/o channels have
300 * been closed. If the terminate on exit flag is set, the i/o
301 * channels are automatically closed when the child exit.
302 * You need to use WEXITSTATUS and friend to get the child exit
303 * code from the status returned.
305 launcher_signals[CHILD_EXITED_SIGNAL] =
306 g_signal_new ("child-exited",
307 G_TYPE_FROM_CLASS (object_class),
308 G_SIGNAL_RUN_FIRST,
309 G_STRUCT_OFFSET (AnjutaLauncherClass,
310 child_exited),
311 NULL, NULL,
312 anjuta_cclosure_marshal_VOID__INT_INT_ULONG,
313 G_TYPE_NONE, 3, G_TYPE_INT,
314 G_TYPE_INT, G_TYPE_ULONG);
317 * AnjutaLauncher::busy
318 * @launcher: a #AnjutaLancher object.
319 * @busy: TRUE is a child is currently running
321 * Emitted when a child starts after a call to one execute function
322 * (busy is TRUE) or when a child exits and all i/o channels are
323 * closed (busy is FALSE).
325 launcher_signals[BUSY_SIGNAL] =
326 g_signal_new ("busy",
327 G_TYPE_FROM_CLASS (object_class),
328 G_SIGNAL_RUN_FIRST,
329 G_STRUCT_OFFSET (AnjutaLauncherClass,
330 busy),
331 NULL, NULL,
332 anjuta_cclosure_marshal_VOID__BOOLEAN,
333 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
335 object_class->dispose = anjuta_launcher_dispose;
336 object_class->finalize = anjuta_launcher_finalize;
339 static void
340 anjuta_launcher_init (AnjutaLauncher * obj)
342 g_return_if_fail (obj != NULL);
343 obj->priv = g_new0 (AnjutaLauncherPriv, 1);
344 anjuta_launcher_initialize (obj);
348 * anjuta_launcher_is_busy:
349 * @launcher: a #AnjutaLancher object.
351 * Tells if the laucher is currently executing any command.
353 * Return value: TRUE if launcher is busy, otherwisee FALSE.
355 gboolean
356 anjuta_launcher_is_busy (AnjutaLauncher *launcher)
358 return launcher->priv->busy;
361 static void
362 anjuta_launcher_set_busy (AnjutaLauncher *launcher, gboolean flag)
364 gboolean old_busy = launcher->priv->busy;
365 launcher->priv->busy = flag;
366 if (old_busy != flag)
367 g_signal_emit_by_name (G_OBJECT (launcher), "busy", flag);
371 * anjuta_launcher_send_stdin:
372 * @launcher: a #AnjutaLancher object.
373 * @input_str: The string to send to STDIN of the process.
375 * Sends a string to Standard input of the process currently being executed.
377 void
378 anjuta_launcher_send_stdin (AnjutaLauncher *launcher, const gchar * input_str)
380 g_return_if_fail (launcher);
381 g_return_if_fail (input_str);
383 anjuta_launcher_send_ptyin (launcher, input_str);
387 * anjuta_launcher_send_stdin:
388 * @launcher: a #AnjutaLancher object.
390 * Sends a EOF to Standard input of the process currently being executed.
393 void
394 anjuta_launcher_send_stdin_eof (AnjutaLauncher *launcher)
396 GError* err = NULL;
397 g_io_channel_shutdown (launcher->priv->pty_channel, TRUE,
398 &err);
399 g_io_channel_unref (launcher->priv->pty_channel);
400 launcher->priv->pty_channel = NULL;
402 if (err)
404 g_warning ("g_io_channel_shutdown () failed: %s", err->message);
409 * anjuta_launcher_send_ptyin:
410 * @launcher: a #AnjutaLancher object.
411 * @input_str: The string to send to PTY of the process.
413 * Sends a string to TTY input of the process currently being executed.
414 * Mostly useful for entering passwords and other inputs which are directly
415 * read from TTY input of the process.
417 void
418 anjuta_launcher_send_ptyin (AnjutaLauncher *launcher, const gchar * input_str)
420 gsize bytes_written;
421 GError *err = NULL;
423 if (!input_str || strlen (input_str) == 0) return;
427 g_io_channel_write_chars (launcher->priv->pty_channel,
428 input_str, strlen (input_str),
429 &bytes_written, &err);
430 g_io_channel_flush (launcher->priv->pty_channel, NULL);
431 if (err)
433 g_warning ("Error encountered while writing to PTY!. %s",
434 err->message);
435 g_error_free (err);
437 return;
439 input_str += bytes_written;
441 while (*input_str);
445 * anjuta_launcher_reset:
446 * @launcher: a #AnjutaLancher object.
448 * Resets the launcher and kills (SIGTERM) current process, if it is still
449 * executing.
451 void
452 anjuta_launcher_reset (AnjutaLauncher *launcher)
454 if (anjuta_launcher_is_busy (launcher))
455 kill (launcher->priv->child_pid, SIGTERM);
459 * anjuta_launcher_signal:
460 * @launcher: a #AnjutaLancher object.
461 * @sig: kernel signal ID (e.g. SIGTERM).
463 * Sends a kernel signal to the process that is being executed.
465 void
466 anjuta_launcher_signal (AnjutaLauncher *launcher, int sig)
468 kill (launcher->priv->child_pid, sig);
472 * anjuta_launcher_get_child_pid:
473 * @launcher: a #AnjutaLancher object.
475 * Gets the Process ID of the child being executed.
477 * Return value: Process ID of the child.
479 pid_t
480 anjuta_launcher_get_child_pid (AnjutaLauncher *launcher)
482 if (anjuta_launcher_is_busy (launcher))
483 return launcher->priv->child_pid;
484 else
485 return -1;
488 static void
489 anjuta_launcher_synchronize (AnjutaLauncher *launcher)
491 if (launcher->priv->in_cleanup) return;
493 if (launcher->priv->child_has_terminated &&
494 launcher->priv->stdout_is_done &&
495 launcher->priv->stderr_is_done)
497 if (launcher->priv->completion_check_timeout >= 0)
498 g_source_remove (launcher->priv->completion_check_timeout);
499 launcher->priv->completion_check_timeout =
500 g_timeout_add (50, anjuta_launcher_check_for_execution_done,
501 launcher);
504 /* This case is not very good, but it blocks the whole IDE
505 because we never new if the child has finished */
506 else if (launcher->priv->stdout_is_done &&
507 launcher->priv->stderr_is_done)
509 /* DEBUG_PRINT ("Child has't exited yet waiting for 200ms"); */
510 if (launcher->priv->completion_check_timeout >= 0)
511 g_source_remove (launcher->priv->completion_check_timeout);
512 launcher->priv->completion_check_timeout =
513 g_timeout_add(200, anjuta_launcher_check_for_execution_done,
514 launcher);
516 /* Add this case for gdb. It creates child inheriting gdb
517 * pipes which are not closed if gdb crashes */
518 else if (launcher->priv->child_has_terminated &&
519 launcher->priv->terminate_on_exit)
521 if (launcher->priv->completion_check_timeout >= 0)
522 g_source_remove (launcher->priv->completion_check_timeout);
523 launcher->priv->completion_check_timeout =
524 g_timeout_add(0, anjuta_launcher_call_execution_done,
525 launcher);
529 /* Password dialog */
530 static GtkWidget*
531 create_password_dialog (const gchar* prompt)
533 GtkWidget *dialog;
534 GtkWidget *hbox;
535 GtkWidget *box;
536 GtkWidget *icon;
537 GtkWidget *label;
538 GtkWidget *entry;
540 g_return_val_if_fail (prompt, NULL);
542 dialog = gtk_dialog_new_with_buttons (prompt,
543 NULL, //FIXME: Pass the parent window here
544 // for transient purpose.
545 GTK_DIALOG_DESTROY_WITH_PARENT,
546 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
547 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
548 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
550 gtk_window_set_wmclass (GTK_WINDOW (dialog), "launcher-password-prompt",
551 "anjuta");
552 hbox = gtk_hbox_new (FALSE, 10);
553 gtk_widget_show (hbox);
554 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
556 icon = anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD);
557 gtk_widget_show (icon);
558 gtk_box_pack_start_defaults (GTK_BOX(hbox), icon);
560 if (strlen (prompt) < 20) {
561 box = gtk_hbox_new (FALSE, 5);
562 } else {
563 box = gtk_vbox_new (FALSE, 5);
565 gtk_widget_show (box);
566 gtk_box_pack_start_defaults (GTK_BOX (hbox), box);
568 label = gtk_label_new (_(prompt));
569 gtk_widget_show (label);
570 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
572 entry = gtk_entry_new ();
573 gtk_widget_show (entry);
574 gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
575 gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
577 gtk_widget_ref (entry);
578 g_object_set_data_full (G_OBJECT (dialog), "password_entry",
579 gtk_widget_ref (entry),
580 (GDestroyNotify) gtk_widget_unref);
581 gtk_widget_grab_focus (entry);
582 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
584 return dialog;
587 /* pty buffer check for password authentication */
588 static void
589 anjuta_launcher_check_password_real (AnjutaLauncher *launcher,
590 const gchar* last_line)
592 if (anjuta_launcher_is_busy (launcher) == FALSE)
593 return;
595 if (last_line) {
597 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
598 if (is_password_prompt(last_line)) {
599 /* Password prompt detected */
600 GtkWidget* dialog;
601 gint button;
602 const gchar* passwd;
603 gchar* line;
605 dialog = create_password_dialog (last_line);
606 button = gtk_dialog_run (GTK_DIALOG(dialog));
607 switch (button) {
608 case GTK_RESPONSE_OK:
609 passwd = gtk_entry_get_text (
610 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog),
611 "password_entry")));
612 line = g_strconcat (passwd, "\n", NULL);
613 anjuta_launcher_send_ptyin (launcher, line);
614 g_free (line);
615 break;
616 case GTK_RESPONSE_CANCEL:
617 anjuta_launcher_send_ptyin (launcher, "<canceled>\n");
618 anjuta_launcher_reset (launcher);
619 break;
620 default:
621 break;
623 gtk_widget_destroy (dialog);
628 static void
629 anjuta_launcher_check_password (AnjutaLauncher *launcher, const gchar *chars)
631 glong start, end;
632 gchar *last_line;
634 if (!chars || strlen(chars) <= 0)
635 return;
637 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
638 start = end = strlen (chars);
639 while (start > 0 && chars[start-1] != '\n') start--;
641 if (end > start)
643 last_line = g_strndup (&chars[start], end - start + 1);
645 /* DEBUG_PRINT ("Last line = %s", last_line); */
646 /* Checks for password, again */
647 anjuta_launcher_check_password_real (launcher, last_line);
648 g_free (last_line);
652 static gboolean
653 is_password_prompt (const gchar* line)
655 const gchar* password = "assword";
656 const gchar* passphrase = "assphrase";
658 if (strlen (line) < strlen (password)
659 || strlen (line) < strlen (passphrase))
660 return FALSE;
662 if (g_strstr_len(line, 80, password) != NULL
663 || g_strstr_len(line, 80, passphrase) != NULL)
665 int i;
666 for (i = strlen(line) - 1; i != 0; --i)
668 if (line[i] == ':')
669 return TRUE;
670 if (g_ascii_isspace(line[i]))
671 continue;
672 else
673 return FALSE;
676 return FALSE;
679 static void
680 anjuta_launcher_buffered_output (AnjutaLauncher *launcher,
681 AnjutaLauncherOutputType output_type,
682 const gchar *chars)
684 gchar *all_lines;
685 gchar *incomplete_line;
686 gchar **buffer;
688 g_return_if_fail (chars != NULL);
689 g_return_if_fail (strlen (chars) > 0);
691 if (launcher->priv->output_callback == NULL)
692 return;
693 if (launcher->priv->buffered_output == FALSE)
695 (launcher->priv->output_callback)(launcher, output_type, chars,
696 launcher->priv->callback_data);
697 return;
699 switch (output_type)
701 case ANJUTA_LAUNCHER_OUTPUT_STDOUT:
702 buffer = &launcher->priv->stdout_buffer;
703 break;
704 case ANJUTA_LAUNCHER_OUTPUT_STDERR:
705 buffer = &launcher->priv->stderr_buffer;
706 break;
707 default:
708 g_warning ("Should not reach here");
709 return;
711 if (*buffer)
712 all_lines = g_strconcat (*buffer, chars, NULL);
713 else
714 all_lines = g_strdup (chars);
716 /* Buffer the last incomplete line */
717 incomplete_line = all_lines + strlen (all_lines);
718 while (incomplete_line > all_lines &&
719 *incomplete_line != '\n')
721 incomplete_line = g_utf8_prev_char (incomplete_line);
723 if (*incomplete_line == '\n')
724 incomplete_line++;
726 /* Update line buffer */
727 g_free(*buffer);
728 *buffer = NULL;
729 if (strlen(incomplete_line))
731 *buffer = g_strdup (incomplete_line);
732 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
734 /* Check for password prompt */
735 if (launcher->priv->check_for_passwd_prompt)
736 anjuta_launcher_check_password (launcher, incomplete_line);
738 /* Deliver complete lines */
739 *incomplete_line = '\0';
740 if (strlen (all_lines) > 0)
741 (launcher->priv->output_callback)(launcher, output_type, all_lines,
742 launcher->priv->callback_data);
743 g_free (all_lines);
746 static gboolean
747 anjuta_launcher_scan_output (GIOChannel *channel, GIOCondition condition,
748 AnjutaLauncher *launcher)
750 gsize n;
751 gchar buffer[FILE_BUFFER_SIZE];
752 gboolean ret = TRUE;
754 if (condition & G_IO_IN)
756 GError *err = NULL;
759 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
760 if (n > 0) /* There is output */
762 gchar *utf8_chars = NULL;
763 buffer[n] = '\0';
764 if (!launcher->priv->custom_encoding)
765 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
766 else
767 utf8_chars = g_strdup(buffer);
768 anjuta_launcher_buffered_output (launcher,
769 ANJUTA_LAUNCHER_OUTPUT_STDOUT,
770 utf8_chars);
771 g_free (utf8_chars);
773 /* Ignore illegal characters */
774 if (err && err->domain == G_CONVERT_ERROR)
776 g_error_free (err);
777 err = NULL;
779 /* The pipe is closed on the other side */
780 /* if not related to non blocking read or interrupted syscall */
781 else if (err && errno != EAGAIN && errno != EINTR)
783 launcher->priv->stdout_is_done = TRUE;
784 anjuta_launcher_synchronize (launcher);
785 ret = FALSE;
787 /* Read next chars if buffer was too small
788 * (the maximum length of one character is 6 bytes) */
789 } while (!err && (n > FILE_BUFFER_SIZE - 7));
790 if (err)
791 g_error_free (err);
793 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
795 DEBUG_PRINT ("launcher.c: STDOUT pipe closed");
796 launcher->priv->stdout_is_done = TRUE;
797 anjuta_launcher_synchronize (launcher);
798 ret = FALSE;
800 return ret;
803 static gboolean
804 anjuta_launcher_scan_error (GIOChannel *channel, GIOCondition condition,
805 AnjutaLauncher *launcher)
807 gsize n;
808 gchar buffer[FILE_BUFFER_SIZE];
809 gboolean ret = TRUE;
811 if (condition & G_IO_IN)
813 GError *err = NULL;
816 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
817 if (n > 0) /* There is stderr output */
819 gchar *utf8_chars;
820 buffer[n] = '\0';
821 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
822 anjuta_launcher_buffered_output (launcher,
823 ANJUTA_LAUNCHER_OUTPUT_STDERR,
824 utf8_chars);
825 g_free (utf8_chars);
827 /* Ignore illegal characters */
828 if (err && err->domain == G_CONVERT_ERROR)
830 g_error_free (err);
831 err = NULL;
833 /* The pipe is closed on the other side */
834 /* if not related to non blocking read or interrupted syscall */
835 else if (err && errno != EAGAIN && errno != EINTR)
838 launcher->priv->stderr_is_done = TRUE;
839 anjuta_launcher_synchronize (launcher);
840 ret = FALSE;
842 /* Read next chars if buffer was too small
843 * (the maximum length of one character is 6 bytes) */
844 } while (!err && (n > FILE_BUFFER_SIZE - 7));
845 if (err)
846 g_error_free (err);
848 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
850 DEBUG_PRINT ("launcher.c: STDERR pipe closed");
851 launcher->priv->stderr_is_done = TRUE;
852 anjuta_launcher_synchronize (launcher);
853 ret = FALSE;
855 return ret;
858 static gboolean
859 anjuta_launcher_scan_pty (GIOChannel *channel, GIOCondition condition,
860 AnjutaLauncher *launcher)
862 gsize n;
863 gchar buffer[FILE_BUFFER_SIZE];
864 gboolean ret = TRUE;
866 if (condition & G_IO_IN)
868 GError *err = NULL;
871 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
872 if (n > 0) /* There is stderr output */
874 gchar *utf8_chars;
875 gchar *old_str = launcher->priv->pty_output_buffer;
876 buffer[n] = '\0';
877 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
878 if (old_str)
880 gchar *str = g_strconcat (old_str, utf8_chars, NULL);
881 launcher->priv->pty_output_buffer = str;
882 g_free (old_str);
884 else
885 launcher->priv->pty_output_buffer = g_strdup (utf8_chars);
886 g_free (utf8_chars);
888 /* Ignore illegal characters */
889 if (err && err->domain == G_CONVERT_ERROR)
891 g_error_free (err);
892 err = NULL;
894 /* The pipe is closed on the other side */
895 /* if not related to non blocking read or interrupted syscall */
896 else if (err && errno != EAGAIN && errno != EINTR)
898 ret = FALSE;
900 /* Read next chars if buffer was too small
901 * (the maximum length of one character is 6 bytes) */
902 } while (!err && (n > FILE_BUFFER_SIZE - 7));
903 if (err)
904 g_error_free (err);
905 if (launcher->priv->check_for_passwd_prompt
906 && launcher->priv->pty_output_buffer
907 && strlen (launcher->priv->pty_output_buffer) > 0)
909 anjuta_launcher_check_password (launcher,
910 launcher->priv->pty_output_buffer);
913 /* In pty case, we handle the cases in different invocations */
914 /* Do not hook up for G_IO_HUP */
915 if (condition & G_IO_ERR)
917 DEBUG_PRINT ("launcher.c: PTY pipe error!");
918 ret = FALSE;
920 return ret;
923 static void
924 anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
925 gboolean emit_signal)
927 gint child_status, child_pid;
928 time_t start_time;
930 if (launcher->priv->in_cleanup)
931 return;
933 launcher->priv->in_cleanup = TRUE;
935 /* Remove pending timeout */
936 if (launcher->priv->completion_check_timeout >= 0)
937 g_source_remove (launcher->priv->completion_check_timeout);
939 /* Make sure all pending I/O are flushed out */
940 while (g_main_context_pending (NULL))
941 g_main_context_iteration (NULL, FALSE);
943 /* Can be called again, while waiting in the previous line
944 * Do nothing if clean up is already done */
945 if (launcher->priv->stdout_channel)
947 g_io_channel_shutdown (launcher->priv->stdout_channel, emit_signal, NULL);
948 g_io_channel_unref (launcher->priv->stdout_channel);
949 g_source_remove (launcher->priv->stdout_watch);
952 if (launcher->priv->stderr_channel)
954 g_io_channel_shutdown (launcher->priv->stderr_channel, emit_signal, NULL);
955 g_io_channel_unref (launcher->priv->stderr_channel);
956 g_source_remove (launcher->priv->stderr_watch);
959 if (launcher->priv->pty_channel)
961 g_io_channel_shutdown (launcher->priv->pty_channel, emit_signal, NULL);
962 g_io_channel_unref (launcher->priv->pty_channel);
964 g_source_remove (launcher->priv->pty_watch);
967 if (launcher->priv->pty_output_buffer)
968 g_free (launcher->priv->pty_output_buffer);
969 if (launcher->priv->stdout_buffer)
970 g_free (launcher->priv->stdout_buffer);
971 if (launcher->priv->stderr_buffer)
972 g_free (launcher->priv->stdout_buffer);
974 /* Save them before we re-initialize */
975 child_status = launcher->priv->child_status;
976 child_pid = launcher->priv->child_pid;
977 start_time = launcher->priv->start_time;
979 if (emit_signal)
980 anjuta_launcher_set_busy (launcher, FALSE);
982 anjuta_launcher_initialize (launcher);
985 /* Call this here, after set_busy (FALSE) so we are able to
986 launch a new child from the terminate function.
987 (by clubfan 2002-04-07)
989 /* DEBUG_PRINT ("Exit status: %d", child_status); */
990 if (emit_signal)
991 g_signal_emit_by_name (launcher, "child-exited", child_pid,
992 child_status,
993 time (NULL) - start_time);
996 /* Using this function is necessary because
997 * anjuta_launcher_execution_done_cleanup needs to be called in the same
998 * thread than the gtk main loop */
999 static gboolean
1000 anjuta_launcher_call_execution_done (gpointer data)
1002 AnjutaLauncher *launcher = data;
1004 launcher->priv->completion_check_timeout = -1;
1005 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
1006 return FALSE;
1009 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
1010 static gboolean
1011 anjuta_launcher_check_for_execution_done (gpointer data)
1013 AnjutaLauncher *launcher = data;
1015 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
1016 launcher->priv->stdout_is_done ? 1 : 0,
1017 launcher->priv->stderr_is_done ? 1 : 0);
1019 if (launcher->priv->stdout_is_done == FALSE ||
1020 launcher->priv->stderr_is_done == FALSE)
1021 return TRUE;
1022 if (launcher->priv->child_has_terminated == FALSE)
1024 /* DEBUG_PRINT ("launcher: We missed the exit of the child"); */
1026 launcher->priv->completion_check_timeout = -1;
1027 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
1028 return FALSE;
1031 static void
1032 anjuta_launcher_child_terminated (GPid pid, gint status, gpointer data)
1034 AnjutaLauncher *launcher = data;
1036 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher));
1038 /* Save child exit code */
1039 launcher->priv->child_status = status;
1040 launcher->priv->child_has_terminated = TRUE;
1041 anjuta_launcher_synchronize (launcher);
1045 static gboolean
1046 anjuta_launcher_set_encoding_real (AnjutaLauncher *launcher, const gchar *charset)
1048 GIOStatus s;
1049 gboolean r = TRUE;
1051 g_return_val_if_fail (launcher != NULL, FALSE);
1052 // charset can be NULL
1054 s = g_io_channel_set_encoding (launcher->priv->stderr_channel, charset, NULL);
1055 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1056 s = g_io_channel_set_encoding (launcher->priv->stdout_channel, charset, NULL);
1057 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1058 s = g_io_channel_set_encoding (launcher->priv->pty_channel, charset, NULL);
1059 if (s != G_IO_STATUS_NORMAL) r = FALSE;
1061 if (! r)
1063 g_warning ("launcher.c: Failed to set channel encoding!");
1065 return r;
1070 * anjuta_launcher_set_encoding:
1071 * @launcher: a #AnjutaLancher object.
1072 * @charset: Character set to use for Input/Output with the process.
1074 * Sets the character set to use for Input/Output with the process.
1077 void
1078 anjuta_launcher_set_encoding (AnjutaLauncher *launcher, const gchar *charset)
1080 if (launcher->priv->custom_encoding)
1081 g_free (launcher->priv->encoding);
1083 launcher->priv->custom_encoding = TRUE;
1084 if (charset)
1085 launcher->priv->encoding = g_strdup(charset);
1086 else
1087 launcher->priv->encoding = NULL;
1091 * anjuta_launcher_set_env:
1092 * @launcher: a #AnjutaLancher object.
1093 * @name: Name of the environment variable to set
1094 * @value: Value of the environment variable to set
1096 * Set an environment variable for the forked process
1099 void
1100 anjuta_launcher_set_env (AnjutaLauncher *launcher,
1101 const gchar *name,
1102 const gchar *value)
1104 g_return_if_fail (launcher && ANJUTA_IS_LAUNCHER(launcher));
1105 g_return_if_fail (name != NULL);
1106 g_return_if_fail (value != NULL);
1108 g_hash_table_insert (launcher->priv->env,
1109 g_strdup(name),
1110 g_strdup(value));
1113 static void
1114 anjuta_launcher_fork_setenv (const gchar* name, const gchar* value)
1116 setenv (name, value, TRUE);
1119 static pid_t
1120 anjuta_launcher_fork (AnjutaLauncher *launcher, gchar *const args[])
1122 char *working_dir;
1123 int pty_master_fd, md;
1124 int stdout_pipe[2], stderr_pipe[2];
1125 pid_t child_pid;
1126 struct termios termios_flags;
1128 working_dir = g_get_current_dir ();
1130 /* The pipes */
1131 pipe (stderr_pipe);
1132 pipe (stdout_pipe);
1134 /* Fork the command */
1135 child_pid = forkpty (&pty_master_fd, NULL, NULL, NULL);
1136 if (child_pid == 0)
1138 close (2);
1139 dup (stderr_pipe[1]);
1140 close (1);
1141 dup (stdout_pipe[1]);
1143 /* Close unnecessary pipes */
1144 close (stderr_pipe[0]);
1145 close (stdout_pipe[0]);
1148 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1149 perror ("Could not set new controlling tty");
1151 /* Set no delays for the write pipes (non_buffered) so
1152 that we get all the outputs immidiately */
1153 if ((md = fcntl (stdout_pipe[1], F_GETFL)) != -1)
1154 fcntl (stdout_pipe[1], F_SETFL, O_SYNC | md);
1155 if ((md = fcntl (stderr_pipe[1], F_GETFL)) != -1)
1156 fcntl (stderr_pipe[1], F_SETFL, O_SYNC | md);
1158 /* Set up environment */
1159 g_hash_table_foreach (launcher->priv->env,
1160 (GHFunc) anjuta_launcher_fork_setenv,
1161 NULL);
1163 execvp (args[0], args);
1164 g_warning (_("Cannot execute command: \"%s\""), args[0]);
1165 perror(_("execvp failed"));
1166 _exit(-1);
1168 g_free (working_dir);
1170 /* Close parent's side pipes */
1171 close (stderr_pipe[1]);
1172 close (stdout_pipe[1]);
1174 if (child_pid < 0)
1176 g_warning ("launcher.c: Fork failed!");
1177 /* Close parent's side pipes */
1178 close (stderr_pipe[0]);
1179 close (stdout_pipe[0]);
1180 return child_pid;
1184 * Set pipes none blocking, so we can read big buffers
1185 * in the callback without having to use FIONREAD
1186 * to make sure the callback doesn't block.
1188 if ((md = fcntl (stdout_pipe[0], F_GETFL)) != -1)
1189 fcntl (stdout_pipe[0], F_SETFL, O_NONBLOCK | md);
1190 if ((md = fcntl (stderr_pipe[0], F_GETFL)) != -1)
1191 fcntl (stderr_pipe[0], F_SETFL, O_NONBLOCK | md);
1192 if ((md = fcntl (pty_master_fd, F_GETFL)) != -1)
1193 fcntl (pty_master_fd, F_SETFL, O_NONBLOCK | md);
1195 launcher->priv->child_pid = child_pid;
1196 launcher->priv->stderr_channel = g_io_channel_unix_new (stderr_pipe[0]);
1197 launcher->priv->stdout_channel = g_io_channel_unix_new (stdout_pipe[0]);
1198 launcher->priv->pty_channel = g_io_channel_unix_new (pty_master_fd);
1200 g_io_channel_set_buffer_size (launcher->priv->pty_channel, FILE_INPUT_BUFFER_SIZE);
1202 if (!launcher->priv->custom_encoding)
1203 g_get_charset ((const gchar**)&launcher->priv->encoding);
1204 anjuta_launcher_set_encoding_real (launcher, launcher->priv->encoding);
1206 tcgetattr(pty_master_fd, &termios_flags);
1207 termios_flags.c_iflag &= ~(IGNPAR | INPCK | INLCR | IGNCR | ICRNL | IXON |
1208 IXOFF | ISTRIP);
1209 termios_flags.c_iflag |= IGNBRK | BRKINT | IMAXBEL | IXANY;
1210 termios_flags.c_oflag &= ~OPOST;
1211 // termios_flags.c_oflag |= 0;
1212 termios_flags.c_cflag &= ~(CSTOPB | CREAD | PARENB | HUPCL);
1213 termios_flags.c_cflag |= CS8 | CLOCAL;
1215 if (!launcher->priv->terminal_echo_on)
1217 termios_flags.c_lflag &= ~(ECHOKE | ECHOE | ECHO | ECHONL |
1218 #ifdef ECHOPRT
1219 ECHOPRT |
1220 #endif
1221 ECHOCTL | ISIG | ICANON | IEXTEN | NOFLSH | TOSTOP);
1223 // termios_flags.c_lflag |= 0;
1224 termios_flags.c_cc[VMIN] = 0;
1225 cfsetospeed(&termios_flags, __MAX_BAUD);
1226 tcsetattr(pty_master_fd, TCSANOW, &termios_flags);
1228 launcher->priv->stderr_watch =
1229 g_io_add_watch (launcher->priv->stderr_channel,
1230 G_IO_IN | G_IO_ERR | G_IO_HUP,
1231 (GIOFunc)anjuta_launcher_scan_error, launcher);
1232 launcher->priv->stdout_watch =
1233 g_io_add_watch (launcher->priv->stdout_channel,
1234 G_IO_IN | G_IO_ERR | G_IO_HUP,
1235 (GIOFunc)anjuta_launcher_scan_output, launcher);
1236 launcher->priv->pty_watch =
1237 g_io_add_watch (launcher->priv->pty_channel,
1238 G_IO_IN | G_IO_ERR, /* Do not hook up for G_IO_HUP */
1239 (GIOFunc)anjuta_launcher_scan_pty, launcher);
1241 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1242 launcher->priv->source = g_child_watch_add (launcher->priv->child_pid,
1243 anjuta_launcher_child_terminated, launcher);
1244 return child_pid;
1248 * anjuta_launcher_execute_v:
1249 * @launcher: a #AnjutaLancher object.
1250 * @argv: Command args.
1251 * @callback: The callback for delivering output from the process.
1252 * @callback_data: Callback data for the above callback.
1254 * The first of the @args is the command itself. The rest are sent to the
1255 * as it's arguments. This function works similar to anjuta_launcher_execute().
1257 * Return value: TRUE if successfully launched, otherwise FALSE.
1259 gboolean
1260 anjuta_launcher_execute_v (AnjutaLauncher *launcher, gchar *const argv[],
1261 AnjutaLauncherOutputCallback callback,
1262 gpointer callback_data)
1264 if (anjuta_launcher_is_busy (launcher))
1265 return FALSE;
1267 anjuta_launcher_set_busy (launcher, TRUE);
1269 launcher->priv->start_time = time (NULL);
1270 launcher->priv->child_status = 0;
1271 launcher->priv->stdout_is_done = FALSE;
1272 launcher->priv->stderr_is_done = FALSE;
1273 launcher->priv->child_has_terminated = FALSE;
1274 launcher->priv->in_cleanup = FALSE;
1275 launcher->priv->output_callback = callback;
1276 launcher->priv->callback_data = callback_data;
1278 /* On a fork error perform a cleanup and return */
1279 if (anjuta_launcher_fork (launcher, argv) < 0)
1281 anjuta_launcher_initialize (launcher);
1282 return FALSE;
1284 return TRUE;
1288 * anjuta_launcher_execute:
1289 * @launcher: a #AnjutaLancher object.
1290 * @command_str: The command to execute.
1291 * @callback: The callback for delivering output from the process.
1292 * @callback_data: Callback data for the above callback.
1294 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1295 * delivered to the above callback. The data are delivered as they arrive
1296 * from the process and could be of any lenght. If the process asks for
1297 * passwords, the user will be automatically prompted with a dialog to enter
1298 * it. Please note that not all formats of the password are recognized. Those
1299 * with the standard 'assword:' substring in the prompt should work well.
1301 * Return value: TRUE if successfully launched, otherwise FALSE.
1303 gboolean
1304 anjuta_launcher_execute (AnjutaLauncher *launcher, const gchar *command_str,
1305 AnjutaLauncherOutputCallback callback,
1306 gpointer callback_data)
1308 GList *args_list, *args_list_ptr;
1309 gchar **args, **args_ptr;
1310 gboolean ret;
1312 /* Prepare command args */
1313 args_list = anjuta_util_parse_args_from_string (command_str);
1314 args = g_new (char*, g_list_length (args_list) + 1);
1315 args_list_ptr = args_list;
1316 args_ptr = args;
1317 while (args_list_ptr)
1319 *args_ptr = (char*) args_list_ptr->data;
1320 args_list_ptr = g_list_next (args_list_ptr);
1321 args_ptr++;
1323 *args_ptr = NULL;
1325 ret = anjuta_launcher_execute_v (launcher, args,
1326 callback, callback_data);
1327 g_free (args);
1328 anjuta_util_glist_strings_free (args_list);
1329 return ret;
1333 * anjuta_launcher_set_buffered_output:
1334 * @launcher: a #AnjutaLancher object.
1335 * @buffered: buffer output.
1337 * Sets if output should buffered or not. By default, it is buffered.
1339 * Return value: Previous flag value
1341 gboolean
1342 anjuta_launcher_set_buffered_output (AnjutaLauncher *launcher, gboolean buffered)
1344 gboolean past_value = launcher->priv->buffered_output;
1345 launcher->priv->buffered_output = buffered;
1346 return past_value;
1350 * anjuta_launcher_set_check_passwd_prompt:
1351 * @launcher: a #AnjutaLancher object.
1352 * @check_passwd: check for password.
1354 * Set if output is checked for a password prompti. A special dialog box
1355 * is use to enter it in this case. By default, this behavior is enabled.
1357 * Return value: Previous flag value
1359 gboolean
1360 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher *launcher, gboolean check_passwd)
1362 gboolean past_value = launcher->priv->check_for_passwd_prompt;
1363 launcher->priv->check_for_passwd_prompt = check_passwd;
1364 return past_value;
1368 * anjuta_launcher_set_terminal_echo:
1369 * @launcher: a #AnjutaLancher object.
1370 * @echo_on: Echo ON flag.
1372 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1373 * it is disabled.
1375 * Return value: Previous flag value
1377 gboolean
1378 anjuta_launcher_set_terminal_echo (AnjutaLauncher *launcher,
1379 gboolean echo_on)
1381 gboolean past_value = launcher->priv->terminal_echo_on;
1382 launcher->priv->terminal_echo_on = echo_on;
1383 return past_value;
1387 * anjuta_launcher_set_terminate_on_exit:
1388 * @launcher: a #AnjutaLancher object.
1389 * @terminate_on_exit: terminate on exit flag
1391 * When this flag is set, al i/o channels are closed and the child-exit
1392 * signal is emitted as soon as the child exit. By default, or when this
1393 * flag is clear, the launcher object wait until the i/o channels are
1394 * closed.
1396 * Return value: Previous flag value
1398 gboolean
1399 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher *launcher,
1400 gboolean terminate_on_exit)
1402 gboolean past_value = launcher->priv->terminate_on_exit;
1403 launcher->priv->terminate_on_exit = terminate_on_exit;
1404 return past_value;
1408 * anjuta_launcher_new:
1410 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1411 * it is disabled.
1413 * Return value: a new instance of #AnjutaLancher class.
1415 AnjutaLauncher*
1416 anjuta_launcher_new ()
1418 return g_object_new (ANJUTA_TYPE_LAUNCHER, NULL);