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 #if !defined(__sun) && !defined(__NetBSD__)
46 #include "anjuta-utils-priv.h"
53 #include <glib/gi18n.h>
56 #include <libgnome/gnome-macros.h>
58 #include "anjuta-children.h"
59 #include "anjuta-utils.h"
60 #include "anjuta-marshal.h"
61 #include "resources.h"
62 #include "anjuta-launcher.h"
63 #include "anjuta-debug.h"
65 #define ANJUTA_PIXMAP_PASSWORD "password.png"
66 #define FILE_BUFFER_SIZE 1024
67 #define FILE_INPUT_BUFFER_SIZE 1048576
70 #define __MAX_BAUD B256000
72 #define __MAX_BAUD B460800
78 anjuta_launcher_pty_check_child_exit_code (AnjutaLauncher *launcher,
81 struct _AnjutaLauncherPriv
84 * Busy flag is TRUE if the Launcher
85 * is currently executing a child.
89 /* These flags are used to synchronize the IO operations. */
90 gboolean stdout_is_done
;
91 gboolean stderr_is_done
;
94 GIOChannel
*stdout_channel
;
95 GIOChannel
*stderr_channel
;
96 /*GIOChannel *stdin_channel;*/
97 GIOChannel
*pty_channel
;
99 /* GIO watch handles */
104 /* Output line buffers */
105 gchar
*stdout_buffer
;
106 gchar
*stderr_buffer
;
108 /* Output of the pty is constantly stored here.*/
109 gchar
*pty_output_buffer
;
112 gboolean terminal_echo_on
;
117 gboolean child_has_terminated
;
119 /* Synchronization in progress */
121 guint completion_check_timeout
;
123 /* Terminate child on child exit */
124 gboolean terminate_on_exit
;
126 /* Start time of execution */
129 /* Should the outputs be buffered */
130 gboolean buffered_output
;
132 /* Should we check for password prompts in stdout and pty */
133 gboolean check_for_passwd_prompt
;
135 /* Output callback */
136 AnjutaLauncherOutputCallback output_callback
;
139 gpointer callback_data
;
144 /* OUTPUT_ARRIVED_SIGNAL, */
150 static void anjuta_launcher_class_init (AnjutaLauncherClass
* klass
);
151 static void anjuta_launcher_init (AnjutaLauncher
* obj
);
152 static gboolean
anjuta_launcher_call_execution_done (gpointer data
);
153 static gboolean
anjuta_launcher_check_for_execution_done (gpointer data
);
154 static void anjuta_launcher_execution_done_cleanup (AnjutaLauncher
*launcher
,
155 gboolean emit_signal
);
157 static gboolean
is_password_prompt(const gchar
* line
);
159 static guint launcher_signals
[LAST_SIGNAL
] = { 0 };
160 static AnjutaLauncherClass
*parent_class
;
163 anjuta_launcher_initialize (AnjutaLauncher
*obj
)
166 obj
->priv
->busy
= FALSE
;
168 /* These flags are used to synchronize the IO operations. */
169 obj
->priv
->stdout_is_done
= FALSE
;
170 obj
->priv
->stderr_is_done
= FALSE
;
173 obj
->priv
->stdout_channel
= NULL
;
174 obj
->priv
->stderr_channel
= NULL
;
175 obj
->priv
->pty_channel
= NULL
;
177 /* Output line buffers */
178 obj
->priv
->stdout_buffer
= NULL
;
179 obj
->priv
->stderr_buffer
= NULL
;
182 obj
->priv
->pty_output_buffer
= NULL
;
184 obj
->priv
->terminal_echo_on
= TRUE
;
187 obj
->priv
->child_pid
= 0;
188 obj
->priv
->child_status
= -1;
189 obj
->priv
->child_has_terminated
= TRUE
;
191 /* Synchronization in progress */
192 obj
->priv
->in_cleanup
= FALSE
;
193 obj
->priv
->completion_check_timeout
= -1;
195 /* Terminate child on child exit */
196 obj
->priv
->terminate_on_exit
= FALSE
;
198 /* Start time of execution */
199 obj
->priv
->start_time
= 0;
201 obj
->priv
->buffered_output
= TRUE
;
202 obj
->priv
->check_for_passwd_prompt
= TRUE
;
204 /* Output callback */
205 obj
->priv
->output_callback
= NULL
;
206 obj
->priv
->callback_data
= NULL
;
210 anjuta_launcher_get_type ()
212 static GType obj_type
= 0;
216 static const GTypeInfo obj_info
=
218 sizeof (AnjutaLauncherClass
),
219 (GBaseInitFunc
) NULL
,
220 (GBaseFinalizeFunc
) NULL
,
221 (GClassInitFunc
) anjuta_launcher_class_init
,
222 (GClassFinalizeFunc
) NULL
,
223 NULL
, /* class_data */
224 sizeof (AnjutaLauncher
),
226 (GInstanceInitFunc
) anjuta_launcher_init
,
227 NULL
/* value_table */
229 obj_type
= g_type_register_static (G_TYPE_OBJECT
,
230 "AnjutaLauncher", &obj_info
, 0);
236 anjuta_launcher_dispose (GObject
*obj
)
238 AnjutaLauncher
*launcher
= ANJUTA_LAUNCHER (obj
);
239 if (anjuta_launcher_is_busy (launcher
))
241 pid_t child_pid_save
= launcher
->priv
->child_pid
;
242 anjuta_children_unregister (child_pid_save
);
243 anjuta_launcher_execution_done_cleanup (launcher
, FALSE
);
245 /* We can not call anjuta_launcher_reset (launcher) to kill the
246 * running child because launcher has been initialized in cleanup
248 kill (child_pid_save
, SIGTERM
);
249 launcher
->priv
->busy
= FALSE
;
251 GNOME_CALL_PARENT (G_OBJECT_CLASS
, dispose
, (obj
));
255 anjuta_launcher_finalize (GObject
*obj
)
257 AnjutaLauncher
*launcher
= ANJUTA_LAUNCHER (obj
);
258 g_free (launcher
->priv
);
259 GNOME_CALL_PARENT (G_OBJECT_CLASS
, finalize
, (obj
));
263 anjuta_launcher_class_init (AnjutaLauncherClass
* klass
)
265 GObjectClass
*object_class
;
266 g_return_if_fail (klass
!= NULL
);
267 object_class
= (GObjectClass
*) klass
;
269 /* DEBUG_PRINT ("Initializing launcher class"); */
271 parent_class
= g_type_class_peek_parent (klass
);
274 * AnjutaLauncher::child-exited
275 * @launcher: a #AnjutaLancher object.
276 * @child_pid: process ID of the child
277 * @status: status as returned by waitpid function
278 * @time: time in seconds taken by the child
280 * Emitted when the child has exited and all i/o channels have
281 * been closed. If the terminate on exit flag is set, the i/o
282 * channels are automatically closed when the child exit.
283 * You need to use WEXITSTATUS and friend to get the child exit
284 * code from the status returned.
286 launcher_signals
[CHILD_EXITED_SIGNAL
] =
287 g_signal_new ("child-exited",
288 G_TYPE_FROM_CLASS (object_class
),
290 G_STRUCT_OFFSET (AnjutaLauncherClass
,
293 anjuta_cclosure_marshal_VOID__INT_INT_ULONG
,
294 G_TYPE_NONE
, 3, G_TYPE_INT
,
295 G_TYPE_INT
, G_TYPE_ULONG
);
298 * AnjutaLauncher::busy
299 * @launcher: a #AnjutaLancher object.
300 * @busy: TRUE is a child is currently running
302 * Emitted when a child starts after a call to one execute function
303 * (busy is TRUE) or when a child exits and all i/o channels are
304 * closed (busy is FALSE).
306 launcher_signals
[BUSY_SIGNAL
] =
307 g_signal_new ("busy",
308 G_TYPE_FROM_CLASS (object_class
),
310 G_STRUCT_OFFSET (AnjutaLauncherClass
,
313 anjuta_cclosure_marshal_VOID__BOOLEAN
,
314 G_TYPE_NONE
, 1, G_TYPE_BOOLEAN
);
316 object_class
->dispose
= anjuta_launcher_dispose
;
317 object_class
->finalize
= anjuta_launcher_finalize
;
321 anjuta_launcher_init (AnjutaLauncher
* obj
)
323 g_return_if_fail (obj
!= NULL
);
324 obj
->priv
= g_new0 (AnjutaLauncherPriv
, 1);
325 anjuta_launcher_initialize (obj
);
329 * anjuta_launcher_is_busy:
330 * @launcher: a #AnjutaLancher object.
332 * Tells if the laucher is currently executing any command.
334 * Return value: TRUE if launcher is busy, otherwisee FALSE.
337 anjuta_launcher_is_busy (AnjutaLauncher
*launcher
)
339 return launcher
->priv
->busy
;
343 anjuta_launcher_set_busy (AnjutaLauncher
*launcher
, gboolean flag
)
345 gboolean old_busy
= launcher
->priv
->busy
;
346 launcher
->priv
->busy
= flag
;
347 if (old_busy
!= flag
)
348 g_signal_emit_by_name (G_OBJECT (launcher
), "busy", flag
);
352 * anjuta_launcher_send_stdin:
353 * @launcher: a #AnjutaLancher object.
354 * @input_str: The string to send to STDIN of the process.
356 * Sends a string to Standard input of the process currently being executed.
359 anjuta_launcher_send_stdin (AnjutaLauncher
*launcher
, const gchar
* input_str
)
361 g_return_if_fail (launcher
);
362 g_return_if_fail (input_str
);
364 anjuta_launcher_send_ptyin (launcher
, input_str
);
368 * anjuta_launcher_send_stdin:
369 * @launcher: a #AnjutaLancher object.
371 * Sends a EOF to Standard input of the process currently being executed.
375 anjuta_launcher_send_stdin_eof (AnjutaLauncher
*launcher
)
378 g_io_channel_shutdown (launcher
->priv
->pty_channel
, TRUE
,
380 g_io_channel_unref (launcher
->priv
->pty_channel
);
381 launcher
->priv
->pty_channel
= NULL
;
385 g_warning ("g_io_channel_shutdown () failed: %s", err
->message
);
390 * anjuta_launcher_send_ptyin:
391 * @launcher: a #AnjutaLancher object.
392 * @input_str: The string to send to PTY of the process.
394 * Sends a string to TTY input of the process currently being executed.
395 * Mostly useful for entering passwords and other inputs which are directly
396 * read from TTY input of the process.
399 anjuta_launcher_send_ptyin (AnjutaLauncher
*launcher
, const gchar
* input_str
)
404 if (!input_str
|| strlen (input_str
) == 0) return;
408 g_io_channel_write_chars (launcher
->priv
->pty_channel
,
409 input_str
, strlen (input_str
),
410 &bytes_written
, &err
);
411 g_io_channel_flush (launcher
->priv
->pty_channel
, NULL
);
414 g_warning ("Error encountered while writing to PTY!. %s",
420 input_str
+= bytes_written
;
426 * anjuta_launcher_reset:
427 * @launcher: a #AnjutaLancher object.
429 * Resets the launcher and kills (SIGTERM) current process, if it is still
433 anjuta_launcher_reset (AnjutaLauncher
*launcher
)
435 if (anjuta_launcher_is_busy (launcher
))
436 kill (launcher
->priv
->child_pid
, SIGTERM
);
440 * anjuta_launcher_signal:
441 * @launcher: a #AnjutaLancher object.
442 * @sig: kernel signal ID (e.g. SIGTERM).
444 * Sends a kernel signal to the process that is being executed.
447 anjuta_launcher_signal (AnjutaLauncher
*launcher
, int sig
)
449 kill (launcher
->priv
->child_pid
, sig
);
453 * anjuta_launcher_get_child_pid:
454 * @launcher: a #AnjutaLancher object.
456 * Gets the Process ID of the child being executed.
458 * Return value: Process ID of the child.
461 anjuta_launcher_get_child_pid (AnjutaLauncher
*launcher
)
463 if (anjuta_launcher_is_busy (launcher
))
464 return launcher
->priv
->child_pid
;
470 anjuta_launcher_synchronize (AnjutaLauncher
*launcher
)
472 if (launcher
->priv
->in_cleanup
) return;
474 if (launcher
->priv
->child_has_terminated
&&
475 launcher
->priv
->stdout_is_done
&&
476 launcher
->priv
->stderr_is_done
)
478 if (launcher
->priv
->completion_check_timeout
>= 0)
479 g_source_remove (launcher
->priv
->completion_check_timeout
);
480 launcher
->priv
->completion_check_timeout
=
481 g_timeout_add (50, anjuta_launcher_check_for_execution_done
,
485 /* This case is not very good, but it blocks the whole IDE
486 because we never new if the child has finished */
487 else if (launcher
->priv
->stdout_is_done
&&
488 launcher
->priv
->stderr_is_done
)
490 /* DEBUG_PRINT ("Child has't exited yet waiting for 200ms"); */
491 if (launcher
->priv
->completion_check_timeout
>= 0)
492 g_source_remove (launcher
->priv
->completion_check_timeout
);
493 launcher
->priv
->completion_check_timeout
=
494 g_timeout_add(200, anjuta_launcher_check_for_execution_done
,
497 /* Add this case for gdb. It creates child inheriting gdb
498 * pipes which are not closed if gdb crashes */
499 else if (launcher
->priv
->child_has_terminated
&&
500 launcher
->priv
->terminate_on_exit
)
502 if (launcher
->priv
->completion_check_timeout
>= 0)
503 g_source_remove (launcher
->priv
->completion_check_timeout
);
504 launcher
->priv
->completion_check_timeout
=
505 g_timeout_add(0, anjuta_launcher_call_execution_done
,
510 /* Password dialog */
512 create_password_dialog (const gchar
* prompt
)
521 g_return_val_if_fail (prompt
, NULL
);
523 dialog
= gtk_dialog_new_with_buttons (prompt
,
524 NULL
, //FIXME: Pass the parent window here
525 // for transient purpose.
526 GTK_DIALOG_DESTROY_WITH_PARENT
,
527 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
528 GTK_STOCK_OK
, GTK_RESPONSE_OK
, NULL
);
529 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
531 gtk_window_set_wmclass (GTK_WINDOW (dialog
), "launcher-password-prompt",
533 hbox
= gtk_hbox_new (FALSE
, 10);
534 gtk_widget_show (hbox
);
535 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog
)->vbox
), hbox
);
537 icon
= anjuta_res_get_image (ANJUTA_PIXMAP_PASSWORD
);
538 gtk_widget_show (icon
);
539 gtk_box_pack_start_defaults (GTK_BOX(hbox
), icon
);
541 if (strlen (prompt
) < 20) {
542 box
= gtk_hbox_new (FALSE
, 5);
544 box
= gtk_vbox_new (FALSE
, 5);
546 gtk_widget_show (box
);
547 gtk_box_pack_start_defaults (GTK_BOX (hbox
), box
);
549 label
= gtk_label_new (_(prompt
));
550 gtk_widget_show (label
);
551 gtk_box_pack_start (GTK_BOX (box
), label
, FALSE
, FALSE
, 0);
553 entry
= gtk_entry_new ();
554 gtk_widget_show (entry
);
555 gtk_entry_set_visibility (GTK_ENTRY (entry
), FALSE
);
556 gtk_box_pack_start (GTK_BOX (box
), entry
, FALSE
, FALSE
, 0);
558 gtk_widget_ref (entry
);
559 g_object_set_data_full (G_OBJECT (dialog
), "password_entry",
560 gtk_widget_ref (entry
),
561 (GDestroyNotify
) gtk_widget_unref
);
562 gtk_widget_grab_focus (entry
);
563 gtk_entry_set_activates_default (GTK_ENTRY (entry
), TRUE
);
568 /* pty buffer check for password authentication */
570 anjuta_launcher_check_password_real (AnjutaLauncher
*launcher
,
571 const gchar
* last_line
)
573 if (anjuta_launcher_is_busy (launcher
) == FALSE
) return;
577 /* DEBUG_PRINT ("(In password) Last line = %s", last_line); */
578 if (is_password_prompt(last_line
)) {
579 /* Password prompt detected */
585 dialog
= create_password_dialog (last_line
);
586 button
= gtk_dialog_run (GTK_DIALOG(dialog
));
588 case GTK_RESPONSE_OK
:
589 passwd
= gtk_entry_get_text (
590 GTK_ENTRY (g_object_get_data (G_OBJECT (dialog
),
592 line
= g_strconcat (passwd
, "\n", NULL
);
593 anjuta_launcher_send_ptyin (launcher
, line
);
596 case GTK_RESPONSE_CANCEL
:
597 anjuta_launcher_send_ptyin (launcher
, "<canceled>\n");
598 anjuta_launcher_reset (launcher
);
603 gtk_widget_destroy (dialog
);
609 anjuta_launcher_check_password (AnjutaLauncher
*launcher
, const gchar
*chars
)
614 if (!chars
|| strlen(chars
) <= 0)
617 /* DEBUG_PRINT ("Chars buffer = %s", chars); */
618 start
= end
= strlen (chars
);
619 while (start
> 0 && chars
[start
-1] != '\n') start
--;
623 last_line
= g_strndup (&chars
[start
], end
- start
+ 1);
625 /* DEBUG_PRINT ("Last line = %s", last_line); */
626 /* Checks for password, again */
627 anjuta_launcher_check_password_real (launcher
, last_line
);
633 is_password_prompt (const gchar
* line
)
635 gchar
* password
= "assword";
636 gchar
* passphrase
= "assphrase";
638 if (strlen (line
) < strlen (password
)
639 || strlen (line
) < strlen (passphrase
))
642 if (g_strstr_len(line
, 80, password
) != NULL
643 || g_strstr_len(line
, 80, passphrase
) != NULL
)
646 for (i
= strlen(line
) - 1; i
!= 0; --i
)
650 if (g_ascii_isspace(line
[i
]))
660 anjuta_launcher_buffered_output (AnjutaLauncher
*launcher
,
661 AnjutaLauncherOutputType output_type
,
665 gchar
*incomplete_line
;
668 g_return_if_fail (chars
!= NULL
);
669 g_return_if_fail (strlen (chars
) > 0);
671 if (launcher
->priv
->output_callback
== NULL
)
673 if (launcher
->priv
->buffered_output
== FALSE
)
675 (launcher
->priv
->output_callback
)(launcher
, output_type
, chars
,
676 launcher
->priv
->callback_data
);
681 case ANJUTA_LAUNCHER_OUTPUT_STDOUT
:
682 buffer
= &launcher
->priv
->stdout_buffer
;
684 case ANJUTA_LAUNCHER_OUTPUT_STDERR
:
685 buffer
= &launcher
->priv
->stderr_buffer
;
688 g_warning ("Should not reach here");
692 all_lines
= g_strconcat (*buffer
, chars
, NULL
);
694 all_lines
= g_strdup (chars
);
696 /* Buffer the last incomplete line */
697 incomplete_line
= all_lines
+ strlen (all_lines
);
698 while (incomplete_line
> all_lines
&&
699 *incomplete_line
!= '\n')
701 incomplete_line
= g_utf8_prev_char (incomplete_line
);
703 if (*incomplete_line
== '\n')
706 /* Update line buffer */
709 if (strlen(incomplete_line
))
711 *buffer
= g_strdup (incomplete_line
);
712 /* DEBUG_PRINT ("Line buffer for %d: %s", output_type, incomplete_line); */
714 /* Check for password prompt */
715 if (launcher
->priv
->check_for_passwd_prompt
)
716 anjuta_launcher_check_password (launcher
, incomplete_line
);
718 /* Deliver complete lines */
719 *incomplete_line
= '\0';
720 if (strlen (all_lines
) > 0)
721 (launcher
->priv
->output_callback
)(launcher
, output_type
, all_lines
,
722 launcher
->priv
->callback_data
);
727 anjuta_launcher_scan_output (GIOChannel
*channel
, GIOCondition condition
,
728 AnjutaLauncher
*launcher
)
731 gchar buffer
[FILE_BUFFER_SIZE
];
734 if (condition
& G_IO_IN
)
739 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
740 if (n
> 0 && !err
) /* There is output */
744 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
745 anjuta_launcher_buffered_output (launcher
,
746 ANJUTA_LAUNCHER_OUTPUT_STDOUT
,
750 /* The pipe is closed on the other side */
751 /* if not related to non blocking read or interrupted syscall */
752 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
754 /* DEBUG_PRINT ("launcher.c: Error while reading child stdout\n"); */
755 launcher
->priv
->stdout_is_done
= TRUE
;
756 anjuta_launcher_synchronize (launcher
);
759 /* Read next chars if buffer was too small
760 * (the maximum length of one character is 6 bytes) */
761 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
765 if ((condition
& G_IO_ERR
) || (condition
& G_IO_HUP
))
767 /* DEBUG_PRINT ("launcher.c: STDOUT pipe closed"); */
768 launcher
->priv
->stdout_is_done
= TRUE
;
769 anjuta_launcher_synchronize (launcher
);
776 anjuta_launcher_scan_error (GIOChannel
*channel
, GIOCondition condition
,
777 AnjutaLauncher
*launcher
)
780 gchar buffer
[FILE_BUFFER_SIZE
];
783 if (condition
& G_IO_IN
)
788 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
789 if (n
> 0 && !err
) /* There is stderr output */
793 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
794 anjuta_launcher_buffered_output (launcher
,
795 ANJUTA_LAUNCHER_OUTPUT_STDERR
,
799 /* The pipe is closed on the other side */
800 /* if not related to non blocking read or interrupted syscall */
801 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
803 /* DEBUG_PRINT ("launcher.c: Error while reading child stderr");*/
804 launcher
->priv
->stderr_is_done
= TRUE
;
805 anjuta_launcher_synchronize (launcher
);
808 /* Read next chars if buffer was too small
809 * (the maximum length of one character is 6 bytes) */
810 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
814 if ((condition
& G_IO_ERR
) || (condition
& G_IO_HUP
))
816 /* DEBUG_PRINT ("launcher.c: STDERR pipe closed"); */
817 launcher
->priv
->stderr_is_done
= TRUE
;
818 anjuta_launcher_synchronize (launcher
);
825 anjuta_launcher_scan_pty (GIOChannel
*channel
, GIOCondition condition
,
826 AnjutaLauncher
*launcher
)
829 gchar buffer
[FILE_BUFFER_SIZE
];
832 if (condition
& G_IO_IN
)
837 g_io_channel_read_chars (channel
, buffer
, FILE_BUFFER_SIZE
-1, &n
, &err
);
838 if (n
> 0 && !err
) /* There is stderr output */
841 gchar
*old_str
= launcher
->priv
->pty_output_buffer
;
843 utf8_chars
= anjuta_util_convert_to_utf8 (buffer
);
846 gchar
*str
= g_strconcat (old_str
, utf8_chars
, NULL
);
847 launcher
->priv
->pty_output_buffer
= str
;
851 launcher
->priv
->pty_output_buffer
= g_strdup (utf8_chars
);
854 /* The pipe is closed on the other side */
855 /* if not related to non blocking read or interrupted syscall */
856 else if (err
&& errno
!= EAGAIN
&& errno
!= EINTR
)
858 g_warning (_("launcher.c: Error while reading child pty\n"));
861 /* Read next chars if buffer was too small
862 * (the maximum length of one character is 6 bytes) */
863 } while (!err
&& (n
> FILE_BUFFER_SIZE
- 7));
866 if (launcher
->priv
->check_for_passwd_prompt
867 && launcher
->priv
->pty_output_buffer
868 && strlen (launcher
->priv
->pty_output_buffer
) > 0)
870 anjuta_launcher_check_password (launcher
,
871 launcher
->priv
->pty_output_buffer
);
874 /* In pty case, we handle the cases in different invocations */
875 /* Do not hook up for G_IO_HUP */
876 if (condition
& G_IO_ERR
)
878 /* DEBUG_PRINT ("launcher.c: PTY pipe error!"); */
885 anjuta_launcher_execution_done_cleanup (AnjutaLauncher
*launcher
,
886 gboolean emit_signal
)
888 gint child_status
, child_pid
;
891 if (launcher
->priv
->in_cleanup
)
894 launcher
->priv
->in_cleanup
= TRUE
;
896 /* Remove pending timeout */
897 if (launcher
->priv
->completion_check_timeout
>= 0)
898 g_source_remove (launcher
->priv
->completion_check_timeout
);
900 /* Make sure all pending I/O are flushed out */
901 while (g_main_context_pending (NULL
))
902 g_main_context_iteration (NULL
, FALSE
);
904 /* Can be called again, while waiting in the previous line
905 * Do nothing if clean up is already done */
906 if (launcher
->priv
->stdout_channel
)
908 g_io_channel_shutdown (launcher
->priv
->stdout_channel
, emit_signal
, NULL
);
909 g_io_channel_unref (launcher
->priv
->stdout_channel
);
910 g_source_remove (launcher
->priv
->stdout_watch
);
913 if (launcher
->priv
->stderr_channel
)
915 g_io_channel_shutdown (launcher
->priv
->stderr_channel
, emit_signal
, NULL
);
916 g_io_channel_unref (launcher
->priv
->stderr_channel
);
917 g_source_remove (launcher
->priv
->stderr_watch
);
920 if (launcher
->priv
->pty_channel
)
922 g_io_channel_shutdown (launcher
->priv
->pty_channel
, emit_signal
, NULL
);
923 g_io_channel_unref (launcher
->priv
->pty_channel
);
925 g_source_remove (launcher
->priv
->pty_watch
);
928 if (launcher
->priv
->pty_output_buffer
)
929 g_free (launcher
->priv
->pty_output_buffer
);
930 if (launcher
->priv
->stdout_buffer
)
931 g_free (launcher
->priv
->stdout_buffer
);
932 if (launcher
->priv
->stderr_buffer
)
933 g_free (launcher
->priv
->stdout_buffer
);
935 /* Save them before we re-initialize */
936 child_status
= launcher
->priv
->child_status
;
937 child_pid
= launcher
->priv
->child_pid
;
938 start_time
= launcher
->priv
->start_time
;
941 anjuta_launcher_set_busy (launcher
, FALSE
);
943 anjuta_launcher_initialize (launcher
);
945 /* Call this here, after set_busy (FALSE) so we are able to
946 launch a new child from the terminate function.
947 (by clubfan 2002-04-07)
949 /* DEBUG_PRINT ("Exit status: %d", child_status); */
951 g_signal_emit_by_name (launcher
, "child-exited", child_pid
,
953 time (NULL
) - start_time
);
955 launcher
->priv
->in_cleanup
= FALSE
;
958 /* Using this function is necessary because
959 * anjuta_launcher_execution_done_cleanup needs to be called in the same
960 * thread than the gtk main loop */
962 anjuta_launcher_call_execution_done (gpointer data
)
964 AnjutaLauncher
*launcher
= data
;
966 launcher
->priv
->completion_check_timeout
= -1;
967 anjuta_launcher_execution_done_cleanup (launcher
, TRUE
);
971 /* monitors closure of stdout stderr and pty through a gtk_timeout_add setup */
973 anjuta_launcher_check_for_execution_done (gpointer data
)
975 AnjutaLauncher
*launcher
= data
;
977 DEBUG_PRINT ("launcher_execution_done STDOUT:%d, STDERR:%d",
978 launcher->priv->stdout_is_done ? 1 : 0,
979 launcher->priv->stderr_is_done ? 1 : 0);
981 if (launcher
->priv
->stdout_is_done
== FALSE
||
982 launcher
->priv
->stderr_is_done
== FALSE
)
984 if (launcher
->priv
->child_has_terminated
== FALSE
)
986 /* DEBUG_PRINT ("launcher: We missed the exit of the child"); */
987 anjuta_children_recover();
989 launcher
->priv
->completion_check_timeout
= -1;
990 anjuta_launcher_execution_done_cleanup (launcher
, TRUE
);
995 anjuta_launcher_child_terminated (int status
, gpointer data
)
997 AnjutaLauncher
*launcher
= data
;
999 g_return_if_fail(ANJUTA_IS_LAUNCHER(launcher
));
1001 /* Save child exit code */
1002 launcher
->priv
->child_status
= status
;
1003 launcher
->priv
->child_has_terminated
= TRUE
;
1004 anjuta_launcher_synchronize (launcher
);
1008 * anjuta_launcher_set_encoding:
1009 * @launcher: a #AnjutaLancher object.
1010 * @charset: Character set to use for Input/Output with the process.
1012 * Sets the character set to use for Input/Output with the process.
1014 * Return value: TRUE if successful, otherwise FALSE.
1017 anjuta_launcher_set_encoding (AnjutaLauncher
*launcher
, const gchar
*charset
)
1022 g_return_val_if_fail (launcher
!= NULL
, FALSE
);
1023 // charset can be NULL
1025 s
= g_io_channel_set_encoding (launcher
->priv
->stderr_channel
, charset
, NULL
);
1026 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1027 s
= g_io_channel_set_encoding (launcher
->priv
->stdout_channel
, charset
, NULL
);
1028 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1029 s
= g_io_channel_set_encoding (launcher
->priv
->pty_channel
, charset
, NULL
);
1030 if (s
!= G_IO_STATUS_NORMAL
) r
= FALSE
;
1034 g_warning ("launcher.c: Failed to set channel encoding!");
1040 anjuta_launcher_fork (AnjutaLauncher
*launcher
, gchar
*const args
[])
1043 int pty_master_fd
, md
;
1044 int stdout_pipe
[2], stderr_pipe
[2];
1046 struct termios termios_flags
;
1047 const gchar
*charset
;
1049 working_dir
= g_get_current_dir ();
1055 /* Fork the command */
1056 child_pid
= forkpty (&pty_master_fd
, NULL
, NULL
, NULL
);
1060 dup (stderr_pipe
[1]);
1062 dup (stdout_pipe
[1]);
1064 /* Close unnecessary pipes */
1065 close (stderr_pipe
[0]);
1066 close (stdout_pipe
[0]);
1069 if ((ioctl(pty_slave_fd, TIOCSCTTY, NULL))
1070 perror ("Could not set new controlling tty");
1072 /* Set no delays for the write pipes (non_buffered) so
1073 that we get all the outputs immidiately */
1074 if ((md
= fcntl (stdout_pipe
[1], F_GETFL
)) != -1)
1075 fcntl (stdout_pipe
[1], F_SETFL
, O_SYNC
| md
);
1076 if ((md
= fcntl (stderr_pipe
[1], F_GETFL
)) != -1)
1077 fcntl (stderr_pipe
[1], F_SETFL
, O_SYNC
| md
);
1079 execvp (args
[0], args
);
1080 g_warning (_("Cannot execute command: \"%s\""), args
[0]);
1081 perror(_("execvp failed"));
1084 g_free (working_dir
);
1086 /* Close parent's side pipes */
1087 close (stderr_pipe
[1]);
1088 close (stdout_pipe
[1]);
1092 g_warning ("launcher.c: Fork failed!");
1093 /* Close parent's side pipes */
1094 close (stderr_pipe
[0]);
1095 close (stdout_pipe
[0]);
1100 * Set pipes none blocking, so we can read big buffers
1101 * in the callback without having to use FIONREAD
1102 * to make sure the callback doesn't block.
1104 if ((md
= fcntl (stdout_pipe
[0], F_GETFL
)) != -1)
1105 fcntl (stdout_pipe
[0], F_SETFL
, O_NONBLOCK
| md
);
1106 if ((md
= fcntl (stderr_pipe
[0], F_GETFL
)) != -1)
1107 fcntl (stderr_pipe
[0], F_SETFL
, O_NONBLOCK
| md
);
1108 if ((md
= fcntl (pty_master_fd
, F_GETFL
)) != -1)
1109 fcntl (pty_master_fd
, F_SETFL
, O_NONBLOCK
| md
);
1111 launcher
->priv
->child_pid
= child_pid
;
1112 launcher
->priv
->stderr_channel
= g_io_channel_unix_new (stderr_pipe
[0]);
1113 launcher
->priv
->stdout_channel
= g_io_channel_unix_new (stdout_pipe
[0]);
1114 launcher
->priv
->pty_channel
= g_io_channel_unix_new (pty_master_fd
);
1116 g_io_channel_set_buffer_size (launcher
->priv
->pty_channel
, FILE_INPUT_BUFFER_SIZE
);
1119 g_get_charset (&charset
);
1120 anjuta_launcher_set_encoding (launcher
, charset
);
1122 tcgetattr(pty_master_fd
, &termios_flags
);
1123 termios_flags
.c_iflag
&= ~(IGNPAR
| INPCK
| INLCR
| IGNCR
| ICRNL
| IXON
|
1125 termios_flags
.c_iflag
|= IGNBRK
| BRKINT
| IMAXBEL
| IXANY
;
1126 termios_flags
.c_oflag
&= ~OPOST
;
1127 // termios_flags.c_oflag |= 0;
1128 termios_flags
.c_cflag
&= ~(CSTOPB
| CREAD
| PARENB
| HUPCL
);
1129 termios_flags
.c_cflag
|= CS8
| CLOCAL
;
1131 if (!launcher
->priv
->terminal_echo_on
)
1133 termios_flags
.c_lflag
&= ~(ECHOKE
| ECHOE
| ECHO
| ECHONL
|
1137 ECHOCTL
| ISIG
| ICANON
| IEXTEN
| NOFLSH
| TOSTOP
);
1139 // termios_flags.c_lflag |= 0;
1140 termios_flags
.c_cc
[VMIN
] = 0;
1141 cfsetospeed(&termios_flags
, __MAX_BAUD
);
1142 tcsetattr(pty_master_fd
, TCSANOW
, &termios_flags
);
1144 launcher
->priv
->stderr_watch
=
1145 g_io_add_watch (launcher
->priv
->stderr_channel
,
1146 G_IO_IN
| G_IO_ERR
| G_IO_HUP
,
1147 (GIOFunc
)anjuta_launcher_scan_error
, launcher
);
1148 launcher
->priv
->stdout_watch
=
1149 g_io_add_watch (launcher
->priv
->stdout_channel
,
1150 G_IO_IN
| G_IO_ERR
| G_IO_HUP
,
1151 (GIOFunc
)anjuta_launcher_scan_output
, launcher
);
1152 launcher
->priv
->pty_watch
=
1153 g_io_add_watch (launcher
->priv
->pty_channel
,
1154 G_IO_IN
| G_IO_ERR
, /* Do not hook up for G_IO_HUP */
1155 (GIOFunc
)anjuta_launcher_scan_pty
, launcher
);
1157 /* DEBUG_PRINT ("Terminal child forked: %d", launcher->priv->child_pid); */
1158 anjuta_children_register (launcher
->priv
->child_pid
,
1159 anjuta_launcher_child_terminated
,
1165 * anjuta_launcher_execute_v:
1166 * @launcher: a #AnjutaLancher object.
1167 * @argv: Command args.
1168 * @callback: The callback for delivering output from the process.
1169 * @callback_data: Callback data for the above callback.
1171 * The first of the @args is the command itself. The rest are sent to the
1172 * as it's arguments. This function works similar to anjuta_launcher_execute().
1174 * Return value: TRUE if successfully launched, otherwise FALSE.
1177 anjuta_launcher_execute_v (AnjutaLauncher
*launcher
, gchar
*const argv
[],
1178 AnjutaLauncherOutputCallback callback
,
1179 gpointer callback_data
)
1181 if (anjuta_launcher_is_busy (launcher
))
1184 anjuta_launcher_set_busy (launcher
, TRUE
);
1186 launcher
->priv
->start_time
= time (NULL
);
1187 launcher
->priv
->child_status
= 0;
1188 launcher
->priv
->stdout_is_done
= FALSE
;
1189 launcher
->priv
->stderr_is_done
= FALSE
;
1190 launcher
->priv
->child_has_terminated
= FALSE
;
1191 launcher
->priv
->in_cleanup
= FALSE
;
1192 launcher
->priv
->output_callback
= callback
;
1193 launcher
->priv
->callback_data
= callback_data
;
1195 /* On a fork error perform a cleanup and return */
1196 if (anjuta_launcher_fork (launcher
, argv
) < 0)
1198 anjuta_launcher_initialize (launcher
);
1205 * anjuta_launcher_execute:
1206 * @launcher: a #AnjutaLancher object.
1207 * @command_str: The command to execute.
1208 * @callback: The callback for delivering output from the process.
1209 * @callback_data: Callback data for the above callback.
1211 * Executes a command in the launcher. Both outputs (STDOUT and STDERR) are
1212 * delivered to the above callback. The data are delivered as they arrive
1213 * from the process and could be of any lenght. If the process asks for
1214 * passwords, the user will be automatically prompted with a dialog to enter
1215 * it. Please note that not all formats of the password are recognized. Those
1216 * with the standard 'assword:' substring in the prompt should work well.
1218 * Return value: TRUE if successfully launched, otherwise FALSE.
1221 anjuta_launcher_execute (AnjutaLauncher
*launcher
, const gchar
*command_str
,
1222 AnjutaLauncherOutputCallback callback
,
1223 gpointer callback_data
)
1225 GList
*args_list
, *args_list_ptr
;
1226 gchar
**args
, **args_ptr
;
1229 /* Prepare command args */
1230 args_list
= anjuta_util_parse_args_from_string (command_str
);
1231 args
= g_new (char*, g_list_length (args_list
) + 1);
1232 args_list_ptr
= args_list
;
1234 while (args_list_ptr
)
1236 *args_ptr
= (char*) args_list_ptr
->data
;
1237 args_list_ptr
= g_list_next (args_list_ptr
);
1242 ret
= anjuta_launcher_execute_v (launcher
, args
,
1243 callback
, callback_data
);
1245 anjuta_util_glist_strings_free (args_list
);
1250 * anjuta_launcher_set_buffered_output:
1251 * @launcher: a #AnjutaLancher object.
1252 * @buffered: buffer output.
1254 * Sets if output should buffered or not. By default, it is buffered.
1256 * Return value: Previous flag value
1259 anjuta_launcher_set_buffered_output (AnjutaLauncher
*launcher
, gboolean buffered
)
1261 gboolean past_value
= launcher
->priv
->buffered_output
;
1262 launcher
->priv
->buffered_output
= buffered
;
1267 * anjuta_launcher_set_check_passwd_prompt:
1268 * @launcher: a #AnjutaLancher object.
1269 * @check_passwd: check for password.
1271 * Set if output is checked for a password prompti. A special dialog box
1272 * is use to enter it in this case. By default, this behavior is enabled.
1274 * Return value: Previous flag value
1277 anjuta_launcher_set_check_passwd_prompt (AnjutaLauncher
*launcher
, gboolean check_passwd
)
1279 gboolean past_value
= launcher
->priv
->check_for_passwd_prompt
;
1280 launcher
->priv
->check_for_passwd_prompt
= check_passwd
;
1285 * anjuta_launcher_set_terminal_echo:
1286 * @launcher: a #AnjutaLancher object.
1287 * @echo_on: Echo ON flag.
1289 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1292 * Return value: Previous flag value
1295 anjuta_launcher_set_terminal_echo (AnjutaLauncher
*launcher
,
1298 gboolean past_value
= launcher
->priv
->terminal_echo_on
;
1299 launcher
->priv
->terminal_echo_on
= echo_on
;
1304 * anjuta_launcher_set_terminate_on_exit:
1305 * @launcher: a #AnjutaLancher object.
1306 * @terminate_on_exit: terminate on exit flag
1308 * When this flag is set, al i/o channels are closed and the child-exit
1309 * signal is emitted as soon as the child exit. By default, or when this
1310 * flag is clear, the launcher object wait until the i/o channels are
1313 * Return value: Previous flag value
1316 anjuta_launcher_set_terminate_on_exit (AnjutaLauncher
*launcher
,
1317 gboolean terminate_on_exit
)
1319 gboolean past_value
= launcher
->priv
->terminate_on_exit
;
1320 launcher
->priv
->terminate_on_exit
= terminate_on_exit
;
1325 * anjuta_launcher_new:
1327 * Sets if input (those given in STDIN) should enabled or disabled. By default,
1330 * Return value: a new instance of #AnjutaLancher class.
1333 anjuta_launcher_new ()
1335 return g_object_new (ANJUTA_TYPE_LAUNCHER
, NULL
);