--- linphone-3.5.2.orig/gtk/main.c 2012-12-26 10:29:12.521835222 -0500 +++ linphone-3.5.2/gtk/main.c 2012-12-26 11:38:40.804443105 -0500 @@ -1632,6 +1632,138 @@ } #endif +// unix signal handler + +static int signal_pipe[2]; + +static void pipe_signals(int signal) +{ + if(write(signal_pipe[1], &signal, sizeof(int)) != sizeof(int)) + { + fprintf(stderr, "unix signal %d lost\n", signal); + } +} + +static gboolean deliver_signal(GIOChannel *source, GIOCondition cond, gpointer d) +{ + GError *error = NULL; /* for error handling */ + + /* + * There is no g_io_channel_read or g_io_channel_read_int, so we read + * char's and use a union to recover the unix signal number. + */ + union { + gchar chars[sizeof(int)]; + int signal; + } buf; + GIOStatus status; /* save the reading status */ + gsize bytes_read; /* save the number of chars read */ + + /* + * Read from the pipe as long as data is available. The reading end is + * also in non-blocking mode, so if we have consumed all unix signals, + * the read returns G_IO_STATUS_AGAIN. + */ + while((status = g_io_channel_read_chars(source, buf.chars, + sizeof(int), &bytes_read, &error)) == G_IO_STATUS_NORMAL) + { + g_assert(error == NULL); /* no error if reading returns normal */ + + /* + * There might be some problem resulting in too few char's read. + * Check it. + */ + if(bytes_read != sizeof(int)){ + fprintf(stderr, "lost data in signal pipe (expected %d, received %d)\n", + (int)sizeof(int), (int)bytes_read); + continue; /* discard the garbage and keep fingers crossed */ + } + + /* Ok, we read a unix signal number, answer the call (if any) */ + fprintf(stderr, "===== received signal %d\n", buf.signal); + linphone_gtk_answer_clicked(NULL); + } + + /* + * Reading from the pipe has not returned with normal status. Check for + * potential errors and return from the callback. + */ + if(error != NULL){ + fprintf(stderr, "reading signal pipe failed: %s\n", error->message); + exit(1); + } + if(status == G_IO_STATUS_EOF){ + fprintf(stderr, "signal pipe has been closed\n"); + exit(1); + } + + g_assert(status == G_IO_STATUS_AGAIN); + + return (TRUE); /* keep the event source */ +} + +static void setup_answer_handler() { + int fd_flags; + GIOChannel *g_signal_in; + GError *error = NULL; /* handle errors */ + + /* + * Set the unix signal handling up. + * First create a pipe. + */ + if(pipe(signal_pipe)) { + perror("pipe"); + exit(1); + } + + /* + * put the write end of the pipe into nonblocking mode, + * need to read the flags first, otherwise we would clear other flags too. + */ + fd_flags = fcntl(signal_pipe[1], F_GETFL); + if(fd_flags == -1) + { + perror("read descriptor flags"); + exit(1); + } + if(fcntl(signal_pipe[1], F_SETFL, fd_flags | O_NONBLOCK) == -1) + { + perror("write descriptor flags"); + exit(1); + } + + /* Install the unix signal handler pipe_signals for the signals of interest */ + signal(SIGUSR1, pipe_signals); + + /* convert the reading end of the pipe into a GIOChannel */ + g_signal_in = g_io_channel_unix_new(signal_pipe[0]); + /* + * we only read raw binary data from the pipe, + * therefore clear any encoding on the channel + */ + g_io_channel_set_encoding(g_signal_in, NULL, &error); + if(error != NULL){ /* handle potential errors */ + fprintf(stderr, "g_io_channel_set_encoding failed %s\n", + error->message); + exit(1); + } + + /* put the reading end also into non-blocking mode */ + g_io_channel_set_flags(g_signal_in, + g_io_channel_get_flags(g_signal_in) | G_IO_FLAG_NONBLOCK, &error); + + if(error != NULL){ /* tread errors */ + fprintf(stderr, "g_io_set_flags failed %s\n", + error->message); + exit(1); + } + + /* register the reading end with the event loop */ + g_io_add_watch(g_signal_in, G_IO_IN | G_IO_PRI, deliver_signal, NULL); + +} + + int main(int argc, char *argv[]){ #ifdef ENABLE_NLS void *p; @@ -1764,6 +1896,8 @@ if (linphone_gtk_get_ui_config_int("update_check_menu",0)==0) linphone_gtk_check_for_new_version(); + setup_answer_handler(); + gtk_main(); linphone_gtk_quit(); #ifndef HAVE_GTK_OSX