clean code and changed version nro.
[irreco.git] / irreco / src / util / irreco_misc.c
blob7f78946b59ea9c2096920a757476f085a33a5908
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi),
4 * Harri Vattulainen (t5vaha01@students.oamk.fi)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (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 Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "irreco_util.h"
24 #include <sys/socket.h>
25 #include <errno.h>
27 /**
28 * @addtogroup IrrecoMisc
29 * @ingroup IrrecoUtil
31 * All kinds of usefull stuff that isnt really part of Irreco. Does not
32 * pull any other Irreco headers, so it can be safely included inside backends.
34 * @{
37 /**
38 * @file
39 * Source file of @ref IrrecoMisc.
42 * Utility functions.
44 * All kinds of usefull stuff that isnt really part of Irreco. Does not pull
45 * any other Irreco headers, so it can be safely included inside backends.
48 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
49 /* Public Functions */
50 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
54 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
55 /* Files and directories. */
56 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
58 /**
59 * @name Files and directories
60 * @{
63 /**
64 * Check if the given filename is a directory.
66 int irreco_is_dir(const char *filename)
68 int rval;
69 struct stat buf;
70 char *realpath = canonicalize_file_name(filename);
71 rval = (realpath != NULL) &&
72 (stat(filename, &buf) == 0) &&
73 S_ISDIR(buf.st_mode);
74 free(realpath);
75 return rval;
78 /**
79 * Check if a given file is a regular file.
81 int irreco_is_file(const char *filename)
83 int rval;
84 struct stat buf;
85 char *realpath = canonicalize_file_name(filename);
86 rval = (realpath != NULL) &&
87 (stat(filename, &buf) == 0) &&
88 S_ISREG(buf.st_mode);
89 free(realpath);
90 return rval;
93 /**
94 * Does the the file or dir exists.
96 int irreco_file_exists(const char *filename)
98 struct stat struct_stat;
99 if (stat(filename, &struct_stat) == 0) {
100 return TRUE;
102 return FALSE;
106 * Return length of file
107 * Return 0 if file doesn't exist
109 gint irreco_file_length(const gchar *filename)
111 struct stat struct_stat;
113 if(!irreco_file_exists(filename)) {
114 return 0;
117 stat(filename, &struct_stat);
118 return struct_stat.st_size;
122 * Write data to file.
124 gboolean irreco_write_file(const gchar * file, const gchar * data,
125 gsize data_size)
127 FILE *handle;
128 size_t written;
129 IRRECO_ENTER
131 if ((handle = fopen(file, "w")) == NULL) {
132 IRRECO_ERROR("Failed to open \"%s\" for writing.\n", file);
133 IRRECO_RETURN_BOOL(FALSE);
136 written = fwrite(data, sizeof(gchar), data_size, handle);
137 fclose(handle);
139 if (written != data_size) {
140 IRRECO_ERROR("Failed to write data to \"%s\". "
141 "Data size \"%u\", wrote \"%u\".\n",
142 file, data_size, written);
143 IRRECO_RETURN_BOOL(FALSE);
145 IRRECO_RETURN_BOOL(TRUE);
149 * Read contents of file into a buffer, or at least as much of the file the
150 * buffer can contain.
152 gboolean irreco_read_text_file(const gchar * file, gchar *buffer,
153 gsize buffer_size)
155 gint count;
156 FILE *fd;
158 buffer[0] = '\0';
159 if ((fd = fopen(file, "r")) == NULL) return FALSE;
160 count = fread(buffer, 1, buffer_size, fd);
161 buffer[count] = '\0';
162 if (count < 1) return FALSE;
163 return TRUE;
167 * Read contents of binary file into a buffer, or at least as much of the file the
168 * buffer can contain.
170 gboolean irreco_read_binary_file(const gchar *file, guchar *buffer,
171 gsize buffer_size, gint *binlen)
173 gint count;
174 FILE *fd;
176 if ((fd = g_fopen(file, "rb")) == NULL) return FALSE;
177 count = (gint) fread(buffer, 1, buffer_size, fd);
178 fclose(fd);
179 if (count < 1) return FALSE;
180 *binlen = count;
181 return TRUE;
185 * Read a line of text from file to buffer.
187 gboolean irreco_read_line(const gchar * file, gchar *buffer,
188 gsize buffer_size)
190 gint i;
192 if (!irreco_read_text_file(file, buffer, buffer_size)) return FALSE;
193 for (i = 0; i < buffer_size; i++) {
194 if (buffer[i] == '\0' || buffer[i] == '\n') {
195 buffer[i] = '\0';
196 return TRUE;
199 return TRUE;
203 * Write GKeyFile contents to file.
205 gboolean irreco_write_keyfile(GKeyFile * keyfile, const gchar * file)
207 gchar *data;
208 gsize data_size;
209 GError *error = NULL;
210 gboolean success;
211 IRRECO_ENTER
213 data = g_key_file_to_data(keyfile, &data_size, &error);
214 if (irreco_gerror_check_print(&error)) {
215 IRRECO_RETURN_BOOL(FALSE);
218 success = irreco_write_file(file, data, data_size);
219 g_free(data);
220 IRRECO_RETURN_BOOL(success);
224 * Read all filenames that match suffix from directory.
226 gboolean irreco_dir_foreach(IrrecoDirForeachData *dir_data,
227 IrrecoDirForeachCallback callback)
229 GError *error = NULL;
230 GDir* dir = NULL;
231 IRRECO_ENTER
233 /* Open Dir. */
234 dir = g_dir_open(dir_data->directory, 0, &error);
235 if (irreco_gerror_check_print(&error)) {
236 IRRECO_ERROR("Could not read directory: \"%s\"\n",
237 dir_data->directory);
238 g_dir_close(dir);
239 IRRECO_RETURN_BOOL(FALSE);
242 /* Read dir. */
243 while ((dir_data->filename = g_dir_read_name(dir)) != NULL) {
244 if (g_str_has_suffix(dir_data->filename,
245 dir_data->filesuffix)) {
246 dir_data->filepath = g_build_path("/",
247 dir_data->directory, dir_data->filename, NULL);
248 callback(dir_data);
249 g_free((void*)dir_data->filepath);
252 g_dir_close(dir);
253 IRRECO_RETURN_BOOL(TRUE);
259 * Read all filenames that match suffix.
260 * Searches ONLY thru subdirectories.
262 gboolean irreco_dir_foreach_subdirectories(IrrecoDirForeachData *dir_data,
263 IrrecoDirForeachCallback callback)
265 GError *error = NULL;
266 GDir *dir = NULL;
267 GDir *subdir = NULL;
268 gchar *subpath = NULL;
269 const gchar *buttonsdir;
270 const gchar *directorykeeper = dir_data->directory;
271 IRRECO_ENTER
273 /* Open Dir. */
274 dir = g_dir_open(dir_data->directory, 0, &error);
275 if (irreco_gerror_check_print(&error)) {
276 IRRECO_ERROR("Could not read directory: \"%s\"\n",
277 dir_data->directory);
278 IRRECO_RETURN_BOOL(FALSE);
281 /* Read buttons dir file by file (also directories) */
282 while ((buttonsdir = g_dir_read_name(dir)) != NULL) {
284 /* Create possible subpath from readed files */
285 subpath = g_build_path("/", dir_data->directory,
286 buttonsdir, NULL);
288 /* Test if subpath is folder */
289 if(g_file_test(subpath, G_FILE_TEST_IS_DIR)) {
291 /* Create GDir from directory or multifail instantly */
292 subdir = g_dir_open(subpath, 0, &error);
293 if (irreco_gerror_check_print(&error)) {
294 IRRECO_ERROR("Could not read dir: \"%s\"\n",
295 subpath);
296 g_free(subpath);
297 g_dir_close(dir);
298 IRRECO_RETURN_BOOL(FALSE);
301 /* Start reading files from subdirectory */
302 while ((dir_data->filename = g_dir_read_name(subdir))
303 != NULL) {
305 /* Find files with wanted suffix */
306 if (g_str_has_suffix(dir_data->filename,
307 dir_data->filesuffix)) {
309 dir_data->filepath = g_build_path("/",
310 subpath,
311 dir_data->filename,
312 NULL);
313 dir_data->directory = subpath;
314 callback(dir_data);
315 dir_data->directory = directorykeeper;
316 g_free((void*)dir_data->filepath);
320 g_free(subpath);
321 subpath = NULL;
322 g_dir_close(subdir);
323 subdir = NULL;
325 if(dir != NULL) g_dir_close(dir);
326 if(subdir != NULL) g_dir_close(subdir);
327 if(subpath != NULL) g_free(subpath);
328 IRRECO_RETURN_BOOL(TRUE);
332 * Create path to directory $HOME/.APP_NAME, and attempt to create the
333 * directory if it does not exists.
335 * @return Directory path inside a newly allocated string,
336 * or NULL if the directory could not be created.
338 gchar * irreco_get_config_dir(const gchar * app_name)
340 GString *app_name_with_dot;
341 gchar *home;
342 gchar *apphome;
343 IRRECO_ENTER
345 if ((home = getenv("HOME")) == NULL) IRRECO_RETURN_PTR(NULL);
347 app_name_with_dot = g_string_new(".");
348 g_string_append(app_name_with_dot, app_name);
349 apphome = g_build_path("/", home, app_name_with_dot->str, NULL);
350 g_string_free(app_name_with_dot, TRUE);
352 if (irreco_is_dir(apphome) == TRUE
353 || g_mkdir(apphome, 0700) == 0)
354 IRRECO_RETURN_PTR(apphome);
356 g_free(apphome);
357 IRRECO_RETURN_PTR(NULL);
361 * Get path to $HOME/.APP_NAME/FILE
363 * @return Newly allocated string which contains path to config file or NULL.
365 gchar * irreco_get_config_file(const gchar * app_name, const gchar * file)
367 gchar *config_dir;
368 gchar *config_file;
369 IRRECO_ENTER
371 if ((config_dir = irreco_get_config_dir(app_name)) != NULL) {
372 config_file = g_build_path("/", config_dir, file, NULL);
373 g_free(config_dir);
374 IRRECO_RETURN_PTR(config_file);
376 IRRECO_RETURN_PTR(NULL);
379 /** @} */
383 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
384 /* Strings. */
385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
388 * @name Strings
389 * @{
393 * Replace characters.
395 void irreco_char_replace(gchar * string, gchar what, gchar with)
397 gint i;
398 IRRECO_ENTER
399 for (i = 0; string[i] != '\0'; i++) {
400 if (string[i] == what) {
401 string[i] = with;
404 IRRECO_RETURN
408 * Find first occurrence of character inside string.
410 * @return Position of character or -1.
412 gint irreco_char_pos(const gchar * string, gchar what)
414 gint i;
415 IRRECO_ENTER
417 for (i = 0; string[i] != '\0'; i++) {
418 if (string[i] == what) {
419 IRRECO_RETURN_INT(i);
422 IRRECO_RETURN_INT(-1);
426 * Check if the string is empty.
428 * String is empty if it is:
429 * @li NULL
430 * @li ""
431 * @li Full of space characters.
433 gboolean irreco_str_isempty(const gchar * string)
435 IRRECO_ENTER
437 if (string == NULL || string[0] == '\0') IRRECO_RETURN_BOOL(TRUE);
438 do {
439 if (g_unichar_isspace(g_utf8_get_char(string)) == FALSE) {
440 IRRECO_RETURN_BOOL(FALSE);
442 printf("\"%s\" %p\n", string, string);
443 } while ((string = g_utf8_find_next_char(string, NULL)) != NULL
444 && string[0] != '\0');
446 IRRECO_RETURN_BOOL(TRUE);
450 * Copy C-string into GString.
452 void irreco_gstring_set(GString * g_str, const gchar * c_str)
454 IRRECO_ENTER
456 if (c_str == NULL) {
457 g_string_assign(g_str, "");
458 } else {
459 g_string_assign(g_str, c_str);
462 IRRECO_RETURN
466 * Copy C-string into GString and free C-string.
468 void irreco_gstring_set_and_free(GString * g_str, gchar * c_str)
470 IRRECO_ENTER
472 if (c_str == NULL) {
473 g_string_assign(g_str, "");
474 } else {
475 g_string_assign(g_str, c_str);
476 g_free(c_str);
479 IRRECO_RETURN
482 /** @} */
485 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
486 /* Error handling. */
487 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
490 * @name Error handling
491 * @{
496 * If GError is set, print message, release GError, and return TRUE.
497 * Otherwise returns FALSE.
499 gboolean irreco_gerror_check_print(GError ** error)
501 if (*error != NULL) {
502 IRRECO_PRINTF("GError: %s\n", (*error)->message);
503 g_error_free(*error);
504 *error = NULL;
505 return TRUE;
507 return FALSE;
511 * If GError is set, free it, and return TRUE.
512 * Otherwise returns FALSE.
514 gboolean irreco_gerror_check_free(GError ** error)
516 if (*error != NULL) {
517 g_error_free(*error);
518 *error = NULL;
519 return TRUE;
521 return FALSE;
524 /** @} */
526 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
527 /* GTK. */
528 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
531 * @name GTK
532 * @{
536 * Show info popup.
538 void irreco_info_dlg(GtkWindow * parent_window, const gchar * message)
540 GtkWidget* dialog;
541 IRRECO_ENTER
543 dialog = gtk_message_dialog_new(parent_window,
544 GTK_DIALOG_DESTROY_WITH_PARENT,
545 GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", message);
546 gtk_dialog_run(GTK_DIALOG(dialog));
547 gtk_widget_destroy(dialog);
549 IRRECO_RETURN
553 * Show error popup.
555 void irreco_error_dlg(GtkWindow * parent_window, const gchar * message)
557 GtkWidget* dialog;
558 IRRECO_ENTER
560 dialog = gtk_message_dialog_new(parent_window,
561 GTK_DIALOG_DESTROY_WITH_PARENT,
562 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", message);
563 gtk_dialog_run(GTK_DIALOG(dialog));
564 gtk_widget_destroy(dialog);
566 IRRECO_RETURN
570 * Format message, and show error popup.
572 void irreco_info_dlg_printf(GtkWindow * parent_window,
573 const gchar * format, ...)
575 gint rvalue;
576 va_list args;
577 gchar *message = NULL;
578 IRRECO_ENTER
580 va_start(args, format);
581 rvalue = g_vasprintf(&message, format, args);
582 va_end(args);
584 if (rvalue > 0) {
585 irreco_info_dlg(parent_window, message);
586 g_free(message);
587 } else {
588 IRRECO_ERROR("Could not format message.\n");
591 IRRECO_RETURN
595 * Format message, and show error popup.
597 void irreco_error_dlg_printf(GtkWindow * parent_window,
598 const gchar * format, ...)
600 gint rvalue;
601 va_list args;
602 gchar *message = NULL;
603 IRRECO_ENTER
605 va_start(args, format);
606 rvalue = g_vasprintf(&message, format, args);
607 va_end(args);
609 if (rvalue > 0) {
610 irreco_error_dlg(parent_window, message);
611 g_free(message);
612 } else {
613 IRRECO_ERROR("Could not format message.\n");
616 IRRECO_RETURN
620 * Popup yes / no dialog.
622 * Returns: TRUE if user click YES, FALSE otherwise.
624 gboolean irreco_yes_no_dlg(GtkWindow * parent_window, const gchar * message)
626 gint responce;
627 GtkWidget* dialog;
628 IRRECO_ENTER
630 dialog = gtk_message_dialog_new(parent_window,
631 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
632 GTK_BUTTONS_YES_NO, "%s", message);
633 responce = gtk_dialog_run(GTK_DIALOG(dialog));
634 gtk_widget_destroy(dialog);
635 IRRECO_RETURN_BOOL(responce == GTK_RESPONSE_YES);
639 * Convenience frapper of gtk_alignment_new().
641 GtkWidget *irreco_gtk_align(GtkWidget *child,
642 gfloat xalign,
643 gfloat yalign,
644 gfloat xscale,
645 gfloat yscale,
646 guint padding_top,
647 guint padding_bottom,
648 guint padding_left,
649 guint padding_right)
651 GtkWidget *align;
652 IRRECO_ENTER
654 align = gtk_alignment_new(xalign, yalign, xscale, yscale);
655 gtk_alignment_set_padding(GTK_ALIGNMENT(align), padding_top,
656 padding_bottom, padding_left, padding_right);
657 gtk_container_add(GTK_CONTAINER(align), child);
658 IRRECO_RETURN_PTR(align);
662 * Create, align, and pad label.
664 GtkWidget *irreco_gtk_label(const gchar * str,
665 gfloat xalign,
666 gfloat yalign,
667 guint padding_top,
668 guint padding_bottom,
669 guint padding_left,
670 guint padding_right)
672 GtkWidget *label;
673 IRRECO_ENTER
675 label = gtk_label_new(str);
676 gtk_misc_set_alignment(GTK_MISC(label), xalign, yalign);
677 IRRECO_RETURN_PTR(irreco_gtk_pad(label, padding_top, padding_bottom,
678 padding_left, padding_right));
682 * Create, align, and pad a label with bold text.
684 GtkWidget *irreco_gtk_label_bold(const gchar * str,
685 gfloat xalign,
686 gfloat yalign,
687 guint padding_top,
688 guint padding_bottom,
689 guint padding_left,
690 guint padding_right)
692 gchar* markup;
693 GtkWidget *label;
694 IRRECO_ENTER
696 label = irreco_gtk_label(NULL, xalign, yalign, padding_top,
697 padding_bottom, padding_left, padding_right);
698 markup = g_markup_printf_escaped("<b>%s</b>", str);
699 gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(label))),
700 markup);
701 g_free(markup);
702 IRRECO_RETURN_PTR(label);
706 * Get button widget for dialog buttons.
708 * @param dialog GtkDialog
709 * @param n Index of button to get.
711 GtkWidget *irreco_gtk_dialog_get_button(GtkWidget *dialog, guint n)
714 GtkBox *action_area;
715 GtkBoxChild *box_child;
716 guint length;
717 IRRECO_ENTER
719 action_area = GTK_BOX(GTK_DIALOG(dialog)->action_area);
720 length = g_list_length(action_area->children);
722 if (n >= length) {
723 IRRECO_ERROR("Cant get button \"%i\". "
724 "Dialog has only \"%i\" buttons", n, length);
725 IRRECO_RETURN_PTR(NULL);
728 box_child = (GtkBoxChild *) g_list_nth_data(g_list_first(
729 action_area->children), n);
730 IRRECO_RETURN_PTR(box_child->widget);
733 GtkWindow *irreco_gtk_get_parent_window(GtkWidget *widget)
735 GtkWidget *parent;
736 IRRECO_ENTER
738 parent = gtk_widget_get_toplevel(widget);
739 if (GTK_WIDGET_TOPLEVEL(parent) != TRUE
740 || GTK_IS_WINDOW(parent) != TRUE) {
741 IRRECO_RETURN_PTR(GTK_WINDOW(parent));
743 IRRECO_RETURN_PTR(NULL);
747 * This function is a modified version of gtk_dialog_new_empty() from GTK
748 * sources, which is used to by gtk_dialog_new_with_buttons() to set the
749 * settings of a dialog.
751 void irreco_gtk_dialog_set(GtkDialog *dialog,
752 const gchar *title,
753 GtkWindow *parent,
754 GtkDialogFlags flags)
756 IRRECO_ENTER
758 if (title)
759 gtk_window_set_title(GTK_WINDOW (dialog), title);
761 if (parent)
762 gtk_window_set_transient_for(GTK_WINDOW (dialog), parent);
764 if (flags & GTK_DIALOG_MODAL)
765 gtk_window_set_modal(GTK_WINDOW (dialog), TRUE);
767 if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
768 gtk_window_set_destroy_with_parent(GTK_WINDOW (dialog), TRUE);
770 if (flags & GTK_DIALOG_NO_SEPARATOR)
771 gtk_dialog_set_has_separator(dialog, FALSE);
773 IRRECO_RETURN
776 /** @} */
778 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
779 /* Time. */
780 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
783 * @name Time
784 * @{
789 * Do not use, use GTimer instead.
791 * @deprecated
793 * Difference of time in microseconds between two GTimeVals.
794 * This works fine as long as the difference is no more than 2146 seconds.
796 glong irreco_time_diff(GTimeVal *start, GTimeVal *end)
798 GTimeVal diff;
799 IRRECO_ENTER
801 diff.tv_sec = end->tv_sec - start->tv_sec;
802 diff.tv_usec = end->tv_usec - start->tv_usec;
804 /* We run out of space in ulong after 2147 seconds. */
805 if (diff.tv_sec >= G_MAXLONG / IRRECO_SECOND_IN_USEC) {
806 IRRECO_RETURN_LONG((G_MAXLONG / IRRECO_SECOND_IN_USEC)
807 * IRRECO_SECOND_IN_USEC);
810 IRRECO_RETURN_LONG(diff.tv_sec * IRRECO_SECOND_IN_USEC + diff.tv_usec);
813 /** @} */
815 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
816 /* Socket. */
817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
820 * @name Socket
821 * @{
825 * Check if the socket is valid.
827 gboolean irreco_is_socket_valid(int socket)
829 gint optval;
830 socklen_t optlen;
831 gint rvalue;
832 IRRECO_ENTER
834 /* This should succeed if socket is valid. */
835 rvalue = getsockopt(socket, SOL_SOCKET, SOCK_STREAM, &optval, &optlen);
837 if (rvalue == 0) {
838 IRRECO_RETURN_BOOL(TRUE);
839 } else {
841 /* glibc docs say these are the possible error values. */
842 switch (errno) {
843 case EBADF: IRRECO_PRINTF("Error: EBADF\n"); break;
844 case ENOTSOCK: IRRECO_PRINTF("Error: ENOTSOCK\n"); break;
845 case ENOPROTOOPT: IRRECO_PRINTF("Error: ENOPROTOOPT\n"); break;
846 default: IRRECO_PRINTF("Error: Unknown\n"); break;
849 IRRECO_RETURN_BOOL(FALSE);
853 /** @} */
855 /** @} */