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., 675 Mass Ave, Cambridge, MA 02139, 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 1048576
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, otherwisee 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:
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
)
428 g_return_if_fail (launcher
);
429 g_return_if_fail (input_str
);
431 if (strlen (input_str
) == 0)
436 g_io_channel_write_chars (launcher
->priv
->pty_channel
,
437 input_str
, strlen (input_str
),
438 &bytes_written
, &err
);
439 g_io_channel_flush (launcher
->priv
->pty_channel
, NULL
);
442 g_warning ("Error encountered while writing to PTY!. %s",
448 input_str
+= bytes_written
;
454 * anjuta_launcher_reset:
455 * @launcher: a #AnjutaLancher object.
457 * Resets the launcher and kills (SIGTERM) current process, if it is still
461 anjuta_launcher_reset (AnjutaLauncher
*launcher
)
463 if (anjuta_launcher_is_busy (launcher
))
464 kill (launcher
->priv
->child_pid
, SIGTERM
);
468 * anjuta_launcher_signal:
469 * @launcher: a #AnjutaLancher object.
470 * @sig: kernel signal ID (e.g. SIGTERM).
472 * Sends a kernel signal to the process that is being executed.
475 anjuta_launcher_signal (AnjutaLauncher
*launcher
, int sig
)
477 kill (launcher
->priv
->child_pid
, sig
);
481 * anjuta_launcher_get_child_pid:
482 * @launcher: a #AnjutaLancher object.
484 * Gets the Process ID of the child being executed.
486 * Return value: Process ID of the child.
489 anjuta_launcher_get_child_pid (AnjutaLauncher
*launcher
)
491 if (anjuta_launcher_is_busy (launcher
))
492 return launcher
->priv
->child_pid
;
498 anjuta_launcher_synchronize (AnjutaLauncher
*launcher
)
500 if (launcher
->priv
->child_has_terminated
&&
501 launcher
->priv
->stdout_is_done
&&
502 launcher
->priv
->stderr_is_done
)
504 if (launcher
->priv
->completion_check_timeout
!= 0)
505 g_source_remove (launcher
->priv
->completion_check_timeout
);
506 launcher
->priv
->completion_check_timeout
=
507 /* Use a low priority timer to make sure all pending I/O are flushed out */
508 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE
, 50, anjuta_launcher_check_for_execution_done
,
512 /* This case is not very good, but it blocks the whole IDE
513 because we never new if the child has finished */
514 else if (launcher
->priv
->stdout_is_done
&&
515 launcher
->priv
->stderr_is_done
)
517 /* DEBUG_PRINT ("%s", "Child has't exited yet waiting for 200ms"); */
518 if (launcher
->priv
->completion_check_timeout
!= 0)
519 g_source_remove (launcher
->priv
->completion_check_timeout
);
520 launcher
->priv
->completion_check_timeout
=
521 /* Use a low priority timer to make sure all pending I/O are flushed out */
522 g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE
, 200, anjuta_launcher_check_for_execution_done
,
525 /* Add this case for gdb. It creates child inheriting gdb
526 * pipes which are not closed if gdb crashes */
527 else if (launcher
->priv
->child_has_terminated
&&
528 launcher
->priv
->terminate_on_exit
)
530 if (launcher
->priv
->completion_check_timeout
!= 0)
531 g_source_remove (launcher
->priv
->completion_check_timeout
);
532 launcher
->priv
->completion_check_timeout
=
533 /* Use a low priority timer to make sure all pending I/O are flushed out */
534 g_idle_add ( anjuta_launcher_call_execution_done
,
539 /* Password dialog */
541 create_password_dialog (const gchar
* prompt
)
550 g_return_val_if_fail (prompt
, NULL
);
552 dialog
= gtk_dialog_new_with_buttons (prompt
,
553 NULL
, //FIXME: Pass the parent window here
554 // for transient purpose.
555 GTK_DIALOG_DESTROY_WITH_PARENT
,
556 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
557 GTK_STOCK_OK
, GTK_RESPONSE_OK
, NULL
);
558 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
560 gtk_window_set_wmclass (GTK_WINDOW (dialog
), "launcher-password-prompt",
562 hbox
= gtk_hbox_new (FALSE
, 10);
563 gtk_widget_show (hbox
);
564 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG(dialog
))), hbox
);
566 icon
= anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD
);
567 gtk_widget_show (icon
);
568 gtk_box_pack_start (GTK_BOX(hbox
), icon
, TRUE
, TRUE
, 0);
570 if (strlen (prompt
) < 20) {
571 box
= gtk_hbox_new (FALSE
, 5);
573 box
= gtk_vbox_new (FALSE
, 5);
575 gtk_widget_show (box
);
576 gtk_box_pack_start (GTK_BOX (hbox
), box
, TRUE
, TRUE
, 0);
578 label
= gtk_label_new (_(prompt
));
579 gtk_widget_show (label
);
580 gtk_box_pack_start (GTK_BOX (box
), label
, FALSE
, FALSE
, 0);
582 entry
= gtk_entry_new ();
583 gtk_widget_show (entry
);
584 gtk_entry_set_visibility (GTK_ENTRY (entry
), FALSE
);
585 gtk_box_pack_start (GTK_BOX (box
), entry
, FALSE
, FALSE
, 0);
587 g_object_ref (entry
);
588 g_object_set_data_full (G_OBJECT (dialog
), "password_entry",
589 g_object_ref (entry
),
591 gtk_widget_grab_focus (entry
);
592 gtk_entry_set_activates_default (GTK_ENTRY (entry
), TRUE
);
597 /* pty buffer check for password authentication */
599 anjuta_launcher_check_password_real (AnjutaLauncher
*launcher
,
600 const gchar
* last_line
)
602 if (anjuta_launcher_is_busy (launcher
) == FALSE
)
607 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
608 if (is_password_prompt(last_line
)) {
609 /* Password prompt detected */
615 dialog
= create_password_dialog (last_line
);
616 button
= gtk_dialog_run (GTK_DIALOG(dialog
));
618 case GTK_RESPONSE_OK
:
619 passwd
= gtk_entry_get_text (
620 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog
),
622 line
= g_strconcat (passwd
, "\n", NULL
);
623 anjuta_launcher_send_ptyin (launcher
, line
);
626 case GTK_RESPONSE_CANCEL
:
627 anjuta_launcher_reset (launcher
);
632 gtk_widget_destroy (dialog
);
638 anjuta_launcher_check_password (AnjutaLauncher
*launcher
, const gchar
*chars
)
643 if (!chars
|| strlen(chars
) <= 0)
646 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
647 start
= end
= strlen (chars
);
648 while (start
> 0 && chars
[start
-1] != '\n') start
--;
652 last_line
= g_strndup (&chars
[start
], end
- start
+ 1);
654 /* DEBUG_PRINT ("Last line = %s", last_line); */
655 /* Checks for password, again */
656 anjuta_launcher_check_password_real (launcher
, last_line
);
662 is_password_prompt (const gchar
* line
)
664 const gchar
* password
= "assword";
665 const gchar
* passphrase
= "assphrase";
667 if (strlen (line
) < strlen (password
)
668 || strlen (line
) < strlen (passphrase
))
671 if (g_strstr_len(line
, 80, password
) != NULL
672 || g_strstr_len(line
, 80, passphrase
) != NULL
)
675 for (i
= strlen(line
) - 1; i
!= 0; --i
)
679 if (g_ascii_isspace(line
[i
]))
689 anjuta_launcher_buffered_output (AnjutaLauncher
*launcher
,
690 AnjutaLauncherOutputType output_type
,
694 gchar
*incomplete_line
;
697 g_return_if_fail (chars
!= NULL
);
698 g_return_if_fail (strlen (chars
) > 0);
700 if (launcher
->priv
->output_callback
== NULL
)
702 if (launcher
->priv
->buffered_output
== FALSE
)
704 (launcher
->priv
->output_callback
)(launcher
, output_type
, chars
,
705 launcher
->priv
->callback_data
);
710 case ANJUTA_LAUNCHER_OUTPUT_STDOUT
:
711 buffer
= &launcher
->priv
->stdout_buffer
;
713 case ANJUTA_LAUNCHER_OUTPUT_STDERR
:
714 buffer
= &launcher
->priv
->stderr_buffer
;
717 g_warning ("Should not reach here");
721 all_lines
= g_strconcat (*buffer
, chars
, NULL
);
723 all_lines
= g_strdup (chars
);
725 /* Buffer the last incomplete line */
726 incomplete_line
= all_lines
+ strlen (all_lines
);
727 while (incomplete_line
> all_lines
&&
728 *incomplete_line
!= '\n')
730 incomplete_line
= g_utf8_prev_char (incomplete_line
);
732 if (*incomplete_line
== '\n')
735 /* Update line buffer */
738 if (strlen(incomplete_line
))
740 *buffer
= g_strdup (incomplete_line
);
741 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
743 /* Check for password prompt */
744 if (launcher
->priv
->check_for_passwd_prompt
)
745 anjuta_launcher_check_password (launcher
, incomplete_line
);
747 /* Deliver complete lines */
748 *incomplete_line
= '\0';
749 if (strlen (all_lines
) > 0)
750 (launcher
->priv
->output_callback
)(launcher
, output_type
, all_lines
,
751 launcher
->priv
->callback_data
);
756 anjuta_launcher_scan_output (GIOChannel
*channel
, GIOCondition condition
,
757 AnjutaLauncher
*launcher
)
760 gchar buffer
[FILE_BUFFER_SIZE
];
763 if (condition
& G_IO_IN
)
768 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
769 if (n
> 0) /* There is output */
771 gchar
*utf8_chars
= NULL
;
773 if (!launcher
->priv
->custom_encoding
)
774 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
776 utf8_chars
= g_strdup(buffer
);
777 anjuta_launcher_buffered_output (launcher
,
778 ANJUTA_LAUNCHER_OUTPUT_STDOUT
,
782 /* Ignore illegal characters */
783 if (err
&& err
->domain
== G_CONVERT_ERROR
)
788 /* The pipe is closed on the other side */
789 /* if not related to non blocking read or interrupted syscall */
790 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
792 launcher
->priv
->stdout_is_done
= TRUE
;
793 anjuta_launcher_synchronize (launcher
);
796 /* Read next chars if buffer was too small
797 * (the maximum length of one character is 6 bytes) */
798 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
802 if ((condition
& G_IO_ERR
) || (condition
& G_IO_HUP
))
804 DEBUG_PRINT ("%s", "launcher.c: STDOUT pipe closed");
805 launcher
->priv
->stdout_is_done
= TRUE
;
806 anjuta_launcher_synchronize (launcher
);
813 anjuta_launcher_scan_error (GIOChannel
*channel
, GIOCondition condition
,
814 AnjutaLauncher
*launcher
)
817 gchar buffer
[FILE_BUFFER_SIZE
];
820 if (condition
& G_IO_IN
)
825 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
826 if (n
> 0) /* There is stderr output */
830 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
831 anjuta_launcher_buffered_output (launcher
,
832 ANJUTA_LAUNCHER_OUTPUT_STDERR
,
836 /* Ignore illegal characters */
837 if (err
&& err
->domain
== G_CONVERT_ERROR
)
842 /* The pipe is closed on the other side */
843 /* if not related to non blocking read or interrupted syscall */
844 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
847 launcher
->priv
->stderr_is_done
= TRUE
;
848 anjuta_launcher_synchronize (launcher
);
851 /* Read next chars if buffer was too small
852 * (the maximum length of one character is 6 bytes) */
853 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
857 if ((condition
& G_IO_ERR
) || (condition
& G_IO_HUP
))
859 DEBUG_PRINT ("%s", "launcher.c: STDERR pipe closed");
860 launcher
->priv
->stderr_is_done
= TRUE
;
861 anjuta_launcher_synchronize (launcher
);
868 anjuta_launcher_scan_pty (GIOChannel
*channel
, GIOCondition condition
,
869 AnjutaLauncher
*launcher
)
872 gchar buffer
[FILE_BUFFER_SIZE
];
875 if (condition
& G_IO_IN
)
880 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
881 if (n
> 0) /* There is stderr output */
884 gchar
*old_str
= launcher
->priv
->pty_output_buffer
;
886 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
889 gchar
*str
= g_strconcat (old_str
, utf8_chars
, NULL
);
890 launcher
->priv
->pty_output_buffer
= str
;
894 launcher
->priv
->pty_output_buffer
= g_strdup (utf8_chars
);
897 /* Ignore illegal characters */
898 if (err
&& err
->domain
== G_CONVERT_ERROR
)
903 /* The pipe is closed on the other side */
904 /* if not related to non blocking read or interrupted syscall */
905 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
909 /* Read next chars if buffer was too small
910 * (the maximum length of one character is 6 bytes) */
911 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
914 if (launcher
->priv
->check_for_passwd_prompt
915 && launcher
->priv
->pty_output_buffer
916 && strlen (launcher
->priv
->pty_output_buffer
) > 0)
918 anjuta_launcher_check_password (launcher
,
919 launcher
->priv
->pty_output_buffer
);
922 /* In pty case, we handle the cases in different invocations */
923 /* Do not hook up for G_IO_HUP */
924 if (condition
& G_IO_ERR
)
926 DEBUG_PRINT ("%s", "launcher.c: PTY pipe error!");
933 anjuta_launcher_execution_done_cleanup (AnjutaLauncher
*launcher
,
934 gboolean emit_signal
)
936 gint child_status
, child_pid
;
939 /* Remove pending timeout */
940 if (launcher
->priv
->completion_check_timeout
!= 0)
941 g_source_remove (launcher
->priv
->completion_check_timeout
);
943 if (launcher
->priv
->stdout_channel
)
945 g_io_channel_shutdown (launcher
->priv
->stdout_channel
, emit_signal
, NULL
);
946 g_io_channel_unref (launcher
->priv
->stdout_channel
);
947 g_source_remove (launcher
->priv
->stdout_watch
);
950 if (launcher
->priv
->stderr_channel
)
952 g_io_channel_shutdown (launcher
->priv
->stderr_channel
, emit_signal
, NULL
);
953 g_io_channel_unref (launcher
->priv
->stderr_channel
);
954 g_source_remove (launcher
->priv
->stderr_watch
);
957 if (launcher
->priv
->pty_channel
)
959 g_io_channel_shutdown (launcher
->priv
->pty_channel
, emit_signal
, NULL
);
960 g_io_channel_unref (launcher
->priv
->pty_channel
);
962 g_source_remove (launcher
->priv
->pty_watch
);
965 if (launcher
->priv
->pty_output_buffer
)
966 g_free (launcher
->priv
->pty_output_buffer
);
967 if (launcher
->priv
->stdout_buffer
)
969 /* Send remaining data if last line is not terminated with EOL */
970 (launcher
->priv
->output_callback
)(launcher
,
971 ANJUTA_LAUNCHER_OUTPUT_STDOUT
,
972 launcher
->priv
->stdout_buffer
,
973 launcher
->priv
->callback_data
);
974 g_free (launcher
->priv
->stdout_buffer
);
976 if (launcher
->priv
->stderr_buffer
)
978 /* Send remaining data if last line is not terminated with EOL */
979 (launcher
->priv
->output_callback
)(launcher
,
980 ANJUTA_LAUNCHER_OUTPUT_STDERR
,
981 launcher
->priv
->stderr_buffer
,
982 launcher
->priv
->callback_data
);
983 g_free (launcher
->priv
->stdout_buffer
);
986 /* Save them before we re-initialize */
987 child_status
= launcher
->priv
->child_status
;
988 child_pid
= launcher
->priv
->child_pid
;
989 start_time
= launcher
->priv
->start_time
;
992 anjuta_launcher_set_busy (launcher
, FALSE
);
994 anjuta_launcher_initialize (launcher
);
997 /* Call this here, after set_busy (FALSE) so we are able to
998 launch a new child from the terminate function.
999 (by clubfan 2002-04-07)
1001 /* DEBUG_PRINT ("Exit status: %d", child_status); */
1003 g_signal_emit_by_name (launcher
, "child-exited", child_pid
,
1005 time (NULL
) - start_time
);
1008 /* Using this function is necessary because
1009 * anjuta_launcher_execution_done_cleanup needs to be called in the same
1010 * thread than the gtk main loop */
1012 anjuta_launcher_call_execution_done (gpointer data
)
1014 AnjutaLauncher
*launcher
= data
;
1016 launcher
->priv
->completion_check_timeout
= 0;
1017 anjuta_launcher_execution_done_cleanup (launcher
, TRUE
);
1021 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
1023 anjuta_launcher_check_for_execution_done (gpointer data
)
1025 AnjutaLauncher
*launcher
= data
;
1027 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
1028 launcher->priv->stdout_is_done ? 1 : 0,
1029 launcher->priv->stderr_is_done ? 1 : 0);
1031 if (launcher
->priv
->stdout_is_done
== FALSE
||
1032 launcher
->priv
->stderr_is_done
== FALSE
)
1034 if (launcher
->priv
->child_has_terminated
== FALSE
)
1036 /* DEBUG_PRINT ("%s", "launcher: We missed the exit of the child"); */
1038 launcher
->priv
->completion_check_timeout
= 0;
1039 anjuta_launcher_execution_done_cleanup (launcher
, TRUE
);
1044 anjuta_launcher_child_terminated (GPid pid
, gint status
, gpointer data
)
1046 AnjutaLauncher
*launcher
= data
;
1048 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher
));
1050 /* Save child exit code */
1051 launcher
->priv
->child_status
= status
;
1052 launcher
->priv
->child_has_terminated
= TRUE
;
1053 anjuta_launcher_synchronize (launcher
);
1058 anjuta_launcher_set_encoding_real (AnjutaLauncher
*launcher
, const gchar
*charset
)
1063 g_return_val_if_fail (launcher
!= NULL
, FALSE
);
1064 // charset can be NULL
1066 s
= g_io_channel_set_encoding (launcher
->priv
->stderr_channel
, charset
, NULL
);
1067 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1068 s
= g_io_channel_set_encoding (launcher
->priv
->stdout_channel
, charset
, NULL
);
1069 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1070 s
= g_io_channel_set_encoding (launcher
->priv
->pty_channel
, charset
, NULL
);
1071 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1075 g_warning ("launcher.c: Failed to set channel encoding!");
1082 * anjuta_launcher_set_encoding:
1083 * @launcher: a #AnjutaLancher object.
1084 * @charset: Character set to use for Input/Output with the process.
1086 * Sets the character set to use for Input/Output with the process.
1090 anjuta_launcher_set_encoding (AnjutaLauncher
*launcher
, const gchar
*charset
)
1092 if (launcher
->priv
->custom_encoding
)
1093 g_free (launcher
->priv
->encoding
);
1095 launcher
->priv
->custom_encoding
= TRUE
;
1097 launcher
->priv
->encoding
= g_strdup(charset
);
1099 launcher
->priv
->encoding
= NULL
;
1103 anjuta_launcher_fork (AnjutaLauncher
*launcher
, const gchar
*dir
, gchar
*const args
[], gchar
*const envp
[])
1105 int pty_master_fd
, md
;
1106 int stdout_pipe
[2], stderr_pipe
[2];
1108 struct termios termios_flags
;
1115 /* Fork the command */
1116 child_pid
= forkpty (&pty_master_fd
, NULL
, NULL
, NULL
);
1120 dup (stderr_pipe
[1]);
1122 dup (stdout_pipe
[1]);
1124 /* Close unnecessary pipes */
1125 close (stderr_pipe
[0]);
1126 close (stdout_pipe
[0]);
1129 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1130 perror ("Could not set new controlling tty");
1132 /* Set no delays for the write pipes (non_buffered) so
1133 that we get all the outputs immidiately */
1134 if ((md
= fcntl (stdout_pipe
[1], F_GETFL
)) != -1)
1135 fcntl (stdout_pipe
[1], F_SETFL
, O_SYNC
| md
);
1136 if ((md
= fcntl (stderr_pipe
[1], F_GETFL
)) != -1)
1137 fcntl (stderr_pipe
[1], F_SETFL
, O_SYNC
| md
);
1139 /* Set working directory */
1145 /* Set up environment */
1148 GString
*variable
= g_string_new (NULL
);
1149 for (env
= envp
; *env
!= NULL
; env
++)
1151 gchar
*value
= strchr (*env
, '=');
1155 g_setenv (*env
, NULL
, TRUE
);
1159 g_string_truncate (variable
, 0);
1160 g_string_append_len (variable
, *env
, value
- *env
);
1161 g_setenv (variable
->str
, value
+ 1, TRUE
);
1164 g_string_free (variable
, TRUE
);
1167 execvp (args
[0], args
);
1168 g_warning (_("Cannot execute command: \"%s\""), args
[0]);
1169 perror(_("execvp failed"));
1173 /* Close parent's side pipes */
1174 close (stderr_pipe
[1]);
1175 close (stdout_pipe
[1]);
1179 g_warning ("launcher.c: Fork failed!");
1180 /* Close parent's side pipes */
1181 close (stderr_pipe
[0]);
1182 close (stdout_pipe
[0]);
1187 * Set pipes none blocking, so we can read big buffers
1188 * in the callback without having to use FIONREAD
1189 * to make sure the callback doesn't block.
1191 if ((md
= fcntl (stdout_pipe
[0], F_GETFL
)) != -1)
1192 fcntl (stdout_pipe
[0], F_SETFL
, O_NONBLOCK
| md
);
1193 if ((md
= fcntl (stderr_pipe
[0], F_GETFL
)) != -1)
1194 fcntl (stderr_pipe
[0], F_SETFL
, O_NONBLOCK
| md
);
1195 if ((md
= fcntl (pty_master_fd
, F_GETFL
)) != -1)
1196 fcntl (pty_master_fd
, F_SETFL
, O_NONBLOCK
| md
);
1198 launcher
->priv
->child_pid
= child_pid
;
1199 launcher
->priv
->stderr_channel
= g_io_channel_unix_new (stderr_pipe
[0]);
1200 launcher
->priv
->stdout_channel
= g_io_channel_unix_new (stdout_pipe
[0]);
1201 launcher
->priv
->pty_channel
= g_io_channel_unix_new (pty_master_fd
);
1203 g_io_channel_set_buffer_size (launcher
->priv
->pty_channel
, FILE_INPUT_BUFFER_SIZE
);
1205 if (!launcher
->priv
->custom_encoding
)
1206 g_get_charset ((const gchar
**)&launcher
->priv
->encoding
);
1207 anjuta_launcher_set_encoding_real (launcher
, launcher
->priv
->encoding
);
1209 tcgetattr(pty_master_fd
, &termios_flags
);
1210 termios_flags
.c_iflag
&= ~(IGNPAR
| INPCK
| INLCR
| IGNCR
| ICRNL
| IXON
|
1212 termios_flags
.c_iflag
|= IGNBRK
| BRKINT
| IMAXBEL
| IXANY
;
1213 termios_flags
.c_oflag
&= ~OPOST
;
1214 // termios_flags.c_oflag |= 0;
1215 termios_flags
.c_cflag
&= ~(CSTOPB
| PARENB
| HUPCL
);
1216 termios_flags
.c_cflag
|= CS8
| CLOCAL
;
1218 if (!launcher
->priv
->terminal_echo_on
)
1220 termios_flags
.c_lflag
&= ~(ECHOKE
| ECHOE
| ECHO
| ECHONL
|
1224 ECHOCTL
| ISIG
| ICANON
| IEXTEN
| NOFLSH
| TOSTOP
);
1226 // termios_flags.c_lflag |= 0;
1227 termios_flags
.c_cc
[VMIN
] = 0;
1228 cfsetospeed(&termios_flags
, __MAX_BAUD
);
1229 tcsetattr(pty_master_fd
, TCSANOW
, &termios_flags
);
1231 launcher
->priv
->stderr_watch
=
1232 g_io_add_watch (launcher
->priv
->stderr_channel
,
1233 G_IO_IN
| G_IO_ERR
| G_IO_HUP
,
1234 (GIOFunc
)anjuta_launcher_scan_error
, launcher
);
1235 launcher
->priv
->stdout_watch
=
1236 g_io_add_watch (launcher
->priv
->stdout_channel
,
1237 G_IO_IN
| G_IO_ERR
| G_IO_HUP
,
1238 (GIOFunc
)anjuta_launcher_scan_output
, launcher
);
1239 launcher
->priv
->pty_watch
=
1240 g_io_add_watch (launcher
->priv
->pty_channel
,
1241 G_IO_IN
| G_IO_ERR
, /* Do not hook up for G_IO_HUP */
1242 (GIOFunc
)anjuta_launcher_scan_pty
, launcher
);
1244 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1245 launcher
->priv
->source
= g_child_watch_add (launcher
->priv
->child_pid
,
1246 anjuta_launcher_child_terminated
, launcher
);
1251 * anjuta_launcher_execute_v:
1252 * @launcher: a #AnjutaLancher object.
1253 * @dir: Working directory or NULL.
1254 * @argv: Command args.
1255 * @envp: Additional environment variable.
1256 * @callback: The callback for delivering output from the process.
1257 * @callback_data: Callback data for the above callback.
1259 * The first of the @args is the command itself. The rest are sent to the
1260 * as it's arguments. This function works similar to anjuta_launcher_execute().
1262 * Return value: TRUE if successfully launched, otherwise FALSE.
1265 anjuta_launcher_execute_v (AnjutaLauncher
*launcher
, gchar
*const dir
,
1266 gchar
*const argv
[],
1267 gchar
*const envp
[],
1268 AnjutaLauncherOutputCallback callback
,
1269 gpointer callback_data
)
1271 if (anjuta_launcher_is_busy (launcher
))
1274 anjuta_launcher_set_busy (launcher
, TRUE
);
1276 launcher
->priv
->start_time
= time (NULL
);
1277 launcher
->priv
->child_status
= 0;
1278 launcher
->priv
->stdout_is_done
= FALSE
;
1279 launcher
->priv
->stderr_is_done
= FALSE
;
1280 launcher
->priv
->child_has_terminated
= FALSE
;
1281 launcher
->priv
->output_callback
= callback
;
1282 launcher
->priv
->callback_data
= callback_data
;
1284 /* On a fork error perform a cleanup and return */
1285 if (anjuta_launcher_fork (launcher
, dir
, argv
, envp
) < 0)
1287 anjuta_launcher_initialize (launcher
);
1294 * anjuta_launcher_execute:
1295 * @launcher: a #AnjutaLancher object.
1296 * @command_str: The command to execute.
1297 * @callback: The callback for delivering output from the process.
1298 * @callback_data: Callback data for the above callback.
1300 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1301 * delivered to the above callback. The data are delivered as they arrive
1302 * from the process and could be of any lenght. If the process asks for
1303 * passwords, the user will be automatically prompted with a dialog to enter
1304 * it. Please note that not all formats of the password are recognized. Those
1305 * with the standard 'assword:' substring in the prompt should work well.
1307 * Return value: TRUE if successfully launched, otherwise FALSE.
1310 anjuta_launcher_execute (AnjutaLauncher
*launcher
, const gchar
*command_str
,
1311 AnjutaLauncherOutputCallback callback
,
1312 gpointer callback_data
)
1314 GList
*args_list
, *args_list_ptr
;
1315 gchar
**args
, **args_ptr
;
1318 /* Prepare command args */
1319 args_list
= anjuta_util_parse_args_from_string (command_str
);
1320 args
= g_new (char*, g_list_length (args_list
) + 1);
1321 args_list_ptr
= args_list
;
1323 while (args_list_ptr
)
1325 *args_ptr
= (char*) args_list_ptr
->data
;
1326 args_list_ptr
= g_list_next (args_list_ptr
);
1331 ret
= anjuta_launcher_execute_v (launcher
, NULL
, args
, NULL
,
1332 callback
, callback_data
);
1334 anjuta_util_glist_strings_free (args_list
);
1339 * anjuta_launcher_set_buffered_output:
1340 * @launcher: a #AnjutaLancher object.
1341 * @buffered: buffer output.
1343 * Sets if output should buffered or not. By default, it is buffered.
1345 * Return value: Previous flag value
1348 anjuta_launcher_set_buffered_output (AnjutaLauncher
*launcher
, gboolean buffered
)
1350 gboolean past_value
= launcher
->priv
->buffered_output
;
1351 launcher
->priv
->buffered_output
= buffered
;
1356 * anjuta_launcher_set_check_passwd_prompt:
1357 * @launcher: a #AnjutaLancher object.
1358 * @check_passwd: check for password.
1360 * Set if output is checked for a password prompti. A special dialog box
1361 * is use to enter it in this case. By default, this behavior is enabled.
1363 * Return value: Previous flag value
1366 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher
*launcher
, gboolean check_passwd
)
1368 gboolean past_value
= launcher
->priv
->check_for_passwd_prompt
;
1369 launcher
->priv
->check_for_passwd_prompt
= check_passwd
;
1374 * anjuta_launcher_set_terminal_echo:
1375 * @launcher: a #AnjutaLancher object.
1376 * @echo_on: Echo ON flag.
1378 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1381 * Return value: Previous flag value
1384 anjuta_launcher_set_terminal_echo (AnjutaLauncher
*launcher
,
1387 gboolean past_value
= launcher
->priv
->terminal_echo_on
;
1388 launcher
->priv
->terminal_echo_on
= echo_on
;
1393 * anjuta_launcher_set_terminate_on_exit:
1394 * @launcher: a #AnjutaLancher object.
1395 * @terminate_on_exit: terminate on exit flag
1397 * When this flag is set, al i/o channels are closed and the child-exit
1398 * signal is emitted as soon as the child exit. By default, or when this
1399 * flag is clear, the launcher object wait until the i/o channels are
1402 * Return value: Previous flag value
1405 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher
*launcher
,
1406 gboolean terminate_on_exit
)
1408 gboolean past_value
= launcher
->priv
->terminate_on_exit
;
1409 launcher
->priv
->terminate_on_exit
= terminate_on_exit
;
1414 * anjuta_launcher_new:
1416 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1419 * Return value: a new instance of #AnjutaLancher class.
1422 anjuta_launcher_new ()
1424 return g_object_new (ANJUTA_TYPE_LAUNCHER
, NULL
);