Updated Spanish translation
[anjuta-git-plugin.git] / libanjuta / anjuta-launcher.c
blob04ab8ebde1248932282452cf05c82b52eb62d846
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 /* Check for passwords in input */
114 gboolean disable_password_check;
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;
145 enum
147 /* OUTPUT_ARRIVED_SIGNAL, */
148 CHILD_EXITED_SIGNAL,
149 BUSY_SIGNAL,
150 LAST_SIGNAL
153 static void anjuta_launcher_class_init (AnjutaLauncherClass * klass);
154 static void anjuta_launcher_init (AnjutaLauncher * obj);
155 static gboolean anjuta_launcher_call_execution_done (gpointer data);
156 static gboolean anjuta_launcher_check_for_execution_done (gpointer data);
157 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
158 gboolean emit_signal);
160 static gboolean is_password_prompt(const gchar* line);
162 static guint launcher_signals[LAST_SIGNAL] = { 0 };
163 static AnjutaLauncherClass *parent_class;
165 static void
166 anjuta_launcher_initialize (AnjutaLauncher *obj)
168 /* Busy flag */
169 obj->priv->busy = FALSE;
171 /* These flags are used to synchronize the IO operations. */
172 obj->priv->stdout_is_done = FALSE;
173 obj->priv->stderr_is_done = FALSE;
175 /* GIO channels */
176 obj->priv->stdout_channel = NULL;
177 obj->priv->stderr_channel = NULL;
178 obj->priv->pty_channel = NULL;
180 /* Output line buffers */
181 obj->priv->stdout_buffer = NULL;
182 obj->priv->stderr_buffer = NULL;
184 /* Pty buffer */
185 obj->priv->pty_output_buffer = NULL;
187 obj->priv->terminal_echo_on = TRUE;
188 obj->priv->disable_password_check = FALSE;
190 /* The child */
191 obj->priv->child_pid = 0;
192 obj->priv->child_status = -1;
193 obj->priv->child_has_terminated = TRUE;
195 /* Synchronization in progress */
196 obj->priv->in_cleanup = FALSE;
197 obj->priv->completion_check_timeout = -1;
199 /* Terminate child on child exit */
200 obj->priv->terminate_on_exit = FALSE;
202 /* Start time of execution */
203 obj->priv->start_time = 0;
205 obj->priv->buffered_output = TRUE;
206 obj->priv->check_for_passwd_prompt = TRUE;
208 /* Output callback */
209 obj->priv->output_callback = NULL;
210 obj->priv->callback_data = NULL;
213 GType
214 anjuta_launcher_get_type ()
216 static GType obj_type = 0;
218 if (!obj_type)
220 static const GTypeInfo obj_info =
222 sizeof (AnjutaLauncherClass),
223 (GBaseInitFunc) NULL,
224 (GBaseFinalizeFunc) NULL,
225 (GClassInitFunc) anjuta_launcher_class_init,
226 (GClassFinalizeFunc) NULL,
227 NULL, /* class_data */
228 sizeof (AnjutaLauncher),
229 0, /* n_preallocs */
230 (GInstanceInitFunc) anjuta_launcher_init,
231 NULL /* value_table */
233 obj_type = g_type_register_static (G_TYPE_OBJECT,
234 "AnjutaLauncher", &obj_info, 0);
236 return obj_type;
239 static void
240 anjuta_launcher_dispose (GObject *obj)
242 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
243 if (anjuta_launcher_is_busy (launcher))
245 pid_t child_pid_save = launcher->priv->child_pid;
246 guint child_source = launcher->priv->source;
247 g_source_remove (child_source);
248 anjuta_launcher_execution_done_cleanup (launcher, FALSE);
250 /* We can not call anjuta_launcher_reset (launcher) to kill the
251 * running child because launcher has been initialized in cleanup
253 kill (child_pid_save, SIGTERM);
254 launcher->priv->busy = FALSE;
256 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
259 static void
260 anjuta_launcher_finalize (GObject *obj)
262 AnjutaLauncher *launcher = ANJUTA_LAUNCHER (obj);
263 g_free (launcher->priv);
264 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
267 static void
268 anjuta_launcher_class_init (AnjutaLauncherClass * klass)
270 GObjectClass *object_class;
271 g_return_if_fail (klass != NULL);
272 object_class = (GObjectClass *) klass;
274 /* DEBUG_PRINT ("Initializing launcher class"); */
276 parent_class = g_type_class_peek_parent (klass);
279 * AnjutaLauncher::child-exited
280 * @launcher: a #AnjutaLancher object.
281 * @child_pid: process ID of the child
282 * @status: status as returned by waitpid function
283 * @time: time in seconds taken by the child
285 * Emitted when the child has exited and all i/o channels have
286 * been closed. If the terminate on exit flag is set, the i/o
287 * channels are automatically closed when the child exit.
288 * You need to use WEXITSTATUS and friend to get the child exit
289 * code from the status returned.
291 launcher_signals[CHILD_EXITED_SIGNAL] =
292 g_signal_new ("child-exited",
293 G_TYPE_FROM_CLASS (object_class),
294 G_SIGNAL_RUN_FIRST,
295 G_STRUCT_OFFSET (AnjutaLauncherClass,
296 child_exited),
297 NULL, NULL,
298 anjuta_cclosure_marshal_VOID__INT_INT_ULONG,
299 G_TYPE_NONE, 3, G_TYPE_INT,
300 G_TYPE_INT, G_TYPE_ULONG);
303 * AnjutaLauncher::busy
304 * @launcher: a #AnjutaLancher object.
305 * @busy: TRUE is a child is currently running
307 * Emitted when a child starts after a call to one execute function
308 * (busy is TRUE) or when a child exits and all i/o channels are
309 * closed (busy is FALSE).
311 launcher_signals[BUSY_SIGNAL] =
312 g_signal_new ("busy",
313 G_TYPE_FROM_CLASS (object_class),
314 G_SIGNAL_RUN_FIRST,
315 G_STRUCT_OFFSET (AnjutaLauncherClass,
316 busy),
317 NULL, NULL,
318 anjuta_cclosure_marshal_VOID__BOOLEAN,
319 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
321 object_class->dispose = anjuta_launcher_dispose;
322 object_class->finalize = anjuta_launcher_finalize;
325 static void
326 anjuta_launcher_init (AnjutaLauncher * obj)
328 g_return_if_fail (obj != NULL);
329 obj->priv = g_new0 (AnjutaLauncherPriv, 1);
330 anjuta_launcher_initialize (obj);
334 * anjuta_launcher_is_busy:
335 * @launcher: a #AnjutaLancher object.
337 * Tells if the laucher is currently executing any command.
339 * Return value: TRUE if launcher is busy, otherwisee FALSE.
341 gboolean
342 anjuta_launcher_is_busy (AnjutaLauncher *launcher)
344 return launcher->priv->busy;
347 static void
348 anjuta_launcher_set_busy (AnjutaLauncher *launcher, gboolean flag)
350 gboolean old_busy = launcher->priv->busy;
351 launcher->priv->busy = flag;
352 if (old_busy != flag)
353 g_signal_emit_by_name (G_OBJECT (launcher), "busy", flag);
357 * anjuta_launcher_send_stdin:
358 * @launcher: a #AnjutaLancher object.
359 * @input_str: The string to send to STDIN of the process.
361 * Sends a string to Standard input of the process currently being executed.
363 void
364 anjuta_launcher_send_stdin (AnjutaLauncher *launcher, const gchar * input_str)
366 g_return_if_fail (launcher);
367 g_return_if_fail (input_str);
369 anjuta_launcher_send_ptyin (launcher, input_str);
373 * anjuta_launcher_send_stdin:
374 * @launcher: a #AnjutaLancher object.
376 * Sends a EOF to Standard input of the process currently being executed.
379 void
380 anjuta_launcher_send_stdin_eof (AnjutaLauncher *launcher)
382 GError* err = NULL;
383 g_io_channel_shutdown (launcher->priv->pty_channel, TRUE,
384 &err);
385 g_io_channel_unref (launcher->priv->pty_channel);
386 launcher->priv->pty_channel = NULL;
388 if (err)
390 g_warning ("g_io_channel_shutdown () failed: %s", err->message);
395 * anjuta_launcher_send_ptyin:
396 * @launcher: a #AnjutaLancher object.
397 * @input_str: The string to send to PTY of the process.
399 * Sends a string to TTY input of the process currently being executed.
400 * Mostly useful for entering passwords and other inputs which are directly
401 * read from TTY input of the process.
403 void
404 anjuta_launcher_send_ptyin (AnjutaLauncher *launcher, const gchar * input_str)
406 gsize bytes_written;
407 GError *err = NULL;
409 if (!input_str || strlen (input_str) == 0) return;
413 g_io_channel_write_chars (launcher->priv->pty_channel,
414 input_str, strlen (input_str),
415 &bytes_written, &err);
416 g_io_channel_flush (launcher->priv->pty_channel, NULL);
417 if (err)
419 g_warning ("Error encountered while writing to PTY!. %s",
420 err->message);
421 g_error_free (err);
423 return;
425 input_str += bytes_written;
427 while (*input_str);
431 * anjuta_launcher_reset:
432 * @launcher: a #AnjutaLancher object.
434 * Resets the launcher and kills (SIGTERM) current process, if it is still
435 * executing.
437 void
438 anjuta_launcher_reset (AnjutaLauncher *launcher)
440 if (anjuta_launcher_is_busy (launcher))
441 kill (launcher->priv->child_pid, SIGTERM);
445 * anjuta_launcher_signal:
446 * @launcher: a #AnjutaLancher object.
447 * @sig: kernel signal ID (e.g. SIGTERM).
449 * Sends a kernel signal to the process that is being executed.
451 void
452 anjuta_launcher_signal (AnjutaLauncher *launcher, int sig)
454 kill (launcher->priv->child_pid, sig);
458 * anjuta_launcher_get_child_pid:
459 * @launcher: a #AnjutaLancher object.
461 * Gets the Process ID of the child being executed.
463 * Return value: Process ID of the child.
465 pid_t
466 anjuta_launcher_get_child_pid (AnjutaLauncher *launcher)
468 if (anjuta_launcher_is_busy (launcher))
469 return launcher->priv->child_pid;
470 else
471 return -1;
474 static void
475 anjuta_launcher_synchronize (AnjutaLauncher *launcher)
477 if (launcher->priv->in_cleanup) return;
479 if (launcher->priv->child_has_terminated &&
480 launcher->priv->stdout_is_done &&
481 launcher->priv->stderr_is_done)
483 if (launcher->priv->completion_check_timeout >= 0)
484 g_source_remove (launcher->priv->completion_check_timeout);
485 launcher->priv->completion_check_timeout =
486 g_timeout_add (50, anjuta_launcher_check_for_execution_done,
487 launcher);
490 /* This case is not very good, but it blocks the whole IDE
491 because we never new if the child has finished */
492 else if (launcher->priv->stdout_is_done &&
493 launcher->priv->stderr_is_done)
495 /* DEBUG_PRINT ("Child has't exited yet waiting for 200ms"); */
496 if (launcher->priv->completion_check_timeout >= 0)
497 g_source_remove (launcher->priv->completion_check_timeout);
498 launcher->priv->completion_check_timeout =
499 g_timeout_add(200, anjuta_launcher_check_for_execution_done,
500 launcher);
502 /* Add this case for gdb. It creates child inheriting gdb
503 * pipes which are not closed if gdb crashes */
504 else if (launcher->priv->child_has_terminated &&
505 launcher->priv->terminate_on_exit)
507 if (launcher->priv->completion_check_timeout >= 0)
508 g_source_remove (launcher->priv->completion_check_timeout);
509 launcher->priv->completion_check_timeout =
510 g_timeout_add(0, anjuta_launcher_call_execution_done,
511 launcher);
515 /* Password dialog */
516 static GtkWidget*
517 create_password_dialog (const gchar* prompt)
519 GtkWidget *dialog;
520 GtkWidget *hbox;
521 GtkWidget *box;
522 GtkWidget *icon;
523 GtkWidget *label;
524 GtkWidget *entry;
526 g_return_val_if_fail (prompt, NULL);
528 dialog = gtk_dialog_new_with_buttons (prompt,
529 NULL, //FIXME: Pass the parent window here
530 // for transient purpose.
531 GTK_DIALOG_DESTROY_WITH_PARENT,
532 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
533 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
534 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
536 gtk_window_set_wmclass (GTK_WINDOW (dialog), "launcher-password-prompt",
537 "anjuta");
538 hbox = gtk_hbox_new (FALSE, 10);
539 gtk_widget_show (hbox);
540 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
542 icon = anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD);
543 gtk_widget_show (icon);
544 gtk_box_pack_start_defaults (GTK_BOX(hbox), icon);
546 if (strlen (prompt) < 20) {
547 box = gtk_hbox_new (FALSE, 5);
548 } else {
549 box = gtk_vbox_new (FALSE, 5);
551 gtk_widget_show (box);
552 gtk_box_pack_start_defaults (GTK_BOX (hbox), box);
554 label = gtk_label_new (_(prompt));
555 gtk_widget_show (label);
556 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
558 entry = gtk_entry_new ();
559 gtk_widget_show (entry);
560 gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
561 gtk_box_pack_start (GTK_BOX (box), entry, FALSE, FALSE, 0);
563 gtk_widget_ref (entry);
564 g_object_set_data_full (G_OBJECT (dialog), "password_entry",
565 gtk_widget_ref (entry),
566 (GDestroyNotify) gtk_widget_unref);
567 gtk_widget_grab_focus (entry);
568 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
570 return dialog;
573 /* pty buffer check for password authentication */
574 static void
575 anjuta_launcher_check_password_real (AnjutaLauncher *launcher,
576 const gchar* last_line)
578 if (anjuta_launcher_is_busy (launcher) == FALSE)
579 return;
581 if (launcher->priv->disable_password_check)
582 return;
584 if (last_line) {
586 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
587 if (is_password_prompt(last_line)) {
588 /* Password prompt detected */
589 GtkWidget* dialog;
590 gint button;
591 const gchar* passwd;
592 gchar* line;
594 dialog = create_password_dialog (last_line);
595 button = gtk_dialog_run (GTK_DIALOG(dialog));
596 switch (button) {
597 case GTK_RESPONSE_OK:
598 passwd = gtk_entry_get_text (
599 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog),
600 "password_entry")));
601 line = g_strconcat (passwd, "\n", NULL);
602 anjuta_launcher_send_ptyin (launcher, line);
603 g_free (line);
604 break;
605 case GTK_RESPONSE_CANCEL:
606 anjuta_launcher_send_ptyin (launcher, "<canceled>\n");
607 anjuta_launcher_reset (launcher);
608 break;
609 default:
610 break;
612 gtk_widget_destroy (dialog);
617 static void
618 anjuta_launcher_check_password (AnjutaLauncher *launcher, const gchar *chars)
620 glong start, end;
621 gchar *last_line;
623 if (!chars || strlen(chars) <= 0)
624 return;
626 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
627 start = end = strlen (chars);
628 while (start > 0 && chars[start-1] != '\n') start--;
630 if (end > start)
632 last_line = g_strndup (&chars[start], end - start + 1);
634 /* DEBUG_PRINT ("Last line = %s", last_line); */
635 /* Checks for password, again */
636 anjuta_launcher_check_password_real (launcher, last_line);
637 g_free (last_line);
641 static gboolean
642 is_password_prompt (const gchar* line)
644 const gchar* password = "assword";
645 const gchar* passphrase = "assphrase";
647 if (strlen (line) < strlen (password)
648 || strlen (line) < strlen (passphrase))
649 return FALSE;
651 if (g_strstr_len(line, 80, password) != NULL
652 || g_strstr_len(line, 80, passphrase) != NULL)
654 int i;
655 for (i = strlen(line) - 1; i != 0; --i)
657 if (line[i] == ':')
658 return TRUE;
659 if (g_ascii_isspace(line[i]))
660 continue;
661 else
662 return FALSE;
665 return FALSE;
668 static void
669 anjuta_launcher_buffered_output (AnjutaLauncher *launcher,
670 AnjutaLauncherOutputType output_type,
671 const gchar *chars)
673 gchar *all_lines;
674 gchar *incomplete_line;
675 gchar **buffer;
677 g_return_if_fail (chars != NULL);
678 g_return_if_fail (strlen (chars) > 0);
680 if (launcher->priv->output_callback == NULL)
681 return;
682 if (launcher->priv->buffered_output == FALSE)
684 (launcher->priv->output_callback)(launcher, output_type, chars,
685 launcher->priv->callback_data);
686 return;
688 switch (output_type)
690 case ANJUTA_LAUNCHER_OUTPUT_STDOUT:
691 buffer = &launcher->priv->stdout_buffer;
692 break;
693 case ANJUTA_LAUNCHER_OUTPUT_STDERR:
694 buffer = &launcher->priv->stderr_buffer;
695 break;
696 default:
697 g_warning ("Should not reach here");
698 return;
700 if (*buffer)
701 all_lines = g_strconcat (*buffer, chars, NULL);
702 else
703 all_lines = g_strdup (chars);
705 /* Buffer the last incomplete line */
706 incomplete_line = all_lines + strlen (all_lines);
707 while (incomplete_line > all_lines &&
708 *incomplete_line != '\n')
710 incomplete_line = g_utf8_prev_char (incomplete_line);
712 if (*incomplete_line == '\n')
713 incomplete_line++;
715 /* Update line buffer */
716 g_free(*buffer);
717 *buffer = NULL;
718 if (strlen(incomplete_line))
720 *buffer = g_strdup (incomplete_line);
721 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
723 /* Check for password prompt */
724 if (launcher->priv->check_for_passwd_prompt)
725 anjuta_launcher_check_password (launcher, incomplete_line);
727 /* Deliver complete lines */
728 *incomplete_line = '\0';
729 if (strlen (all_lines) > 0)
730 (launcher->priv->output_callback)(launcher, output_type, all_lines,
731 launcher->priv->callback_data);
732 g_free (all_lines);
735 static gboolean
736 anjuta_launcher_scan_output (GIOChannel *channel, GIOCondition condition,
737 AnjutaLauncher *launcher)
739 gsize n;
740 gchar buffer[FILE_BUFFER_SIZE];
741 gboolean ret = TRUE;
743 if (condition & G_IO_IN)
745 GError *err = NULL;
748 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
749 if (n > 0 && !err) /* There is output */
751 gchar *utf8_chars;
752 buffer[n] = '\0';
753 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
754 anjuta_launcher_buffered_output (launcher,
755 ANJUTA_LAUNCHER_OUTPUT_STDOUT,
756 utf8_chars);
757 g_free (utf8_chars);
759 /* Ignore illegal characters */
760 else if (err && err->domain == G_CONVERT_ERROR)
762 DEBUG_PRINT ("stdout: %s", err->message);
763 g_error_free (err);
764 err = NULL;
766 /* The pipe is closed on the other side */
767 /* if not related to non blocking read or interrupted syscall */
768 else if (err && errno != EAGAIN && errno != EINTR)
770 DEBUG_PRINT ("stdout: %s", err->message);
771 launcher->priv->stdout_is_done = TRUE;
772 anjuta_launcher_synchronize (launcher);
773 ret = FALSE;
775 /* Read next chars if buffer was too small
776 * (the maximum length of one character is 6 bytes) */
777 } while (!err && (n > FILE_BUFFER_SIZE - 7));
778 if (err)
779 g_error_free (err);
781 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
783 DEBUG_PRINT ("launcher.c: STDOUT pipe closed");
784 launcher->priv->stdout_is_done = TRUE;
785 anjuta_launcher_synchronize (launcher);
786 ret = FALSE;
788 return ret;
791 static gboolean
792 anjuta_launcher_scan_error (GIOChannel *channel, GIOCondition condition,
793 AnjutaLauncher *launcher)
795 gsize n;
796 gchar buffer[FILE_BUFFER_SIZE];
797 gboolean ret = TRUE;
799 if (condition & G_IO_IN)
801 GError *err = NULL;
804 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
805 if (n > 0 && !err) /* There is stderr output */
807 gchar *utf8_chars;
808 buffer[n] = '\0';
809 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
810 anjuta_launcher_buffered_output (launcher,
811 ANJUTA_LAUNCHER_OUTPUT_STDERR,
812 utf8_chars);
813 g_free (utf8_chars);
815 /* Ignore illegal characters */
816 else if (err && err->domain == G_CONVERT_ERROR)
818 DEBUG_PRINT ("stderr: %s", err->message);
819 g_error_free (err);
820 err = NULL;
822 /* The pipe is closed on the other side */
823 /* if not related to non blocking read or interrupted syscall */
824 else if (err && errno != EAGAIN && errno != EINTR)
826 DEBUG_PRINT ("stderr: %s", err->message);
828 launcher->priv->stderr_is_done = TRUE;
829 anjuta_launcher_synchronize (launcher);
830 ret = FALSE;
832 /* Read next chars if buffer was too small
833 * (the maximum length of one character is 6 bytes) */
834 } while (!err && (n > FILE_BUFFER_SIZE - 7));
835 if (err)
836 g_error_free (err);
838 if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
840 DEBUG_PRINT ("launcher.c: STDERR pipe closed");
841 launcher->priv->stderr_is_done = TRUE;
842 anjuta_launcher_synchronize (launcher);
843 ret = FALSE;
845 return ret;
848 static gboolean
849 anjuta_launcher_scan_pty (GIOChannel *channel, GIOCondition condition,
850 AnjutaLauncher *launcher)
852 gsize n;
853 gchar buffer[FILE_BUFFER_SIZE];
854 gboolean ret = TRUE;
856 if (condition & G_IO_IN)
858 GError *err = NULL;
861 g_io_channel_read_chars (channel, buffer, FILE_BUFFER_SIZE-1, &n, &err);
862 if (n > 0 && !err) /* There is stderr output */
864 gchar *utf8_chars;
865 gchar *old_str = launcher->priv->pty_output_buffer;
866 buffer[n] = '\0';
867 utf8_chars = anjuta_util_convert_to_utf8 (buffer);
868 if (old_str)
870 gchar *str = g_strconcat (old_str, utf8_chars, NULL);
871 launcher->priv->pty_output_buffer = str;
872 g_free (old_str);
874 else
875 launcher->priv->pty_output_buffer = g_strdup (utf8_chars);
876 g_free (utf8_chars);
878 /* Ignore illegal characters */
879 else if (err && err->domain == G_CONVERT_ERROR)
881 DEBUG_PRINT ("pty: %s", err->message);
882 g_error_free (err);
883 err = NULL;
885 /* The pipe is closed on the other side */
886 /* if not related to non blocking read or interrupted syscall */
887 else if (err && errno != EAGAIN && errno != EINTR)
889 DEBUG_PRINT ("pty: %s", err->message);
890 ret = FALSE;
892 /* Read next chars if buffer was too small
893 * (the maximum length of one character is 6 bytes) */
894 } while (!err && (n > FILE_BUFFER_SIZE - 7));
895 if (err)
896 g_error_free (err);
897 if (launcher->priv->check_for_passwd_prompt
898 && launcher->priv->pty_output_buffer
899 && strlen (launcher->priv->pty_output_buffer) > 0)
901 anjuta_launcher_check_password (launcher,
902 launcher->priv->pty_output_buffer);
905 /* In pty case, we handle the cases in different invocations */
906 /* Do not hook up for G_IO_HUP */
907 if (condition & G_IO_ERR)
909 DEBUG_PRINT ("launcher.c: PTY pipe error!");
910 ret = FALSE;
912 return ret;
915 static void
916 anjuta_launcher_execution_done_cleanup (AnjutaLauncher *launcher,
917 gboolean emit_signal)
919 gint child_status, child_pid;
920 time_t start_time;
922 if (launcher->priv->in_cleanup)
923 return;
925 launcher->priv->in_cleanup = TRUE;
927 /* Remove pending timeout */
928 if (launcher->priv->completion_check_timeout >= 0)
929 g_source_remove (launcher->priv->completion_check_timeout);
931 /* Make sure all pending I/O are flushed out */
932 while (g_main_context_pending (NULL))
933 g_main_context_iteration (NULL, FALSE);
935 /* Can be called again, while waiting in the previous line
936 * Do nothing if clean up is already done */
937 if (launcher->priv->stdout_channel)
939 g_io_channel_shutdown (launcher->priv->stdout_channel, emit_signal, NULL);
940 g_io_channel_unref (launcher->priv->stdout_channel);
941 g_source_remove (launcher->priv->stdout_watch);
944 if (launcher->priv->stderr_channel)
946 g_io_channel_shutdown (launcher->priv->stderr_channel, emit_signal, NULL);
947 g_io_channel_unref (launcher->priv->stderr_channel);
948 g_source_remove (launcher->priv->stderr_watch);
951 if (launcher->priv->pty_channel)
953 g_io_channel_shutdown (launcher->priv->pty_channel, emit_signal, NULL);
954 g_io_channel_unref (launcher->priv->pty_channel);
956 g_source_remove (launcher->priv->pty_watch);
959 if (launcher->priv->pty_output_buffer)
960 g_free (launcher->priv->pty_output_buffer);
961 if (launcher->priv->stdout_buffer)
962 g_free (launcher->priv->stdout_buffer);
963 if (launcher->priv->stderr_buffer)
964 g_free (launcher->priv->stdout_buffer);
966 /* Save them before we re-initialize */
967 child_status = launcher->priv->child_status;
968 child_pid = launcher->priv->child_pid;
969 start_time = launcher->priv->start_time;
971 if (emit_signal)
972 anjuta_launcher_set_busy (launcher, FALSE);
974 anjuta_launcher_initialize (launcher);
977 /* Call this here, after set_busy (FALSE) so we are able to
978 launch a new child from the terminate function.
979 (by clubfan 2002-04-07)
981 /* DEBUG_PRINT ("Exit status: %d", child_status); */
982 if (emit_signal)
983 g_signal_emit_by_name (launcher, "child-exited", child_pid,
984 child_status,
985 time (NULL) - start_time);
988 /* Using this function is necessary because
989 * anjuta_launcher_execution_done_cleanup needs to be called in the same
990 * thread than the gtk main loop */
991 static gboolean
992 anjuta_launcher_call_execution_done (gpointer data)
994 AnjutaLauncher *launcher = data;
996 launcher->priv->completion_check_timeout = -1;
997 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
998 return FALSE;
1001 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
1002 static gboolean
1003 anjuta_launcher_check_for_execution_done (gpointer data)
1005 AnjutaLauncher *launcher = data;
1007 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
1008 launcher->priv->stdout_is_done ? 1 : 0,
1009 launcher->priv->stderr_is_done ? 1 : 0);
1011 if (launcher->priv->stdout_is_done == FALSE ||
1012 launcher->priv->stderr_is_done == FALSE)
1013 return TRUE;
1014 if (launcher->priv->child_has_terminated == FALSE)
1016 /* DEBUG_PRINT ("launcher: We missed the exit of the child"); */
1018 launcher->priv->completion_check_timeout = -1;
1019 anjuta_launcher_execution_done_cleanup (launcher, TRUE);
1020 return FALSE;
1023 static void
1024 anjuta_launcher_child_terminated (GPid pid, gint status, gpointer data)
1026 AnjutaLauncher *launcher = data;
1028 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher));
1030 /* Save child exit code */
1031 launcher->priv->child_status = status;
1032 launcher->priv->child_has_terminated = TRUE;
1033 anjuta_launcher_synchronize (launcher);
1037 * anjuta_launcher_set_encoding:
1038 * @launcher: a #AnjutaLancher object.
1039 * @charset: Character set to use for Input/Output with the process.
1041 * Sets the character set to use for Input/Output with the process.
1043 * Return value: TRUE if successful, otherwise FALSE.
1045 gboolean
1046 anjuta_launcher_set_encoding (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;
1068 static pid_t
1069 anjuta_launcher_fork (AnjutaLauncher *launcher, gchar *const args[])
1071 char *working_dir;
1072 int pty_master_fd, md;
1073 int stdout_pipe[2], stderr_pipe[2];
1074 pid_t child_pid;
1075 struct termios termios_flags;
1076 const gchar *charset;
1078 working_dir = g_get_current_dir ();
1080 /* The pipes */
1081 pipe (stderr_pipe);
1082 pipe (stdout_pipe);
1084 /* Fork the command */
1085 child_pid = forkpty (&pty_master_fd, NULL, NULL, NULL);
1086 if (child_pid == 0)
1088 close (2);
1089 dup (stderr_pipe[1]);
1090 close (1);
1091 dup (stdout_pipe[1]);
1093 /* Close unnecessary pipes */
1094 close (stderr_pipe[0]);
1095 close (stdout_pipe[0]);
1098 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1099 perror ("Could not set new controlling tty");
1101 /* Set no delays for the write pipes (non_buffered) so
1102 that we get all the outputs immidiately */
1103 if ((md = fcntl (stdout_pipe[1], F_GETFL)) != -1)
1104 fcntl (stdout_pipe[1], F_SETFL, O_SYNC | md);
1105 if ((md = fcntl (stderr_pipe[1], F_GETFL)) != -1)
1106 fcntl (stderr_pipe[1], F_SETFL, O_SYNC | md);
1108 execvp (args[0], args);
1109 g_warning (_("Cannot execute command: \"%s\""), args[0]);
1110 perror(_("execvp failed"));
1111 _exit(-1);
1113 g_free (working_dir);
1115 /* Close parent's side pipes */
1116 close (stderr_pipe[1]);
1117 close (stdout_pipe[1]);
1119 if (child_pid < 0)
1121 g_warning ("launcher.c: Fork failed!");
1122 /* Close parent's side pipes */
1123 close (stderr_pipe[0]);
1124 close (stdout_pipe[0]);
1125 return child_pid;
1129 * Set pipes none blocking, so we can read big buffers
1130 * in the callback without having to use FIONREAD
1131 * to make sure the callback doesn't block.
1133 if ((md = fcntl (stdout_pipe[0], F_GETFL)) != -1)
1134 fcntl (stdout_pipe[0], F_SETFL, O_NONBLOCK | md);
1135 if ((md = fcntl (stderr_pipe[0], F_GETFL)) != -1)
1136 fcntl (stderr_pipe[0], F_SETFL, O_NONBLOCK | md);
1137 if ((md = fcntl (pty_master_fd, F_GETFL)) != -1)
1138 fcntl (pty_master_fd, F_SETFL, O_NONBLOCK | md);
1140 launcher->priv->child_pid = child_pid;
1141 launcher->priv->stderr_channel = g_io_channel_unix_new (stderr_pipe[0]);
1142 launcher->priv->stdout_channel = g_io_channel_unix_new (stdout_pipe[0]);
1143 launcher->priv->pty_channel = g_io_channel_unix_new (pty_master_fd);
1145 g_io_channel_set_buffer_size (launcher->priv->pty_channel, FILE_INPUT_BUFFER_SIZE);
1148 g_get_charset (&charset);
1149 anjuta_launcher_set_encoding (launcher, charset);
1151 tcgetattr(pty_master_fd, &termios_flags);
1152 termios_flags.c_iflag &= ~(IGNPAR | INPCK | INLCR | IGNCR | ICRNL | IXON |
1153 IXOFF | ISTRIP);
1154 termios_flags.c_iflag |= IGNBRK | BRKINT | IMAXBEL | IXANY;
1155 termios_flags.c_oflag &= ~OPOST;
1156 // termios_flags.c_oflag |= 0;
1157 termios_flags.c_cflag &= ~(CSTOPB | CREAD | PARENB | HUPCL);
1158 termios_flags.c_cflag |= CS8 | CLOCAL;
1160 if (!launcher->priv->terminal_echo_on)
1162 termios_flags.c_lflag &= ~(ECHOKE | ECHOE | ECHO | ECHONL |
1163 #ifdef ECHOPRT
1164 ECHOPRT |
1165 #endif
1166 ECHOCTL | ISIG | ICANON | IEXTEN | NOFLSH | TOSTOP);
1168 // termios_flags.c_lflag |= 0;
1169 termios_flags.c_cc[VMIN] = 0;
1170 cfsetospeed(&termios_flags, __MAX_BAUD);
1171 tcsetattr(pty_master_fd, TCSANOW, &termios_flags);
1173 launcher->priv->stderr_watch =
1174 g_io_add_watch (launcher->priv->stderr_channel,
1175 G_IO_IN | G_IO_ERR | G_IO_HUP,
1176 (GIOFunc)anjuta_launcher_scan_error, launcher);
1177 launcher->priv->stdout_watch =
1178 g_io_add_watch (launcher->priv->stdout_channel,
1179 G_IO_IN | G_IO_ERR | G_IO_HUP,
1180 (GIOFunc)anjuta_launcher_scan_output, launcher);
1181 launcher->priv->pty_watch =
1182 g_io_add_watch (launcher->priv->pty_channel,
1183 G_IO_IN | G_IO_ERR, /* Do not hook up for G_IO_HUP */
1184 (GIOFunc)anjuta_launcher_scan_pty, launcher);
1186 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1187 launcher->priv->source = g_child_watch_add (launcher->priv->child_pid,
1188 anjuta_launcher_child_terminated, launcher);
1189 return child_pid;
1193 * anjuta_launcher_execute_v:
1194 * @launcher: a #AnjutaLancher object.
1195 * @argv: Command args.
1196 * @callback: The callback for delivering output from the process.
1197 * @callback_data: Callback data for the above callback.
1199 * The first of the @args is the command itself. The rest are sent to the
1200 * as it's arguments. This function works similar to anjuta_launcher_execute().
1202 * Return value: TRUE if successfully launched, otherwise FALSE.
1204 gboolean
1205 anjuta_launcher_execute_v (AnjutaLauncher *launcher, gchar *const argv[],
1206 AnjutaLauncherOutputCallback callback,
1207 gpointer callback_data)
1209 if (anjuta_launcher_is_busy (launcher))
1210 return FALSE;
1212 anjuta_launcher_set_busy (launcher, TRUE);
1214 launcher->priv->start_time = time (NULL);
1215 launcher->priv->child_status = 0;
1216 launcher->priv->stdout_is_done = FALSE;
1217 launcher->priv->stderr_is_done = FALSE;
1218 launcher->priv->child_has_terminated = FALSE;
1219 launcher->priv->in_cleanup = FALSE;
1220 launcher->priv->output_callback = callback;
1221 launcher->priv->callback_data = callback_data;
1223 /* On a fork error perform a cleanup and return */
1224 if (anjuta_launcher_fork (launcher, argv) < 0)
1226 anjuta_launcher_initialize (launcher);
1227 return FALSE;
1229 return TRUE;
1233 * anjuta_launcher_execute:
1234 * @launcher: a #AnjutaLancher object.
1235 * @command_str: The command to execute.
1236 * @callback: The callback for delivering output from the process.
1237 * @callback_data: Callback data for the above callback.
1239 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1240 * delivered to the above callback. The data are delivered as they arrive
1241 * from the process and could be of any lenght. If the process asks for
1242 * passwords, the user will be automatically prompted with a dialog to enter
1243 * it. Please note that not all formats of the password are recognized. Those
1244 * with the standard 'assword:' substring in the prompt should work well.
1246 * Return value: TRUE if successfully launched, otherwise FALSE.
1248 gboolean
1249 anjuta_launcher_execute (AnjutaLauncher *launcher, const gchar *command_str,
1250 AnjutaLauncherOutputCallback callback,
1251 gpointer callback_data)
1253 GList *args_list, *args_list_ptr;
1254 gchar **args, **args_ptr;
1255 gboolean ret;
1257 /* Prepare command args */
1258 args_list = anjuta_util_parse_args_from_string (command_str);
1259 args = g_new (char*, g_list_length (args_list) + 1);
1260 args_list_ptr = args_list;
1261 args_ptr = args;
1262 while (args_list_ptr)
1264 *args_ptr = (char*) args_list_ptr->data;
1265 args_list_ptr = g_list_next (args_list_ptr);
1266 args_ptr++;
1268 *args_ptr = NULL;
1270 ret = anjuta_launcher_execute_v (launcher, args,
1271 callback, callback_data);
1272 g_free (args);
1273 anjuta_util_glist_strings_free (args_list);
1274 return ret;
1278 * anjuta_launcher_set_buffered_output:
1279 * @launcher: a #AnjutaLancher object.
1280 * @buffered: buffer output.
1282 * Sets if output should buffered or not. By default, it is buffered.
1284 * Return value: Previous flag value
1286 gboolean
1287 anjuta_launcher_set_buffered_output (AnjutaLauncher *launcher, gboolean buffered)
1289 gboolean past_value = launcher->priv->buffered_output;
1290 launcher->priv->buffered_output = buffered;
1291 return past_value;
1295 * anjuta_launcher_set_check_passwd_prompt:
1296 * @launcher: a #AnjutaLancher object.
1297 * @check_passwd: check for password.
1299 * Set if output is checked for a password prompti. A special dialog box
1300 * is use to enter it in this case. By default, this behavior is enabled.
1302 * Return value: Previous flag value
1304 gboolean
1305 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher *launcher, gboolean check_passwd)
1307 gboolean past_value = launcher->priv->check_for_passwd_prompt;
1308 launcher->priv->check_for_passwd_prompt = check_passwd;
1309 return past_value;
1313 * anjuta_launcher_set_terminal_echo:
1314 * @launcher: a #AnjutaLancher object.
1315 * @echo_on: Echo ON flag.
1317 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1318 * it is disabled.
1320 * Return value: Previous flag value
1322 gboolean
1323 anjuta_launcher_set_terminal_echo (AnjutaLauncher *launcher,
1324 gboolean echo_on)
1326 gboolean past_value = launcher->priv->terminal_echo_on;
1327 launcher->priv->terminal_echo_on = echo_on;
1328 return past_value;
1332 * anjuta_launcher_set_terminate_on_exit:
1333 * @launcher: a #AnjutaLancher object.
1334 * @terminate_on_exit: terminate on exit flag
1336 * When this flag is set, al i/o channels are closed and the child-exit
1337 * signal is emitted as soon as the child exit. By default, or when this
1338 * flag is clear, the launcher object wait until the i/o channels are
1339 * closed.
1341 * Return value: Previous flag value
1343 gboolean
1344 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher *launcher,
1345 gboolean terminate_on_exit)
1347 gboolean past_value = launcher->priv->terminate_on_exit;
1348 launcher->priv->terminate_on_exit = terminate_on_exit;
1349 return past_value;
1353 * anjuta_launcher_disable_password_check:
1354 * @launcher: IAnjutaLauncher object
1355 * @disable: TRUE disables password check
1357 * Do not check for password prompts in input
1359 * Return value: a new instance of #AnjutaLancher class.
1362 void anjuta_launcher_disable_password_check (AnjutaLauncher* launcher,
1363 gboolean disable)
1365 launcher->priv->disable_password_check = disable;
1369 * anjuta_launcher_new:
1371 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1372 * it is disabled.
1374 * Return value: a new instance of #AnjutaLancher class.
1376 AnjutaLauncher*
1377 anjuta_launcher_new ()
1379 return g_object_new (ANJUTA_TYPE_LAUNCHER, NULL);