1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * SECTION:anjuta-launcher
23 * @short_description: External process launcher with async input/output
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-launcher.h
39 /* not sure if any platform has more than one of these, so play it
40 safe and use any-and-all-found rather than elif fallback */
51 #include "anjuta-utils-priv.h"
58 #include <glib/gi18n.h>
61 #include "anjuta-utils.h"
62 #include "anjuta-marshal.h"
63 #include "resources.h"
64 #include "anjuta-launcher.h"
65 #include "anjuta-debug.h"
67 #define ANJUTA_PIXMAP_PASSWORD "password.png"
68 #define FILE_BUFFER_SIZE 1024
69 #define FILE_INPUT_BUFFER_SIZE (1024 * 1024 * 4)
72 # define __MAX_BAUD B460800
73 # elif defined(B307200)
74 # define __MAX_BAUD B307200
75 # elif defined(B256000)
76 # define __MAX_BAUD B256000
78 # define __MAX_BAUD B230400
84 anjuta_launcher_pty_check_child_exit_code (AnjutaLauncher *launcher,
87 struct _AnjutaLauncherPriv
90 * Busy flag is TRUE if the Launcher
91 * is currently executing a child.
95 /* These flags are used to synchronize the IO operations. */
96 gboolean stdout_is_done
;
97 gboolean stderr_is_done
;
100 GIOChannel
*stdout_channel
;
101 GIOChannel
*stderr_channel
;
102 /*GIOChannel *stdin_channel;*/
103 GIOChannel
*pty_channel
;
105 /* GIO watch handles */
110 /* Output line buffers */
111 gchar
*stdout_buffer
;
112 gchar
*stderr_buffer
;
114 /* Output of the pty is constantly stored here.*/
115 gchar
*pty_output_buffer
;
118 gboolean terminal_echo_on
;
124 gboolean child_has_terminated
;
126 /* Synchronization in progress */
127 guint completion_check_timeout
;
129 /* Terminate child on child exit */
130 gboolean terminate_on_exit
;
132 /* Start time of execution */
135 /* Should the outputs be buffered */
136 gboolean buffered_output
;
138 /* Should we check for password prompts in stdout and pty */
139 gboolean check_for_passwd_prompt
;
141 /* Output callback */
142 AnjutaLauncherOutputCallback output_callback
;
145 gpointer callback_data
;
148 gboolean custom_encoding
;
157 /* OUTPUT_ARRIVED_SIGNAL, */
163 static void anjuta_launcher_class_init (AnjutaLauncherClass
* klass
);
164 static void anjuta_launcher_init (AnjutaLauncher
* obj
);
165 static gboolean
anjuta_launcher_call_execution_done (gpointer data
);
166 static gboolean
anjuta_launcher_check_for_execution_done (gpointer data
);
167 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher
*launcher
,
168 gboolean emit_signal
);
170 static gboolean
is_password_prompt(const gchar
* line
);
172 static guint launcher_signals
[LAST_SIGNAL
] = { 0 };
173 static AnjutaLauncherClass
*parent_class
;
176 anjuta_launcher_initialize (AnjutaLauncher
*obj
)
179 obj
->priv
->busy
= FALSE
;
181 /* These flags are used to synchronize the IO operations. */
182 obj
->priv
->stdout_is_done
= FALSE
;
183 obj
->priv
->stderr_is_done
= FALSE
;
186 obj
->priv
->stdout_channel
= NULL
;
187 obj
->priv
->stderr_channel
= NULL
;
188 obj
->priv
->pty_channel
= NULL
;
190 /* Output line buffers */
191 obj
->priv
->stdout_buffer
= NULL
;
192 obj
->priv
->stderr_buffer
= NULL
;
195 obj
->priv
->pty_output_buffer
= NULL
;
197 obj
->priv
->terminal_echo_on
= TRUE
;
200 obj
->priv
->child_pid
= 0;
201 obj
->priv
->child_status
= -1;
202 obj
->priv
->child_has_terminated
= TRUE
;
203 obj
->priv
->source
= 0;
205 /* Synchronization in progress */
206 obj
->priv
->completion_check_timeout
= 0;
208 /* Terminate child on child exit */
209 obj
->priv
->terminate_on_exit
= FALSE
;
211 /* Start time of execution */
212 obj
->priv
->start_time
= 0;
214 obj
->priv
->buffered_output
= TRUE
;
215 obj
->priv
->check_for_passwd_prompt
= TRUE
;
217 /* Output callback */
218 obj
->priv
->output_callback
= NULL
;
219 obj
->priv
->callback_data
= NULL
;
222 obj
->priv
->custom_encoding
= FALSE
;
223 obj
->priv
->encoding
= NULL
;
226 obj
->priv
->env
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
231 anjuta_launcher_get_type ()
233 static GType obj_type
= 0;
237 static const GTypeInfo obj_info
=
239 sizeof (AnjutaLauncherClass
),
240 (GBaseInitFunc
) NULL
,
241 (GBaseFinalizeFunc
) NULL
,
242 (GClassInitFunc
) anjuta_launcher_class_init
,
243 (GClassFinalizeFunc
) NULL
,
244 NULL
, /* class_data */
245 sizeof (AnjutaLauncher
),
247 (GInstanceInitFunc
) anjuta_launcher_init
,
248 NULL
/* value_table */
250 obj_type
= g_type_register_static (G_TYPE_OBJECT
,
251 "AnjutaLauncher", &obj_info
, 0);
257 anjuta_launcher_dispose (GObject
*obj
)
259 AnjutaLauncher
*launcher
= ANJUTA_LAUNCHER (obj
);
260 if (anjuta_launcher_is_busy (launcher
))
262 g_source_remove (launcher
->priv
->source
);
263 launcher
->priv
->source
= 0;
265 anjuta_launcher_execution_done_cleanup (launcher
, FALSE
);
267 launcher
->priv
->busy
= FALSE
;
270 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
274 anjuta_launcher_finalize (GObject
*obj
)
276 AnjutaLauncher
*launcher
= ANJUTA_LAUNCHER (obj
);
277 if (launcher
->priv
->custom_encoding
&& launcher
->priv
->encoding
)
278 g_free (launcher
->priv
->encoding
);
280 g_hash_table_destroy (launcher
->priv
->env
);
282 g_free (launcher
->priv
);
283 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
287 anjuta_launcher_class_init (AnjutaLauncherClass
* klass
)
289 GObjectClass
*object_class
;
290 g_return_if_fail (klass
!= NULL
);
291 object_class
= (GObjectClass
*) klass
;
293 /* DEBUG_PRINT ("%s", "Initializing launcher class"); */
295 parent_class
= g_type_class_peek_parent (klass
);
298 * AnjutaLauncher::child-exited:
299 * @launcher: a #AnjutaLancher object.
300 * @child_pid: process ID of the child
301 * @status: status as returned by waitpid function
302 * @time: time in seconds taken by the child
304 * Emitted when the child has exited and all i/o channels have
305 * been closed. If the terminate on exit flag is set, the i/o
306 * channels are automatically closed when the child exit.
307 * You need to use WEXITSTATUS and friend to get the child exit
308 * code from the status returned.
310 launcher_signals
[CHILD_EXITED_SIGNAL
] =
311 g_signal_new ("child-exited",
312 G_TYPE_FROM_CLASS (object_class
),
314 G_STRUCT_OFFSET (AnjutaLauncherClass
,
317 anjuta_cclosure_marshal_VOID__INT_INT_ULONG
,
318 G_TYPE_NONE
, 3, G_TYPE_INT
,
319 G_TYPE_INT
, G_TYPE_ULONG
);
322 * AnjutaLauncher::busy:
323 * @launcher: a #AnjutaLancher object.
324 * @busy: %TRUE is a child is currently running
326 * Emitted when a child starts after a call to one execute function
327 * (busy is %TRUE) or when a child exits and all i/o channels are
328 * closed (busy is %FALSE).
330 launcher_signals
[BUSY_SIGNAL
] =
331 g_signal_new ("busy",
332 G_TYPE_FROM_CLASS (object_class
),
334 G_STRUCT_OFFSET (AnjutaLauncherClass
,
337 anjuta_cclosure_marshal_VOID__BOOLEAN
,
338 G_TYPE_NONE
, 1, G_TYPE_BOOLEAN
);
340 object_class
->dispose
= anjuta_launcher_dispose
;
341 object_class
->finalize
= anjuta_launcher_finalize
;
345 anjuta_launcher_init (AnjutaLauncher
* obj
)
347 g_return_if_fail (obj
!= NULL
);
348 obj
->priv
= g_new0 (AnjutaLauncherPriv
, 1);
349 anjuta_launcher_initialize (obj
);
353 * anjuta_launcher_is_busy:
354 * @launcher: a #AnjutaLancher object.
356 * Tells if the laucher is currently executing any command.
358 * Return value: %TRUE if launcher is busy, otherwise %FALSE.
361 anjuta_launcher_is_busy (AnjutaLauncher
*launcher
)
363 return launcher
->priv
->busy
;
367 anjuta_launcher_set_busy (AnjutaLauncher
*launcher
, gboolean flag
)
369 gboolean old_busy
= launcher
->priv
->busy
;
370 launcher
->priv
->busy
= flag
;
371 if (old_busy
!= flag
)
372 g_signal_emit_by_name (G_OBJECT (launcher
), "busy", flag
);
376 * anjuta_launcher_send_stdin:
377 * @launcher: a #AnjutaLancher object.
378 * @input_str: The string to send to STDIN of the process.
380 * Sends a string to Standard input of the process currently being executed.
383 anjuta_launcher_send_stdin (AnjutaLauncher
*launcher
, const gchar
* input_str
)
385 g_return_if_fail (launcher
);
386 g_return_if_fail (input_str
);
388 anjuta_launcher_send_ptyin (launcher
, input_str
);
392 * anjuta_launcher_send_stdin_eof:
393 * @launcher: a #AnjutaLancher object.
395 * Sends a EOF to Standard input of the process currently being executed.
399 anjuta_launcher_send_stdin_eof (AnjutaLauncher
*launcher
)
402 g_io_channel_shutdown (launcher
->priv
->pty_channel
, TRUE
,
404 g_io_channel_unref (launcher
->priv
->pty_channel
);
405 launcher
->priv
->pty_channel
= NULL
;
409 g_warning ("g_io_channel_shutdown () failed: %s", err
->message
);
414 * anjuta_launcher_send_ptyin:
415 * @launcher: a #AnjutaLancher object.
416 * @input_str: The string to send to PTY of the process.
418 * Sends a string to TTY input of the process currently being executed.
419 * Mostly useful for entering passwords and other inputs which are directly
420 * read from TTY input of the process.
423 anjuta_launcher_send_ptyin (AnjutaLauncher
*launcher
, const gchar
* input_str
)
425 gsize bytes_written
= 0;
428 g_return_if_fail (launcher
);
429 g_return_if_fail (input_str
);
430 g_return_if_fail (launcher
->priv
->pty_channel
!= NULL
);
432 if (strlen (input_str
) == 0)
437 g_io_channel_write_chars (launcher
->priv
->pty_channel
,
438 input_str
, strlen (input_str
),
439 &bytes_written
, &err
);
440 g_io_channel_flush (launcher
->priv
->pty_channel
, NULL
);
443 g_warning ("Error encountered while writing to PTY!. %s",
449 input_str
+= bytes_written
;
455 * anjuta_launcher_reset:
456 * @launcher: a #AnjutaLancher object.
458 * Resets the launcher and kills (SIGTERM) current process, if it is still
462 anjuta_launcher_reset (AnjutaLauncher
*launcher
)
464 if (anjuta_launcher_is_busy (launcher
) &&
465 launcher
->priv
->child_pid
)
466 kill (launcher
->priv
->child_pid
, SIGTERM
);
470 * anjuta_launcher_signal:
471 * @launcher: a #AnjutaLancher object.
472 * @sig: kernel signal ID (e.g. SIGTERM).
474 * Sends a kernel signal to the process that is being executed.
477 anjuta_launcher_signal (AnjutaLauncher
*launcher
, int sig
)
479 if (launcher
->priv
->child_pid
)
480 kill (launcher
->priv
->child_pid
, sig
);
484 * anjuta_launcher_get_child_pid:
485 * @launcher: a #AnjutaLancher object.
487 * Gets the Process ID of the child being executed.
489 * Return value: Process ID of the child.
492 anjuta_launcher_get_child_pid (AnjutaLauncher
*launcher
)
494 if (anjuta_launcher_is_busy (launcher
))
495 return launcher
->priv
->child_pid
;
501 anjuta_launcher_synchronize (AnjutaLauncher
*launcher
)
503 if (launcher
->priv
->child_has_terminated
&&
504 launcher
->priv
->stdout_is_done
&&
505 launcher
->priv
->stderr_is_done
)
507 if (launcher
->priv
->completion_check_timeout
!= 0)
508 g_source_remove (launcher
->priv
->completion_check_timeout
);
509 launcher
->priv
->completion_check_timeout
=
510 /* Use a low priority timer to make sure all pending I/O are flushed out */
511 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE
, 50, anjuta_launcher_check_for_execution_done
,
515 /* This case is not very good, but it blocks the whole IDE
516 because we never new if the child has finished */
517 else if (launcher
->priv
->stdout_is_done
&&
518 launcher
->priv
->stderr_is_done
)
520 /* DEBUG_PRINT ("%s", "Child has't exited yet waiting for 200ms"); */
521 if (launcher
->priv
->completion_check_timeout
!= 0)
522 g_source_remove (launcher
->priv
->completion_check_timeout
);
523 launcher
->priv
->completion_check_timeout
=
524 /* Use a low priority timer to make sure all pending I/O are flushed out */
525 g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
, 200, anjuta_launcher_check_for_execution_done
,
528 /* Add this case for gdb. It creates child inheriting gdb
529 * pipes which are not closed if gdb crashes */
530 else if (launcher
->priv
->child_has_terminated
&&
531 launcher
->priv
->terminate_on_exit
)
533 if (launcher
->priv
->completion_check_timeout
!= 0)
534 g_source_remove (launcher
->priv
->completion_check_timeout
);
535 launcher
->priv
->completion_check_timeout
=
536 /* Use a low priority timer to make sure all pending I/O are flushed out */
537 g_idle_add ( anjuta_launcher_call_execution_done
,
542 /* Password dialog */
544 create_password_dialog (const gchar
* prompt
)
553 g_return_val_if_fail (prompt
, NULL
);
555 dialog
= gtk_dialog_new_with_buttons (prompt
,
556 NULL
, //FIXME: Pass the parent window here
557 // for transient purpose.
558 GTK_DIALOG_DESTROY_WITH_PARENT
,
559 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
560 GTK_STOCK_OK
, GTK_RESPONSE_OK
, NULL
);
561 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
563 gtk_window_set_wmclass (GTK_WINDOW (dialog
), "launcher-password-prompt",
565 hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 10);
566 gtk_widget_show (hbox
);
567 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG(dialog
))), hbox
);
569 icon
= anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD
);
570 gtk_widget_show (icon
);
571 gtk_box_pack_start (GTK_BOX(hbox
), icon
, TRUE
, TRUE
, 0);
573 if (strlen (prompt
) < 20) {
574 box
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 5);
576 box
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 5);
578 gtk_widget_show (box
);
579 gtk_box_pack_start (GTK_BOX (hbox
), box
, TRUE
, TRUE
, 0);
581 label
= gtk_label_new (_(prompt
));
582 gtk_widget_show (label
);
583 gtk_box_pack_start (GTK_BOX (box
), label
, FALSE
, FALSE
, 0);
585 entry
= gtk_entry_new ();
586 gtk_widget_show (entry
);
587 gtk_entry_set_visibility (GTK_ENTRY (entry
), FALSE
);
588 gtk_box_pack_start (GTK_BOX (box
), entry
, FALSE
, FALSE
, 0);
590 g_object_ref (entry
);
591 g_object_set_data_full (G_OBJECT (dialog
), "password_entry",
592 g_object_ref (entry
),
594 gtk_widget_grab_focus (entry
);
595 gtk_entry_set_activates_default (GTK_ENTRY (entry
), TRUE
);
600 /* pty buffer check for password authentication */
602 anjuta_launcher_check_password_real (AnjutaLauncher
*launcher
,
603 const gchar
* last_line
)
605 if (anjuta_launcher_is_busy (launcher
) == FALSE
)
610 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
611 if (is_password_prompt(last_line
)) {
612 /* Password prompt detected */
618 dialog
= create_password_dialog (last_line
);
619 button
= gtk_dialog_run (GTK_DIALOG(dialog
));
621 case GTK_RESPONSE_OK
:
622 passwd
= gtk_entry_get_text (
623 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog
),
625 line
= g_strconcat (passwd
, "\n", NULL
);
626 anjuta_launcher_send_ptyin (launcher
, line
);
629 case GTK_RESPONSE_CANCEL
:
630 anjuta_launcher_reset (launcher
);
635 gtk_widget_destroy (dialog
);
641 anjuta_launcher_check_password (AnjutaLauncher
*launcher
, const gchar
*chars
)
646 if (!chars
|| strlen(chars
) <= 0)
649 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
650 start
= end
= strlen (chars
);
651 while (start
> 0 && chars
[start
-1] != '\n') start
--;
655 last_line
= g_strndup (&chars
[start
], end
- start
+ 1);
657 /* DEBUG_PRINT ("Last line = %s", last_line); */
658 /* Checks for password, again */
659 anjuta_launcher_check_password_real (launcher
, last_line
);
665 is_password_prompt (const gchar
* line
)
667 const gchar
* regex
= "[Pp]assword.*:";
669 * Translators: This regex should match the password prompts of
670 * at least the "su" and the "sudo" command line utility in your
671 * language and possible other things like "ssh".
672 * More information on the regular expression syntax can be
673 * found at http://library.gnome.org/devel/glib/unstable/glib-regex-syntax.html
675 const gchar
* i18n_regex
= _("[Pp]assword.*:");
676 if (g_regex_match_simple (regex
, line
, 0, 0))
678 else if (g_regex_match_simple (i18n_regex
, line
, 0, 0))
685 anjuta_launcher_buffered_output (AnjutaLauncher
*launcher
,
686 AnjutaLauncherOutputType output_type
,
690 gchar
*incomplete_line
;
693 g_return_if_fail (chars
!= NULL
);
694 g_return_if_fail (strlen (chars
) > 0);
696 if (launcher
->priv
->output_callback
== NULL
)
698 if (launcher
->priv
->buffered_output
== FALSE
)
700 (launcher
->priv
->output_callback
)(launcher
, output_type
, chars
,
701 launcher
->priv
->callback_data
);
706 case ANJUTA_LAUNCHER_OUTPUT_STDOUT
:
707 buffer
= &launcher
->priv
->stdout_buffer
;
709 case ANJUTA_LAUNCHER_OUTPUT_STDERR
:
710 buffer
= &launcher
->priv
->stderr_buffer
;
713 g_warning ("Should not reach here");
717 all_lines
= g_strconcat (*buffer
, chars
, NULL
);
719 all_lines
= g_strdup (chars
);
721 /* Buffer the last incomplete line */
722 incomplete_line
= all_lines
+ strlen (all_lines
);
723 while (incomplete_line
> all_lines
&&
724 *incomplete_line
!= '\n')
726 incomplete_line
= g_utf8_prev_char (incomplete_line
);
728 if (*incomplete_line
== '\n')
731 /* Update line buffer */
734 if (strlen(incomplete_line
))
736 *buffer
= g_strdup (incomplete_line
);
737 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
739 /* Check for password prompt */
740 if (launcher
->priv
->check_for_passwd_prompt
)
741 anjuta_launcher_check_password (launcher
, incomplete_line
);
743 /* Deliver complete lines */
744 *incomplete_line
= '\0';
745 if (strlen (all_lines
) > 0)
746 (launcher
->priv
->output_callback
)(launcher
, output_type
, all_lines
,
747 launcher
->priv
->callback_data
);
752 anjuta_launcher_scan_output (GIOChannel
*channel
, GIOCondition condition
,
753 AnjutaLauncher
*launcher
)
756 gchar buffer
[FILE_BUFFER_SIZE
];
759 if (condition
& G_IO_IN
)
764 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
765 if (n
> 0) /* There is output */
767 gchar
*utf8_chars
= NULL
;
769 if (!launcher
->priv
->custom_encoding
)
770 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
772 utf8_chars
= g_strdup(buffer
);
773 anjuta_launcher_buffered_output (launcher
,
774 ANJUTA_LAUNCHER_OUTPUT_STDOUT
,
778 /* Ignore illegal characters */
779 if (err
&& err
->domain
== G_CONVERT_ERROR
)
784 /* The pipe is closed on the other side */
785 /* if not related to non blocking read or interrupted syscall */
786 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
788 launcher
->priv
->stdout_is_done
= TRUE
;
789 anjuta_launcher_synchronize (launcher
);
792 /* Read next chars if buffer was too small
793 * (the maximum length of one character is 6 bytes) */
794 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
798 if ((condition
& G_IO_ERR
) || (condition
& G_IO_HUP
))
800 DEBUG_PRINT ("%s", "launcher.c: STDOUT pipe closed");
801 launcher
->priv
->stdout_is_done
= TRUE
;
802 anjuta_launcher_synchronize (launcher
);
809 anjuta_launcher_scan_error (GIOChannel
*channel
, GIOCondition condition
,
810 AnjutaLauncher
*launcher
)
813 gchar buffer
[FILE_BUFFER_SIZE
];
816 if (condition
& G_IO_IN
)
821 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
822 if (n
> 0) /* There is stderr output */
826 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
827 anjuta_launcher_buffered_output (launcher
,
828 ANJUTA_LAUNCHER_OUTPUT_STDERR
,
832 /* Ignore illegal characters */
833 if (err
&& err
->domain
== G_CONVERT_ERROR
)
838 /* The pipe is closed on the other side */
839 /* if not related to non blocking read or interrupted syscall */
840 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
843 launcher
->priv
->stderr_is_done
= TRUE
;
844 anjuta_launcher_synchronize (launcher
);
847 /* Read next chars if buffer was too small
848 * (the maximum length of one character is 6 bytes) */
849 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
853 if ((condition
& G_IO_ERR
) || (condition
& G_IO_HUP
))
855 DEBUG_PRINT ("%s", "launcher.c: STDERR pipe closed");
856 launcher
->priv
->stderr_is_done
= TRUE
;
857 anjuta_launcher_synchronize (launcher
);
864 anjuta_launcher_scan_pty (GIOChannel
*channel
, GIOCondition condition
,
865 AnjutaLauncher
*launcher
)
868 gchar buffer
[FILE_BUFFER_SIZE
];
871 if (condition
& G_IO_IN
)
876 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
877 if (n
> 0) /* There is stderr output */
880 gchar
*old_str
= launcher
->priv
->pty_output_buffer
;
882 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
885 gchar
*str
= g_strconcat (old_str
, utf8_chars
, NULL
);
886 launcher
->priv
->pty_output_buffer
= str
;
890 launcher
->priv
->pty_output_buffer
= g_strdup (utf8_chars
);
893 /* Ignore illegal characters */
894 if (err
&& err
->domain
== G_CONVERT_ERROR
)
899 /* The pipe is closed on the other side */
900 /* if not related to non blocking read or interrupted syscall */
901 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
905 /* Read next chars if buffer was too small
906 * (the maximum length of one character is 6 bytes) */
907 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
910 if (launcher
->priv
->check_for_passwd_prompt
911 && launcher
->priv
->pty_output_buffer
912 && strlen (launcher
->priv
->pty_output_buffer
) > 0)
914 anjuta_launcher_check_password (launcher
,
915 launcher
->priv
->pty_output_buffer
);
918 /* In pty case, we handle the cases in different invocations */
919 /* Do not hook up for G_IO_HUP */
920 if (condition
& G_IO_ERR
)
922 DEBUG_PRINT ("%s", "launcher.c: PTY pipe error!");
929 anjuta_launcher_execution_done_cleanup (AnjutaLauncher
*launcher
,
930 gboolean emit_signal
)
932 gint child_status
, child_pid
;
935 /* Remove pending timeout */
936 if (launcher
->priv
->completion_check_timeout
!= 0)
937 g_source_remove (launcher
->priv
->completion_check_timeout
);
939 if (launcher
->priv
->stdout_channel
)
941 g_io_channel_shutdown (launcher
->priv
->stdout_channel
, emit_signal
, NULL
);
942 g_io_channel_unref (launcher
->priv
->stdout_channel
);
943 if (!launcher
->priv
->stdout_is_done
)
944 g_source_remove (launcher
->priv
->stdout_watch
);
947 if (launcher
->priv
->stderr_channel
)
949 g_io_channel_shutdown (launcher
->priv
->stderr_channel
, emit_signal
, NULL
);
950 g_io_channel_unref (launcher
->priv
->stderr_channel
);
951 if (!launcher
->priv
->stderr_is_done
)
952 g_source_remove (launcher
->priv
->stderr_watch
);
955 if (launcher
->priv
->pty_channel
)
957 g_io_channel_shutdown (launcher
->priv
->pty_channel
, emit_signal
, NULL
);
958 g_io_channel_unref (launcher
->priv
->pty_channel
);
960 g_source_remove (launcher
->priv
->pty_watch
);
963 if (launcher
->priv
->pty_output_buffer
)
964 g_free (launcher
->priv
->pty_output_buffer
);
965 if (launcher
->priv
->stdout_buffer
)
967 /* Send remaining data if last line is not terminated with EOL */
968 (launcher
->priv
->output_callback
)(launcher
,
969 ANJUTA_LAUNCHER_OUTPUT_STDOUT
,
970 launcher
->priv
->stdout_buffer
,
971 launcher
->priv
->callback_data
);
972 g_free (launcher
->priv
->stdout_buffer
);
974 if (launcher
->priv
->stderr_buffer
)
976 /* Send remaining data if last line is not terminated with EOL */
977 (launcher
->priv
->output_callback
)(launcher
,
978 ANJUTA_LAUNCHER_OUTPUT_STDERR
,
979 launcher
->priv
->stderr_buffer
,
980 launcher
->priv
->callback_data
);
981 g_free (launcher
->priv
->stdout_buffer
);
984 /* Save them before we re-initialize */
985 child_status
= launcher
->priv
->child_status
;
986 child_pid
= launcher
->priv
->child_pid
;
987 start_time
= launcher
->priv
->start_time
;
990 anjuta_launcher_set_busy (launcher
, FALSE
);
992 anjuta_launcher_initialize (launcher
);
995 /* Call this here, after set_busy (FALSE) so we are able to
996 launch a new child from the terminate function.
997 (by clubfan 2002-04-07)
999 /* DEBUG_PRINT ("Exit status: %d", child_status); */
1001 g_signal_emit_by_name (launcher
, "child-exited", child_pid
,
1003 time (NULL
) - start_time
);
1006 /* Using this function is necessary because
1007 * anjuta_launcher_execution_done_cleanup needs to be called in the same
1008 * thread than the gtk main loop */
1010 anjuta_launcher_call_execution_done (gpointer data
)
1012 AnjutaLauncher
*launcher
= data
;
1014 launcher
->priv
->completion_check_timeout
= 0;
1015 anjuta_launcher_execution_done_cleanup (launcher
, TRUE
);
1019 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
1021 anjuta_launcher_check_for_execution_done (gpointer data
)
1023 AnjutaLauncher
*launcher
= data
;
1025 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
1026 launcher->priv->stdout_is_done ? 1 : 0,
1027 launcher->priv->stderr_is_done ? 1 : 0);
1029 if (launcher
->priv
->stdout_is_done
== FALSE
||
1030 launcher
->priv
->stderr_is_done
== FALSE
)
1032 if (launcher
->priv
->child_has_terminated
== FALSE
)
1034 /* DEBUG_PRINT ("%s", "launcher: We missed the exit of the child"); */
1036 launcher
->priv
->completion_check_timeout
= 0;
1037 anjuta_launcher_execution_done_cleanup (launcher
, TRUE
);
1042 anjuta_launcher_child_terminated (GPid pid
, gint status
, gpointer data
)
1044 AnjutaLauncher
*launcher
= data
;
1046 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher
));
1048 /* Save child exit code */
1049 launcher
->priv
->child_status
= status
;
1050 launcher
->priv
->child_has_terminated
= TRUE
;
1051 anjuta_launcher_synchronize (launcher
);
1056 anjuta_launcher_set_encoding_real (AnjutaLauncher
*launcher
, const gchar
*charset
)
1061 g_return_val_if_fail (launcher
!= NULL
, FALSE
);
1062 // charset can be NULL
1064 s
= g_io_channel_set_encoding (launcher
->priv
->stderr_channel
, charset
, NULL
);
1065 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1066 s
= g_io_channel_set_encoding (launcher
->priv
->stdout_channel
, charset
, NULL
);
1067 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1068 s
= g_io_channel_set_encoding (launcher
->priv
->pty_channel
, charset
, NULL
);
1069 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1073 g_warning ("launcher.c: Failed to set channel encoding!");
1080 * anjuta_launcher_set_encoding:
1081 * @launcher: a #AnjutaLancher object.
1082 * @charset: Character set to use for Input/Output with the process.
1084 * Sets the character set to use for Input/Output with the process.
1088 anjuta_launcher_set_encoding (AnjutaLauncher
*launcher
, const gchar
*charset
)
1090 if (launcher
->priv
->custom_encoding
)
1091 g_free (launcher
->priv
->encoding
);
1093 launcher
->priv
->custom_encoding
= TRUE
;
1095 launcher
->priv
->encoding
= g_strdup(charset
);
1097 launcher
->priv
->encoding
= NULL
;
1101 anjuta_launcher_fork (AnjutaLauncher
*launcher
, const gchar
*dir
, gchar
*const args
[], gchar
*const envp
[])
1103 int pty_master_fd
, md
;
1104 int stdout_pipe
[2], stderr_pipe
[2];
1106 struct termios termios_flags
;
1113 /* Fork the command */
1114 child_pid
= forkpty (&pty_master_fd
, NULL
, NULL
, NULL
);
1118 dup (stderr_pipe
[1]);
1120 dup (stdout_pipe
[1]);
1122 /* Close unnecessary pipes */
1123 close (stderr_pipe
[0]);
1124 close (stdout_pipe
[0]);
1127 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1128 perror ("Could not set new controlling tty");
1130 /* Set no delays for the write pipes (non_buffered) so
1131 that we get all the outputs immidiately */
1132 if ((md
= fcntl (stdout_pipe
[1], F_GETFL
)) != -1)
1133 fcntl (stdout_pipe
[1], F_SETFL
, O_SYNC
| md
);
1134 if ((md
= fcntl (stderr_pipe
[1], F_GETFL
)) != -1)
1135 fcntl (stderr_pipe
[1], F_SETFL
, O_SYNC
| md
);
1137 /* Set working directory */
1140 /* Exit if working directory doesn't exist */
1141 if (chdir (dir
) != 0) _exit(-1);
1144 /* Set up environment */
1147 GString
*variable
= g_string_new (NULL
);
1148 for (env
= envp
; *env
!= NULL
; env
++)
1150 gchar
*value
= strchr (*env
, '=');
1154 g_setenv (*env
, NULL
, TRUE
);
1158 g_string_truncate (variable
, 0);
1159 g_string_append_len (variable
, *env
, value
- *env
);
1160 g_setenv (variable
->str
, value
+ 1, TRUE
);
1163 g_string_free (variable
, TRUE
);
1166 execvp (args
[0], args
);
1167 g_warning (_("Cannot execute command: \"%s\""), args
[0]);
1168 perror(_("execvp failed"));
1172 /* Close parent's side pipes */
1173 close (stderr_pipe
[1]);
1174 close (stdout_pipe
[1]);
1178 g_warning ("launcher.c: Fork failed!");
1179 /* Close parent's side pipes */
1180 close (stderr_pipe
[0]);
1181 close (stdout_pipe
[0]);
1186 * Set pipes none blocking, so we can read big buffers
1187 * in the callback without having to use FIONREAD
1188 * to make sure the callback doesn't block.
1190 if ((md
= fcntl (stdout_pipe
[0], F_GETFL
)) != -1)
1191 fcntl (stdout_pipe
[0], F_SETFL
, O_NONBLOCK
| md
);
1192 if ((md
= fcntl (stderr_pipe
[0], F_GETFL
)) != -1)
1193 fcntl (stderr_pipe
[0], F_SETFL
, O_NONBLOCK
| md
);
1194 if ((md
= fcntl (pty_master_fd
, F_GETFL
)) != -1)
1195 fcntl (pty_master_fd
, F_SETFL
, O_NONBLOCK
| md
);
1197 launcher
->priv
->child_pid
= child_pid
;
1198 launcher
->priv
->stderr_channel
= g_io_channel_unix_new (stderr_pipe
[0]);
1199 launcher
->priv
->stdout_channel
= g_io_channel_unix_new (stdout_pipe
[0]);
1200 launcher
->priv
->pty_channel
= g_io_channel_unix_new (pty_master_fd
);
1202 g_io_channel_set_buffer_size (launcher
->priv
->pty_channel
, FILE_INPUT_BUFFER_SIZE
);
1204 if (!launcher
->priv
->custom_encoding
)
1205 g_get_charset ((const gchar
**)&launcher
->priv
->encoding
);
1206 anjuta_launcher_set_encoding_real (launcher
, launcher
->priv
->encoding
);
1208 tcgetattr(pty_master_fd
, &termios_flags
);
1209 termios_flags
.c_iflag
&= ~(IGNPAR
| INPCK
| INLCR
| IGNCR
| ICRNL
| IXON
|
1211 termios_flags
.c_iflag
|= IGNBRK
| BRKINT
| IMAXBEL
| IXANY
;
1212 termios_flags
.c_oflag
&= ~OPOST
;
1213 // termios_flags.c_oflag |= 0;
1214 termios_flags
.c_cflag
&= ~(CSTOPB
| PARENB
| HUPCL
);
1215 termios_flags
.c_cflag
|= CS8
| CLOCAL
;
1217 if (!launcher
->priv
->terminal_echo_on
)
1219 termios_flags
.c_lflag
&= ~(ECHOKE
| ECHOE
| ECHO
| ECHONL
|
1223 ECHOCTL
| ISIG
| ICANON
| IEXTEN
| NOFLSH
| TOSTOP
);
1225 // termios_flags.c_lflag |= 0;
1226 termios_flags
.c_cc
[VMIN
] = 0;
1227 cfsetospeed(&termios_flags
, __MAX_BAUD
);
1228 tcsetattr(pty_master_fd
, TCSANOW
, &termios_flags
);
1230 launcher
->priv
->stderr_watch
=
1231 g_io_add_watch (launcher
->priv
->stderr_channel
,
1232 G_IO_IN
| G_IO_ERR
| G_IO_HUP
,
1233 (GIOFunc
)anjuta_launcher_scan_error
, launcher
);
1234 launcher
->priv
->stdout_watch
=
1235 g_io_add_watch (launcher
->priv
->stdout_channel
,
1236 G_IO_IN
| G_IO_ERR
| G_IO_HUP
,
1237 (GIOFunc
)anjuta_launcher_scan_output
, launcher
);
1238 launcher
->priv
->pty_watch
=
1239 g_io_add_watch (launcher
->priv
->pty_channel
,
1240 G_IO_IN
| G_IO_ERR
, /* Do not hook up for G_IO_HUP */
1241 (GIOFunc
)anjuta_launcher_scan_pty
, launcher
);
1243 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1244 launcher
->priv
->source
= g_child_watch_add (launcher
->priv
->child_pid
,
1245 anjuta_launcher_child_terminated
, launcher
);
1250 * anjuta_launcher_execute_v:
1251 * @launcher: a #AnjutaLancher object.
1252 * @dir: Working directory or %NULL.
1253 * @argv: Command args.
1254 * @envp: Additional environment variable.
1255 * @callback: The callback for delivering output from the process.
1256 * @callback_data: Callback data for the above callback.
1258 * The first of the @args is the command itself. The rest are sent to the
1259 * as it's arguments. This function works similar to anjuta_launcher_execute().
1261 * Return value: %TRUE if successfully launched, otherwise %FALSE.
1264 anjuta_launcher_execute_v (AnjutaLauncher
*launcher
, gchar
*const dir
,
1265 gchar
*const argv
[],
1266 gchar
*const envp
[],
1267 AnjutaLauncherOutputCallback callback
,
1268 gpointer callback_data
)
1270 if (anjuta_launcher_is_busy (launcher
))
1273 anjuta_launcher_set_busy (launcher
, TRUE
);
1275 launcher
->priv
->start_time
= time (NULL
);
1276 launcher
->priv
->child_status
= 0;
1277 launcher
->priv
->stdout_is_done
= FALSE
;
1278 launcher
->priv
->stderr_is_done
= FALSE
;
1279 launcher
->priv
->child_has_terminated
= FALSE
;
1280 launcher
->priv
->output_callback
= callback
;
1281 launcher
->priv
->callback_data
= callback_data
;
1283 /* On a fork error perform a cleanup and return */
1284 if (anjuta_launcher_fork (launcher
, dir
, argv
, envp
) < 0)
1286 anjuta_launcher_initialize (launcher
);
1293 * anjuta_launcher_execute:
1294 * @launcher: a #AnjutaLancher object.
1295 * @command_str: The command to execute.
1296 * @callback: The callback for delivering output from the process.
1297 * @callback_data: Callback data for the above callback.
1299 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1300 * delivered to the above callback. The data are delivered as they arrive
1301 * from the process and could be of any lenght. If the process asks for
1302 * passwords, the user will be automatically prompted with a dialog to enter
1303 * it. Please note that not all formats of the password are recognized. Those
1304 * with the standard 'assword:' substring in the prompt should work well.
1306 * Return value: %TRUE if successfully launched, otherwise %FALSE.
1309 anjuta_launcher_execute (AnjutaLauncher
*launcher
, const gchar
*command_str
,
1310 AnjutaLauncherOutputCallback callback
,
1311 gpointer callback_data
)
1313 GList
*args_list
, *args_list_ptr
;
1314 gchar
**args
, **args_ptr
;
1317 /* Prepare command args */
1318 args_list
= anjuta_util_parse_args_from_string (command_str
);
1319 args
= g_new (char*, g_list_length (args_list
) + 1);
1320 args_list_ptr
= args_list
;
1322 while (args_list_ptr
)
1324 *args_ptr
= (char*) args_list_ptr
->data
;
1325 args_list_ptr
= g_list_next (args_list_ptr
);
1330 ret
= anjuta_launcher_execute_v (launcher
, NULL
, args
, NULL
,
1331 callback
, callback_data
);
1333 anjuta_util_glist_strings_free (args_list
);
1338 * anjuta_launcher_set_buffered_output:
1339 * @launcher: a #AnjutaLancher object.
1340 * @buffered: buffer output.
1342 * Sets if output should buffered or not. By default, it is buffered.
1344 * Return value: Previous flag value
1347 anjuta_launcher_set_buffered_output (AnjutaLauncher
*launcher
, gboolean buffered
)
1349 gboolean past_value
= launcher
->priv
->buffered_output
;
1350 launcher
->priv
->buffered_output
= buffered
;
1355 * anjuta_launcher_set_check_passwd_prompt:
1356 * @launcher: a #AnjutaLancher object.
1357 * @check_passwd: check for password.
1359 * Set if output is checked for a password prompti. A special dialog box
1360 * is use to enter it in this case. By default, this behavior is enabled.
1362 * Return value: Previous flag value
1365 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher
*launcher
, gboolean check_passwd
)
1367 gboolean past_value
= launcher
->priv
->check_for_passwd_prompt
;
1368 launcher
->priv
->check_for_passwd_prompt
= check_passwd
;
1373 * anjuta_launcher_set_terminal_echo:
1374 * @launcher: a #AnjutaLancher object.
1375 * @echo_on: Echo ON flag.
1377 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1380 * Return value: Previous flag value
1383 anjuta_launcher_set_terminal_echo (AnjutaLauncher
*launcher
,
1386 gboolean past_value
= launcher
->priv
->terminal_echo_on
;
1387 launcher
->priv
->terminal_echo_on
= echo_on
;
1392 * anjuta_launcher_set_terminate_on_exit:
1393 * @launcher: a #AnjutaLancher object.
1394 * @terminate_on_exit: terminate on exit flag
1396 * When this flag is set, al i/o channels are closed and the child-exit
1397 * signal is emitted as soon as the child exit. By default, or when this
1398 * flag is clear, the launcher object wait until the i/o channels are
1401 * Return value: Previous flag value
1404 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher
*launcher
,
1405 gboolean terminate_on_exit
)
1407 gboolean past_value
= launcher
->priv
->terminate_on_exit
;
1408 launcher
->priv
->terminate_on_exit
= terminate_on_exit
;
1413 * anjuta_launcher_new:
1415 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1418 * Return value: a new instance of #AnjutaLancher class.
1421 anjuta_launcher_new ()
1423 return g_object_new (ANJUTA_TYPE_LAUNCHER
, NULL
);