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