1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Naba Kumar <naba@gnome.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * SECTION:anjuta-utils
24 * @short_description: Utility functions
26 * @stability: Unstable
27 * @include: libanjuta/anjuta-utils.h
40 #include <sys/types.h>
41 #include <sys/fcntl.h>
42 #include <sys/termios.h>
48 #include <glib/gi18n.h>
50 #include <glib/gstdio.h>
52 #include <libanjuta/anjuta-utils.h>
53 #include <libanjuta/anjuta-debug.h>
55 #include <libgnomevfs/gnome-vfs.h>
57 #define FILE_BUFFER_SIZE 1024
60 anjuta_util_copy_file (gchar
* src
, gchar
* dest
, gboolean show_error
)
62 FILE *input_fp
, *output_fp
;
63 gchar buffer
[FILE_BUFFER_SIZE
];
64 gint bytes_read
, bytes_written
;
69 input_fp
= fopen (src
, "rb");
73 anjuta_util_dialog_error_system (NULL
, errno
,
74 _("Unable to read file: %s."),
79 output_fp
= fopen (dest
, "wb");
80 if (output_fp
== NULL
)
83 anjuta_util_dialog_error_system (NULL
, errno
,
84 _("Unable to create file: %s."),
92 bytes_read
= fread (buffer
, 1, FILE_BUFFER_SIZE
, input_fp
);
93 if (bytes_read
!= FILE_BUFFER_SIZE
&& ferror (input_fp
))
101 bytes_written
= fwrite (buffer
, 1, bytes_read
, output_fp
);
102 if (bytes_read
!= bytes_written
)
109 if (bytes_read
!= FILE_BUFFER_SIZE
&& feof (input_fp
))
118 if( show_error
&& (error
== FALSE
))
119 anjuta_util_dialog_error_system (NULL
, errno
,
120 _("Unable to complete file copy"));
125 anjuta_util_color_from_string (const gchar
* val
, guint16
* r
, guint16
* g
, guint16
* b
)
128 if (gdk_color_parse(val
, &color
))
137 anjuta_util_string_from_color (guint16 r
, guint16 g
, guint16 b
)
139 return g_strdup_printf("#%02x%02x%02x", r
>> 8, g
>> 8, b
>> 8);
142 /* Get a GdkColor from preferences. Free the color with gdk_color_free() */
144 anjuta_util_convert_color(AnjutaPreferences
* prefs
, const gchar
* pref_name
)
146 GdkColor
* color
= g_new0(GdkColor
, 1);
147 gchar
* color_string
= anjuta_preferences_get(prefs
, pref_name
);
148 gdk_color_parse(color_string
, color
);
153 anjuta_util_button_new_with_stock_image (const gchar
* text
,
154 const gchar
* stock_id
)
163 button
= gtk_button_new ();
165 if (GTK_BIN (button
)->child
)
166 gtk_container_remove (GTK_CONTAINER (button
),
167 GTK_BIN (button
)->child
);
169 if (gtk_stock_lookup (stock_id
, &item
))
171 label
= gtk_label_new_with_mnemonic (text
);
173 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), GTK_WIDGET (button
));
175 image
= gtk_image_new_from_stock (stock_id
, GTK_ICON_SIZE_BUTTON
);
176 hbox
= gtk_hbox_new (FALSE
, 2);
178 align
= gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
180 gtk_box_pack_start (GTK_BOX (hbox
), image
, FALSE
, FALSE
, 0);
181 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
183 gtk_container_add (GTK_CONTAINER (button
), align
);
184 gtk_container_add (GTK_CONTAINER (align
), hbox
);
185 gtk_widget_show_all (align
);
190 label
= gtk_label_new_with_mnemonic (text
);
191 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), GTK_WIDGET (button
));
193 gtk_misc_set_alignment (GTK_MISC (label
), 0.5, 0.5);
195 gtk_widget_show (label
);
196 gtk_container_add (GTK_CONTAINER (button
), label
);
202 anjuta_util_dialog_add_button (GtkDialog
*dialog
, const gchar
* text
,
203 const gchar
* stock_id
, gint response_id
)
207 g_return_val_if_fail (GTK_IS_DIALOG (dialog
), NULL
);
208 g_return_val_if_fail (text
!= NULL
, NULL
);
209 g_return_val_if_fail (stock_id
!= NULL
, NULL
);
211 button
= anjuta_util_button_new_with_stock_image (text
, stock_id
);
212 g_return_val_if_fail (button
!= NULL
, NULL
);
214 GTK_WIDGET_SET_FLAGS (button
, GTK_CAN_DEFAULT
);
216 gtk_widget_show (button
);
218 gtk_dialog_add_action_widget (dialog
, button
, response_id
);
224 anjuta_util_dialog_error (GtkWindow
*parent
, const gchar
*mesg
, ...)
229 GtkWindow
*real_parent
;
231 va_start (args
, mesg
);
232 message
= g_strdup_vprintf (mesg
, args
);
235 if (parent
&& GTK_IS_WINDOW (parent
))
237 real_parent
= parent
;
244 // Dialog to be HIG compliant
245 dialog
= gtk_message_dialog_new (real_parent
,
246 GTK_DIALOG_DESTROY_WITH_PARENT
,
248 GTK_BUTTONS_CLOSE
, message
);
249 g_signal_connect (G_OBJECT (dialog
), "response",
250 G_CALLBACK (gtk_widget_destroy
), NULL
);
251 gtk_widget_show (dialog
);
256 anjuta_util_dialog_warning (GtkWindow
*parent
, const gchar
* mesg
, ...)
261 GtkWindow
*real_parent
;
263 va_start (args
, mesg
);
264 message
= g_strdup_vprintf (mesg
, args
);
267 if (parent
&& GTK_IS_WINDOW (parent
))
269 real_parent
= parent
;
276 // Dialog to be HIG compliant
277 dialog
= gtk_message_dialog_new (real_parent
,
278 GTK_DIALOG_DESTROY_WITH_PARENT
,
280 GTK_BUTTONS_CLOSE
, message
);
281 g_signal_connect (G_OBJECT (dialog
), "response",
282 G_CALLBACK (gtk_widget_destroy
), NULL
);
283 gtk_widget_show (dialog
);
288 anjuta_util_dialog_info (GtkWindow
*parent
, const gchar
* mesg
, ...)
293 GtkWindow
*real_parent
;
295 va_start (args
, mesg
);
296 message
= g_strdup_vprintf (mesg
, args
);
299 if (parent
&& GTK_IS_WINDOW (parent
))
301 real_parent
= parent
;
307 // Dialog to be HIG compliant
308 dialog
= gtk_message_dialog_new (real_parent
,
309 GTK_DIALOG_DESTROY_WITH_PARENT
,
311 GTK_BUTTONS_CLOSE
, message
);
312 g_signal_connect (G_OBJECT (dialog
), "response",
313 G_CALLBACK (gtk_widget_destroy
), NULL
);
314 gtk_widget_show (dialog
);
319 anjuta_util_dialog_error_system (GtkWindow
* parent
, gint errnum
,
320 const gchar
* mesg
, ... )
326 GtkWindow
*real_parent
;
328 va_start (args
, mesg
);
329 message
= g_strdup_vprintf (mesg
, args
);
333 tot_mesg
= g_strconcat (message
, _("\nSystem: "),
334 g_strerror(errnum
), NULL
);
339 if (parent
&& GTK_IS_WINDOW (parent
))
341 real_parent
= parent
;
347 // Dialog to be HIG compliant
348 dialog
= gtk_message_dialog_new (real_parent
,
349 GTK_DIALOG_DESTROY_WITH_PARENT
,
351 GTK_BUTTONS_CLOSE
, tot_mesg
);
352 g_signal_connect (G_OBJECT (dialog
), "response",
353 G_CALLBACK (gtk_widget_destroy
), NULL
);
354 gtk_widget_show (dialog
);
359 anjuta_util_dialog_boolean_question (GtkWindow
*parent
, const gchar
*mesg
, ...)
365 GtkWindow
*real_parent
;
367 va_start (args
, mesg
);
368 message
= g_strdup_vprintf (mesg
, args
);
371 if (parent
&& GTK_IS_WINDOW (parent
))
373 real_parent
= parent
;
380 dialog
= gtk_message_dialog_new (real_parent
,
381 GTK_DIALOG_DESTROY_WITH_PARENT
,
382 GTK_MESSAGE_QUESTION
,
383 GTK_BUTTONS_YES_NO
, message
);
385 ret
= gtk_dialog_run (GTK_DIALOG (dialog
));
386 gtk_widget_destroy (dialog
);
389 return (ret
== GTK_RESPONSE_YES
);
393 anjuta_util_dialog_input (GtkWindow
*parent
, const gchar
*prompt
,
394 const gchar
*default_value
, gchar
**return_value
)
396 GtkWidget
*dialog
, *label
, *frame
, *entry
, *dialog_vbox
, *vbox
;
399 GtkWindow
*real_parent
;
401 if (parent
&& GTK_IS_WINDOW (parent
))
403 real_parent
= parent
;
410 dialog
= gtk_dialog_new_with_buttons (prompt
, real_parent
,
411 GTK_DIALOG_DESTROY_WITH_PARENT
,
412 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
413 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
415 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
416 dialog_vbox
= GTK_DIALOG (dialog
)->vbox
;
417 gtk_window_set_default_size (GTK_WINDOW (dialog
), 400, -1);
418 gtk_widget_show (dialog_vbox
);
420 markup
= g_strconcat ("<b>", prompt
, "</b>", NULL
);
421 label
= gtk_label_new (NULL
);
422 gtk_label_set_markup (GTK_LABEL (label
), markup
);
423 gtk_widget_show (label
);
426 frame
= gtk_frame_new (NULL
);
427 gtk_frame_set_label_widget (GTK_FRAME (frame
), label
);
428 gtk_frame_set_shadow_type (GTK_FRAME (frame
), GTK_SHADOW_NONE
);
429 gtk_container_set_border_width (GTK_CONTAINER (frame
), 10);
430 gtk_widget_show (frame
);
431 gtk_box_pack_start (GTK_BOX (dialog_vbox
), frame
, FALSE
, FALSE
, 0);
433 vbox
= gtk_vbox_new (FALSE
, 0);
434 gtk_widget_show (vbox
);
435 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
436 gtk_container_add (GTK_CONTAINER (frame
), vbox
);
438 entry
= gtk_entry_new ();
439 gtk_widget_show (entry
);
440 gtk_entry_set_activates_default (GTK_ENTRY (entry
), TRUE
);
441 gtk_box_pack_start (GTK_BOX (vbox
), entry
, FALSE
, FALSE
, 0);
443 gtk_entry_set_text (GTK_ENTRY (entry
), default_value
);
445 res
= gtk_dialog_run (GTK_DIALOG (dialog
));
447 if (gtk_entry_get_text (GTK_ENTRY (entry
)) &&
448 strlen (gtk_entry_get_text (GTK_ENTRY (entry
))) > 0)
450 *return_value
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
454 *return_value
= NULL
;
456 gtk_widget_destroy (dialog
);
457 return (res
== GTK_RESPONSE_OK
);
461 anjuta_util_prog_is_installed (gchar
* prog
, gboolean show
)
463 gchar
* prog_path
= g_find_program_in_path (prog
);
471 anjuta_util_dialog_error (NULL
, _("The \"%s\" utility is not installed.\n"
472 "Please install it."), prog
);
478 anjuta_util_get_a_tmp_file (void)
480 static gint count
= 0;
484 tmpdir
= g_get_tmp_dir ();
486 g_strdup_printf ("%s/anjuta_%d.%d", tmpdir
, count
++, getpid ());
490 /* GList of strings operations */
492 anjuta_util_glist_from_string (const gchar
*string
)
494 gchar
*str
, *temp
, buff
[256];
496 gchar
*word_start
, *word_end
;
501 temp
= g_strdup (string
);
511 /* Remove leading spaces */
512 while (isspace (*str
) && *str
!= '\0')
517 /* Find start and end of word */
519 while (!isspace (*str
) && *str
!= '\0')
523 /* Copy the word into the buffer */
524 for (ptr
= word_start
, i
= 0; ptr
< word_end
; ptr
++, i
++)
528 list
= g_list_append (list
, g_strdup (buff
));
537 /* Prefix the strings */
539 anjuta_util_glist_strings_prefix (GList
* list
, const gchar
*prefix
)
544 g_return_if_fail (prefix
!= NULL
);
549 node
->data
= g_strconcat (prefix
, tmp
, NULL
);
550 if (tmp
) g_free (tmp
);
551 node
= g_list_next (node
);
555 /* Suffix the strings */
557 anjuta_util_glist_strings_sufix (GList
* list
, const gchar
*sufix
)
562 g_return_if_fail (sufix
!= NULL
);
567 node
->data
= g_strconcat (tmp
, sufix
, NULL
);
568 if (tmp
) g_free (tmp
);
569 node
= g_list_next (node
);
573 /* Duplicate list of strings */
575 anjuta_util_glist_strings_dup (GList
* list
)
585 new_list
= g_list_append (new_list
, g_strdup(node
->data
));
587 new_list
= g_list_append (new_list
, NULL
);
588 node
= g_list_next (node
);
593 /* Join list of strings using the given delimiter */
595 anjuta_util_glist_strings_join (GList
* list
, gchar
*delimiter
)
598 gboolean first
= TRUE
;
601 joined
= g_string_new (NULL
);
608 g_string_append (joined
, delimiter
);
611 g_string_append (joined
, node
->data
);
613 node
= g_list_next (node
);
616 return g_string_free (joined
, FALSE
);
618 g_string_free (joined
, TRUE
);
623 anjuta_util_get_real_path (const gchar
*path
)
629 gchar buf
[PATH_MAX
+1];
631 result
= realpath (path
, buf
);
634 *(buf
+ PATH_MAX
) = '\0'; /* ensure a terminator */
635 return g_strdup (buf
);
639 /* the string returned by realpath should be cleaned with
640 free(), not g_free() */
641 buf
= realpath (path
, NULL
);
644 result
= g_strdup (buf
);
653 /* Dedup a list of paths - duplicates are removed from the tail.
654 ** Useful for deduping Recent Files and Recent Projects */
656 anjuta_util_glist_path_dedup(GList
*list
)
658 GList
*nlist
= NULL
, *tmp
, *tmp1
;
661 for (tmp
= list
; tmp
; tmp
= g_list_next(tmp
))
663 path
= anjuta_util_get_real_path ((const gchar
*) tmp
->data
);
666 if (stat (path
, &s
) != 0)
672 for (tmp1
= nlist
; tmp1
; tmp1
= g_list_next(tmp1
))
674 if (0 == strcmp((const char *) tmp1
->data
, path
))
682 nlist
= g_list_prepend(nlist
, path
);
686 anjuta_util_glist_strings_free(list
);
687 nlist
= g_list_reverse(nlist
);
692 sort_node (gchar
* a
, gchar
*b
)
694 if ( !a
&& !b
) return 0;
695 else if (!a
) return -1;
696 else if (!b
) return 1;
697 return strcmp (a
, b
);
700 /* Sort the list alphabatically */
702 anjuta_util_glist_strings_sort (GList
* list
)
704 return g_list_sort(list
, (GCompareFunc
)sort_node
);
707 /* Free the strings and GList */
709 anjuta_util_glist_strings_free (GList
* list
)
717 node
= g_list_next (node
);
723 anjuta_util_type_from_string (AnjutaUtilStringMap
*map
, const char *str
)
727 while (-1 != map
[i
].type
)
729 if (0 == strcmp(map
[i
].name
, str
))
737 anjuta_util_string_from_type (AnjutaUtilStringMap
*map
, int type
)
740 while (-1 != map
[i
].type
)
742 if (map
[i
].type
== type
)
750 anjuta_util_glist_from_map (AnjutaUtilStringMap
*map
)
752 GList
*out_list
= NULL
;
754 while (-1 != map
[i
].type
)
756 out_list
= g_list_append(out_list
, map
[i
].name
);
764 anjuta_util_update_string_list (GList
*p_list
, const gchar
*p_str
, gint length
)
770 for (i
= 0; i
< g_list_length (p_list
); i
++)
772 str
= (gchar
*) g_list_nth_data (p_list
, i
);
775 if (strcmp (p_str
, str
) == 0)
777 p_list
= g_list_remove (p_list
, str
);
778 p_list
= g_list_prepend (p_list
, str
);
782 p_list
= g_list_prepend (p_list
, g_strdup (p_str
));
783 while (g_list_length (p_list
) > length
)
785 str
= g_list_nth_data (p_list
, g_list_length (p_list
) - 1);
786 p_list
= g_list_remove (p_list
, str
);
793 anjuta_util_create_dir (const gchar
* d
)
795 if (g_file_test (d
, G_FILE_TEST_IS_DIR
))
803 anjuta_util_execute_shell (const gchar
*dir
, const gchar
*command
)
808 g_return_val_if_fail (command
!= NULL
, -1);
810 shell
= gnome_util_user_shell ();
816 anjuta_util_create_dir (dir
);
819 execlp (shell
, shell
, "-c", command
, NULL
);
820 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command
, shell
);
824 g_warning (_("Cannot execute command: %s (using shell %s)\n"), command
, shell
);
826 // Anjuta will take care of child exit automatically.
831 anjuta_util_convert_to_utf8 (const gchar
*str
)
833 GError
*error
= NULL
;
834 gchar
*utf8_msg_string
= NULL
;
836 g_return_val_if_fail (str
!= NULL
, NULL
);
837 g_return_val_if_fail (strlen (str
) > 0, NULL
);
839 if (g_utf8_validate(str
, -1, NULL
))
841 utf8_msg_string
= g_strdup (str
);
845 gsize rbytes
, wbytes
;
846 utf8_msg_string
= g_locale_to_utf8 (str
, -1, &rbytes
, &wbytes
, &error
);
848 g_warning ("g_locale_to_utf8 failed: %s\n", error
->message
);
849 g_error_free (error
);
850 /* g_free (utf8_msg_string);
854 return utf8_msg_string
;
858 anjuta_util_parse_args_from_string (const gchar
* string
)
862 gboolean is_quote
= FALSE
;
863 gchar
* buffer
= g_new0(gchar
, strlen(string
) + 1);
880 /* The current char was escaped */
883 } else if (*s
== '\\') {
884 /* Current char is an escape */
886 } else if (is_quote
&& *s
== quote
) {
887 /* Current char ends a quotation */
889 if (!isspace(*(s
+1)) && (*(s
+1) != '\0')) {
890 /* If there is no space after the quotation or it is not
891 the end of the string */
892 g_warning ("Parse error while parsing program arguments");
894 } else if ((*s
== '\"' || *s
== '\'')) {
896 /* Current char starts a quotation */
900 /* Just a quote char inside quote */
903 } else if (is_quote
){
904 /* Any other char inside quote */
906 } else if (isspace(*s
)) {
907 /* Any white space outside quote */
909 buffer
[idx
++] = '\0';
910 args
= g_list_append (args
, g_strdup (buffer
));
919 /* There are chars in the buffer. Flush as the last arg */
920 buffer
[idx
++] = '\0';
921 args
= g_list_append (args
, g_strdup (buffer
));
925 g_warning ("Unclosed quotation encountered at the end of parsing");
931 anjuta_util_escape_quotes(const gchar
* str
)
935 const gchar
*s
= str
;
937 g_return_val_if_fail(str
, NULL
);
940 /* We are assuming there will be less than 2048 chars to escape */
941 max_size
= strlen(str
) + 2048;
942 buffer
= g_new (gchar
, max_size
);
948 if (*s
== '\"' || *s
== '\'' || *s
== '\\')
949 buffer
[idx
++] = '\\';
957 /* Diff the text contained in uri with text. Return true if files
958 differ, FALSE if they are identical.
959 FIXME: Find a better algorithm, this seems ineffective */
961 gboolean
anjuta_util_diff(const gchar
* uri
, const gchar
* text
)
963 GnomeVFSFileSize bytes_read
;
965 GnomeVFSFileInfo info
;
966 GnomeVFSHandle
* handle
= NULL
;
968 gnome_vfs_get_file_info(uri
, &info
, GNOME_VFS_FILE_INFO_DEFAULT
);
970 if (info
.size
== 0 && text
== NULL
)
972 else if (info
.size
== 0 || text
== NULL
)
975 file_text
= g_new0(gchar
, info
.size
+ 1);
977 if (gnome_vfs_open(&handle
, uri
, GNOME_VFS_OPEN_READ
!= GNOME_VFS_OK
))
980 if ((gnome_vfs_read(handle
, file_text
, info
.size
, &bytes_read
) == GNOME_VFS_OK
)
981 && (bytes_read
== info
.size
))
983 gnome_vfs_close(handle
);
985 if ((g_utf8_strlen(file_text
, -1) == g_utf8_strlen(text
, -1))
986 && strcmp(file_text
, text
) == 0)
992 gnome_vfs_close(handle
);
998 anjuta_util_path_has_extension (const gchar
*path
, const gchar
*ext
)
1000 if (strlen (path
) <= strlen (ext
))
1002 if ((path
[strlen (path
) - strlen (ext
) - 1] == '.') &&
1003 (strcmp (&path
[strlen (path
) - strlen (ext
)], ext
) == 0))
1009 anjuta_util_get_uri_mime_type (const gchar
*uri
)
1011 GnomeVFSURI
*vfs_uri
;
1015 g_return_val_if_fail (uri
!= NULL
, NULL
);
1017 vfs_uri
= gnome_vfs_uri_new (uri
);
1019 path
= gnome_vfs_uri_get_path (vfs_uri
);
1023 /* If Anjuta is not installed in system gnome prefix, the mime types
1024 * may not have been correctly registed. In that case, we use the
1025 * following mime detection
1029 mime_type
= gnome_vfs_get_slow_mime_type (uri
);
1031 else if (anjuta_util_path_has_extension (path
, "anjuta"))
1033 mime_type
= g_strdup ("application/x-anjuta");
1035 else if (anjuta_util_path_has_extension (path
, "prj"))
1037 mime_type
= g_strdup ("application/x-anjuta-old");
1039 else if (anjuta_util_path_has_extension (path
, "ui"))
1041 mime_type
= g_strdup ("text/xml");
1043 else if (anjuta_util_path_has_extension (path
, "glade"))
1045 mime_type
= g_strdup ("application/x-glade");
1049 mime_type
= gnome_vfs_get_slow_mime_type (uri
);
1053 gnome_vfs_uri_unref (vfs_uri
);
1057 #ifndef HAVE_LIBUTIL
1060 static int ptym_open (char *pts_name
);
1061 static int ptys_open (int fdm
, char * pts_name
);
1064 login_tty(int ttyfd
)
1076 /* First disconnect from the old controlling tty. */
1078 fd
= open("/dev/tty", O_RDWR
|O_NOCTTY
);
1081 ioctl(fd
, TIOCNOTTY
, NULL
);
1085 //syslog(LOG_WARNING, "NO CTTY");
1086 #endif /* TIOCNOTTY */
1088 /* Verify that we are successfully disconnected from the controlling tty. */
1089 fd
= open("/dev/tty", O_RDWR
|O_NOCTTY
);
1092 //syslog(LOG_WARNING, "Failed to disconnect from controlling tty.");
1096 /* Make it our controlling tty. */
1098 ioctl(ttyfd
, TIOCSCTTY
, NULL
);
1099 #endif /* TIOCSCTTY */
1101 fdname
= ttyname (ttyfd
);
1102 fd
= open(fdname
, O_RDWR
);
1104 ;//syslog(LOG_WARNING, "open %s: %s", fdname, strerror(errno));
1108 /* Verify that we now have a controlling tty. */
1109 fd
= open("/dev/tty", O_WRONLY
);
1112 //syslog(LOG_WARNING, "open /dev/tty: %s", strerror(errno));
1117 #if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
1119 RETSIGTYPE (*sig
)();
1120 sig
= signal(SIGHUP
, SIG_IGN
);
1122 signal(SIGHUP
, sig
);
1125 fd
= open(fdname
, O_RDWR
);
1128 //syslog(LOG_ERR, "can't reopen ctty %s: %s", fdname, strerror(errno));
1150 openpty(int *amaster
, int *aslave
, char *name
, struct termios
*termp
,
1151 struct winsize
*winp
)
1154 *amaster
= ptym_open(line
);
1157 *aslave
= ptys_open(*amaster
, line
);
1165 #define TCSAFLUSH TCSETAF
1168 (void) tcsetattr(*aslave
, TCSAFLUSH
, termp
);
1171 (void) ioctl(*aslave
, TIOCSWINSZ
, (char *)winp
);
1177 ptym_open(char * pts_name
)
1183 strcpy(pts_name
, "/dev/ptmx");
1184 fdm
= open(pts_name
, O_RDWR
);
1187 if (grantpt(fdm
) < 0) { /* grant access to slave */
1191 if (unlockpt(fdm
) < 0) { /* clear slave's lock flag */
1196 if (ptr
== NULL
) { /* get slave's name */
1200 strcpy(pts_name
, ptr
); /* return name of slave */
1201 return fdm
; /* return fd of master */
1205 strcpy(pts_name
, "/dev/ptyXY");
1206 /* array index: 012345689 (for references in following code) */
1207 for (ptr1
= "pqrstuvwxyzPQRST"; *ptr1
!= 0; ptr1
++) {
1208 pts_name
[8] = *ptr1
;
1209 for (ptr2
= "0123456789abcdef"; *ptr2
!= 0; ptr2
++) {
1210 pts_name
[9] = *ptr2
;
1211 /* try to open master */
1212 fdm
= open(pts_name
, O_RDWR
);
1214 if (errno
== ENOENT
) /* different from EIO */
1215 return -1; /* out of pty devices */
1217 continue; /* try next pty device */
1219 pts_name
[5] = 't'; /* chage "pty" to "tty" */
1220 return fdm
; /* got it, return fd of master */
1223 return -1; /* out of pty devices */
1228 ptys_open(int fdm
, char * pts_name
)
1232 /* following should allocate controlling terminal */
1233 fds
= open(pts_name
, O_RDWR
);
1238 if (ioctl(fds
, I_PUSH
, "ptem") < 0) {
1243 if (ioctl(fds
, I_PUSH
, "ldterm") < 0) {
1248 if (ioctl(fds
, I_PUSH
, "ttcompat") < 0) {
1254 if (ioctl(fdm
, I_PUSH
, "pckt") < 0) {
1260 if (ioctl(fdm
, I_SRDOPT
, RMSGN
|RPROTDAT
) < 0) {
1269 struct group
*grptr
;
1271 grptr
= getgrnam("tty");
1273 gid
= grptr
->gr_gid
;
1275 gid
= -1; /* group tty is not in the group file */
1276 /* following two functions don't work unless we're root */
1277 chown(pts_name
, getuid(), gid
);
1278 chmod(pts_name
, S_IRUSR
| S_IWUSR
| S_IWGRP
);
1279 fds
= open(pts_name
, O_RDWR
);
1289 forkpty(int *amaster
, char *name
, struct termios
*termp
, struct winsize
*winp
)
1291 int master
, slave
, pid
;
1293 if (openpty(&master
, &slave
, name
, termp
, winp
) == -1)
1295 switch (pid
= fork()) {
1314 int scandir(const char *dir
, struct dirent
***namelist
,
1315 int (*select
)(const struct dirent
*),
1316 int (*compar
)(const struct dirent
**, const struct dirent
**))
1319 struct dirent
*entry
;
1323 if ((d
=opendir(dir
)) == NULL
)
1327 while ((entry
=readdir(d
)) != NULL
)
1329 if (select
== NULL
|| (select
!= NULL
&& (*select
)(entry
)))
1331 *namelist
=(struct dirent
**)realloc((void *)(*namelist
),
1332 (size_t)((i
+1)*sizeof(struct dirent
*)));
1333 if (*namelist
== NULL
) return(-1);
1334 entrysize
=sizeof(struct dirent
)-sizeof(entry
->d_name
)+strlen(entry
->d_name
)+1;
1335 (*namelist
)[i
]=(struct dirent
*)malloc(entrysize
);
1336 if ((*namelist
)[i
] == NULL
) return(-1);
1337 memcpy((*namelist
)[i
], entry
, entrysize
);
1341 if (closedir(d
)) return(-1);
1342 if (i
== 0) return(-1);
1344 qsort((void *)(*namelist
), (size_t)i
, sizeof(struct dirent
*), compar
);
1349 #endif /* HAVE_LIBUTIL */
1352 anjuta_util_help_display (GtkWindow
*parent
,
1353 const gchar
*doc_id
,
1354 const gchar
*file_name
)
1357 GError
*error
= NULL
;
1361 const gchar
* const *langs
;
1365 g_return_if_fail (file_name
!= NULL
);
1367 langs
= g_get_language_names ();
1368 for (i
= 0; langs
[i
]; i
++)
1371 if (strchr (lang
, '.'))
1374 uri
= g_build_filename (DATADIR
, "/gnome/help/", doc_id
,
1375 lang
, file_name
, NULL
);
1377 if (g_file_test (uri
, G_FILE_TEST_EXISTS
)) {
1386 anjuta_util_dialog_error (parent
, _("Unable to display help. Please make sure Anjuta "
1387 "documentation package is install. It can be downloaded "
1388 "from http://anjuta.org"));
1393 command
= g_strconcat ("gnome-help ghelp://", uri
, NULL
);
1396 screen
= gtk_widget_get_screen (GTK_WIDGET (parent
));
1397 gdk_spawn_command_line_on_screen (screen
, command
, &error
);
1400 g_warning ("Error executing help application: %s",
1402 g_error_free (error
);
1410 * anjuta_utils_get_user_config_dir:
1412 * Returns a base directory in which to store user-specific application
1413 * configuration information such as user preferences and settings.
1415 * Return value: a new allocated string with the user config directory.
1418 anjuta_util_get_user_config_dir ()
1422 folder
= g_build_filename (g_get_user_config_dir (), "anjuta", NULL
);
1424 if (!g_file_test (folder
, G_FILE_TEST_IS_DIR
))
1426 if (g_mkdir (folder
, 755) == -1)
1428 g_warning ("There was an error creating the Anjuta config directory");