Mercurial > pidgin.yaz
changeset 28887:4b3ef6752037
merged with im.pidgin.pidgin
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Fri, 06 Nov 2009 17:23:40 +0900 |
parents | 9d17b1c09193 (current diff) 9d6e1327f614 (diff) |
children | 08a52bdd9619 |
files | libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h |
diffstat | 13 files changed, 190 insertions(+), 121 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYRIGHT Wed Nov 04 17:03:05 2009 +0900 +++ b/COPYRIGHT Fri Nov 06 17:23:40 2009 +0900 @@ -268,6 +268,7 @@ Ambrose C. Li Nicolas Lichtmaier Wesley Lin +Shaun Lindsay Artem Litvinovich Josh Littlefield Daniel Ljungborg
--- a/ChangeLog Wed Nov 04 17:03:05 2009 +0900 +++ b/ChangeLog Fri Nov 06 17:23:40 2009 +0900 @@ -1,3 +1,4 @@ + Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.6.4 (??/??/20??): @@ -16,6 +17,8 @@ * More detailed error messages when messages fail to send. (Aman Gupta) * The simultaneous login account option is respected when using the clientLogin authentication method. + * Fix offline message retrieval (broken in 2.6.3) + * Fix SSL when clientLogin is enabled. MSN: * Don't forget display names for buddies. @@ -23,6 +26,9 @@ * Fix more FQY 240 connection errors. * Fix a crash that could occur when adding a buddy. * Fix an occasional crash when sending message to an offline user. + * Fix a random crash that might occur when idle. + * Fix a crash when logging in with some long non-ASCII passwords. + (Shaun Lindsay) XMPP: * Users connecting to Google Talk now have an "Initiate Chat" context menu @@ -30,10 +36,10 @@ * Fix a crash when attempting to validate an invalid JID. * Resolve an issue when connecting to iChat Server when no resource is specified. - * Fix a crash when adding a buddy without an '@'. * Try to automatically find a STUN server by using an SRV lookup on the account's domain, and use that for voice and video if found and the user didn't set one manually in prefs. + * Fix a crash when adding a buddy without an '@'. Yahoo: * Fix sending /buzz. @@ -52,12 +58,6 @@ * The userlist in a multiuser chat can be styled via gtkrc by using the widget name "pidgin_conv_userlist". (Heiko Schmitt) * Add a hold button to the media window. - * Tooltips for custom smileys should work now. - * Users with unread messages are again bolded in the Buddy List. - * Minor reworking of the Preferences window's Network tab to make it need - less vertical space. - * The global "Use remote DNS with SOCKS4 proxies" preference no longer - disappears when the preference value changes in certain ways. version 2.6.3 (10/16/2009): General:
--- a/finch/libgnt/gnttree.c Wed Nov 04 17:03:05 2009 +0900 +++ b/finch/libgnt/gnttree.c Fri Nov 06 17:23:40 2009 +0900 @@ -815,7 +815,7 @@ gnt_widget_activate(widget); } else if (tree->priv->search) { gboolean changed = TRUE; - if (isalnum(*text)) { + if (g_unichar_isprint(*text)) { tree->priv->search = g_string_append_c(tree->priv->search, *text); } else if (g_utf8_collate(text, GNT_KEY_BACKSPACE) == 0) { if (tree->priv->search->len)
--- a/libpurple/protocols/bonjour/mdns_avahi.c Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/bonjour/mdns_avahi.c Fri Nov 06 17:23:40 2009 +0900 @@ -150,6 +150,10 @@ } break; case AVAHI_RESOLVER_FOUND: + + purple_debug_info("bonjour", "_resolve_callback - name:%s account:%p bb:%p\n", + name, account, bb); + /* create a buddy record */ if (bb == NULL) bb = bonjour_buddy_new(name, account); @@ -173,8 +177,12 @@ /* Get the ip as a string */ + ip[0] = '\0'; avahi_address_snprint(ip, AVAHI_ADDRESS_STR_MAX, a); + purple_debug_info("bonjour", "_resolve_callback - name:%s ip:%s prev_ip:%s\n", + name, ip, rd->ip); + if (rd->ip == NULL || strcmp(rd->ip, ip) != 0) { /* We store duplicates in bb->ips, so we always remove the one */ if (rd->ip != NULL) {
--- a/libpurple/protocols/msn/nexus.c Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/msn/nexus.c Fri Nov 06 17:23:40 2009 +0900 @@ -399,7 +399,14 @@ username = purple_account_get_username(session->account); password = purple_connection_get_password(session->account->gc); - password_xml = g_markup_escape_text(password, MIN(strlen(password), 16)); + if (g_utf8_strlen(password, -1) > 16) { + /* max byte size for 16 utf8 characters is 64 + 1 for the null */ + gchar truncated[65]; + g_utf8_strncpy(truncated, password, 16); + password_xml = g_markup_escape_text(truncated, -1); + } else { + password_xml = g_markup_escape_text(password, -1); + } purple_debug_info("msn", "Logging on %s, with policy '%s', nonce '%s'\n", username, nexus->policy, nexus->nonce);
--- a/libpurple/protocols/oscar/clientlogin.c Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/oscar/clientlogin.c Fri Nov 06 17:23:40 2009 +0900 @@ -40,6 +40,7 @@ #include "core.h" #include "oscar.h" +#include "oscarcommon.h" #define URL_CLIENT_LOGIN "https://api.screenname.aol.com/auth/clientLogin" #define URL_START_OSCAR_SESSION "http://api.oscar.aol.com/aim/startOSCARSession" @@ -102,12 +103,15 @@ return signature; } -static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie) +static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname) { xmlnode *response_node, *tmp_node, *data_node; - xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL; + xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL; + gboolean use_tls; char *tmp; + use_tls = purple_account_get_bool(purple_connection_get_account(gc), "use_ssl", OSCAR_DEFAULT_USE_SSL); + /* Parse the response as XML */ response_node = xmlnode_from_str(response, response_len); if (response_node == NULL) @@ -131,6 +135,7 @@ host_node = xmlnode_get_child(data_node, "host"); port_node = xmlnode_get_child(data_node, "port"); cookie_node = xmlnode_get_child(data_node, "cookie"); + tls_node = xmlnode_get_child(data_node, "tlsCertName"); } /* Make sure we have a status code */ @@ -177,7 +182,8 @@ /* Make sure we have everything else */ if (data_node == NULL || host_node == NULL || - port_node == NULL || cookie_node == NULL) + port_node == NULL || cookie_node == NULL || + (use_tls && tls_node == NULL)) { char *msg; purple_debug_error("oscar", "startOSCARSession response was missing " @@ -195,7 +201,12 @@ *host = xmlnode_get_data_unescaped(host_node); tmp = xmlnode_get_data_unescaped(port_node); *cookie = xmlnode_get_data_unescaped(cookie_node); - if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || cookie == NULL || *cookie == '\0') + + if (use_tls) + *tls_certname = xmlnode_get_data_unescaped(tls_node); + + if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || *cookie == NULL || **cookie == '\0' || + (use_tls && (*tls_certname == NULL || **tls_certname == '\0'))) { char *msg; purple_debug_error("oscar", "startOSCARSession response was missing " @@ -223,6 +234,7 @@ OscarData *od; PurpleConnection *gc; char *host, *cookie; + char *tls_certname = NULL; unsigned short port; guint8 *cookiedata; gsize cookiedata_len; @@ -244,28 +256,30 @@ return; } - if (!parse_start_oscar_session_response(gc, url_text, len, &host, &port, &cookie)) + if (!parse_start_oscar_session_response(gc, url_text, len, &host, &port, &cookie, &tls_certname)) return; cookiedata = purple_base64_decode(cookie, &cookiedata_len); - oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len); + oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len, tls_certname); g_free(cookiedata); g_free(host); g_free(cookie); + g_free(tls_certname); } static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime) { char *query_string, *signature, *url; + gboolean use_tls = purple_account_get_bool(purple_connection_get_account(od->gc), "use_ssl", OSCAR_DEFAULT_USE_SSL); /* Construct the GET parameters */ query_string = g_strdup_printf("a=%s" "&f=xml" "&k=%s" "&ts=%" PURPLE_TIME_T_MODIFIER - "&useTLS=0", - purple_url_encode(token), get_client_key(od), hosttime); + "&useTLS=%d", + purple_url_encode(token), get_client_key(od), hosttime, use_tls); signature = generate_signature("GET", URL_START_OSCAR_SESSION, query_string, session_key); url = g_strdup_printf(URL_START_OSCAR_SESSION "?%s&sig_sha256=%s",
--- a/libpurple/protocols/oscar/libaim.c Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/oscar/libaim.c Fri Nov 06 17:23:40 2009 +0900 @@ -141,7 +141,7 @@ static void init_plugin(PurplePlugin *plugin) { - oscar_init(PURPLE_PLUGIN_PROTOCOL_INFO(plugin)); + oscar_init(plugin); } PURPLE_INIT_PLUGIN(aim, init_plugin, info);
--- a/libpurple/protocols/oscar/libicq.c Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/oscar/libicq.c Fri Nov 06 17:23:40 2009 +0900 @@ -153,7 +153,7 @@ { PurpleAccountOption *option; - oscar_init(PURPLE_PLUGIN_PROTOCOL_INFO(plugin)); + oscar_init(plugin); option = purple_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--- a/libpurple/protocols/oscar/oscar.c Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/oscar/oscar.c Fri Nov 06 17:23:40 2009 +0900 @@ -1855,17 +1855,35 @@ return 1; } -int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen) +int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname) { + PurpleAccount *account; FlapConnection *conn; + account = purple_connection_get_account(gc); + conn = flap_connection_new(od, SNAC_FAMILY_LOCATE); conn->cookielen = cookielen; conn->cookie = g_memdup(cookie, cookielen); - conn->connect_data = purple_proxy_connect(NULL, - purple_connection_get_account(gc), host, port, - connection_established_cb, conn); - if (conn->connect_data == NULL) + + /* + * tls_certname is only set (and must be set if we get this far) if + * SSL is enabled. + */ + if (tls_certname) + { + conn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port, + ssl_connection_established_cb, ssl_connection_error_cb, + tls_certname, conn); + } + else + { + conn->connect_data = purple_proxy_connect(NULL, + account, host, port, + connection_established_cb, conn); + } + + if (conn->gsc == NULL && conn->connect_data == NULL) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return 0; @@ -4032,9 +4050,6 @@ presence = purple_status_get_presence(status); aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence)); - /* Request offline messages for AIM and ICQ */ - aim_im_reqofflinemsgs(od); - if (od->icq) { #ifdef OLDSTYLE_ICQ_OFFLINEMSGS aim_icq_reqofflinemsgs(od); @@ -4061,6 +4076,10 @@ */ if (od->ssi.received_data) { aim_srv_clientready(od, conn); + + /* Request offline messages for AIM and ICQ */ + aim_im_reqofflinemsgs(od); + purple_connection_set_state(gc, PURPLE_CONNECTED); } @@ -5254,7 +5273,7 @@ { /* If not in server list then prune from local list */ GSList *cur, *next; GSList *buddies = purple_find_buddies(account, NULL); - + /* Buddies */ cur = NULL; @@ -5344,45 +5363,28 @@ /* Add from server list to local list */ for (curitem=od->ssi.local; curitem; curitem=curitem->next) { - if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL))) switch (curitem->type) { case AIM_SSI_TYPE_BUDDY: { /* Buddy */ if (curitem->name) { struct aim_ssi_item *groupitem; - char *gname, *gname_utf8, *alias, *alias_utf8; + const char *gname, *alias; groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000); gname = groupitem ? groupitem->name : NULL; - if (gname != NULL) { - if (g_utf8_validate(gname, -1, NULL)) - gname_utf8 = g_strdup(gname); - else - gname_utf8 = oscar_utf8_try_convert(account, gname); - } else - gname_utf8 = NULL; - - g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")); + + g = purple_find_group(gname ? gname : _("Orphans")); if (g == NULL) { - g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); + g = purple_group_new(gname ? gname : _("Orphans")); purple_blist_add_group(g, NULL); } alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name); - if (alias != NULL) { - if (g_utf8_validate(alias, -1, NULL)) - alias_utf8 = g_strdup(alias); - else - alias_utf8 = oscar_utf8_try_convert(account, alias); - g_free(alias); - } else - alias_utf8 = NULL; - b = purple_find_buddy_in_group(account, curitem->name, g); if (b) { /* Get server stored alias */ - purple_blist_alias_buddy(b, alias_utf8); + purple_blist_alias_buddy(b, alias); } else { - b = purple_buddy_new(account, curitem->name, alias_utf8); + b = purple_buddy_new(account, curitem->name, alias); purple_debug_info("oscar", "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname); @@ -5406,30 +5408,15 @@ purple_buddy_get_name(b), OSCAR_STATUS_ID_MOBILE, NULL); } - - g_free(gname_utf8); - g_free(alias_utf8); } } break; case AIM_SSI_TYPE_GROUP: { /* Group */ - char *gname; - char *gname_utf8; - - gname = curitem->name; - if (gname != NULL) { - if (g_utf8_validate(gname, -1, NULL)) - gname_utf8 = g_strdup(gname); - else - gname_utf8 = oscar_utf8_try_convert(account, gname); - } else - gname_utf8 = NULL; - - if (gname_utf8 != NULL && purple_find_group(gname_utf8) == NULL) { - g = purple_group_new(gname_utf8); + const char *gname = curitem->name; + if (gname != NULL && purple_find_group(gname) == NULL) { + g = purple_group_new(gname); purple_blist_add_group(g, NULL); } - g_free(gname_utf8); } break; case AIM_SSI_TYPE_PERMIT: { /* Permit buddy */ @@ -5505,6 +5492,10 @@ */ if (od->bos.have_rights) { aim_srv_clientready(od, conn); + + /* Request offline messages for AIM and ICQ */ + aim_im_reqofflinemsgs(od); + purple_connection_set_state(gc, PURPLE_CONNECTED); } @@ -5564,7 +5555,8 @@ { PurpleConnection *gc; PurpleAccount *account; - char *gname, *gname_utf8, *alias, *alias_utf8; + const char *gname; + char *alias; PurpleBuddy *b; PurpleGroup *g; struct aim_ssi_item *ssi_item; @@ -5585,19 +5577,7 @@ return 1; gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); - gname_utf8 = gname ? oscar_utf8_try_convert(account, gname) : NULL; - alias = aim_ssi_getalias(od->ssi.local, gname, name); - if (alias != NULL) - { - if (g_utf8_validate(alias, -1, NULL)) - alias_utf8 = g_strdup(alias); - else - alias_utf8 = oscar_utf8_try_convert(account, alias); - } - else - alias_utf8 = NULL; - g_free(alias); b = purple_find_buddy(account, name); if (b) { @@ -5606,21 +5586,21 @@ * of your buddies, so update our local buddy list with * the person's new alias. */ - purple_blist_alias_buddy(b, alias_utf8); + purple_blist_alias_buddy(b, alias); } else if (snac_subtype == 0x0008) { /* * You're logged in somewhere else and you added a buddy to * your server list, so add them to your local buddy list. */ - b = purple_buddy_new(account, name, alias_utf8); - - if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) { - g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); + b = purple_buddy_new(account, name, alias); + + if (!(g = purple_find_group(gname ? gname : _("Orphans")))) { + g = purple_group_new(gname ? gname : _("Orphans")); purple_blist_add_group(g, NULL); } purple_debug_info("oscar", - "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans")); + "ssi: adding buddy %s to group %s to local list\n", name, gname ? gname : _("Orphans")); purple_blist_add_buddy(b, NULL, g, NULL); /* Mobile users should always be online */ @@ -5633,6 +5613,8 @@ } + g_free(alias); + ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, gname, name, AIM_SSI_TYPE_BUDDY); if (ssi_item == NULL) @@ -5642,9 +5624,6 @@ "group %s\n", name, gname); } - g_free(gname_utf8); - g_free(alias_utf8); - return 1; } @@ -6347,7 +6326,6 @@ struct name_data *data; PurpleGroup *g; char *comment; - gchar *comment_utf8; gchar *title; PurpleAccount *account; const char *name; @@ -6366,7 +6344,6 @@ data = g_new(struct name_data, 1); comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name); - comment_utf8 = comment ? oscar_utf8_try_convert(account, comment) : NULL; data->gc = gc; data->name = g_strdup(name); @@ -6374,7 +6351,7 @@ title = g_strdup_printf(_("Buddy Comment for %s"), data->name); purple_request_input(gc, title, _("Buddy Comment:"), NULL, - comment_utf8, TRUE, FALSE, NULL, + comment, TRUE, FALSE, NULL, _("_OK"), G_CALLBACK(oscar_ssi_editcomment), _("_Cancel"), G_CALLBACK(oscar_free_name_data), account, data->name, NULL, @@ -6382,7 +6359,6 @@ g_free(title); g_free(comment); - g_free(comment_utf8); } static void @@ -7188,8 +7164,9 @@ return FALSE; } -void oscar_init(PurplePluginProtocolInfo *prpl_info) +void oscar_init(PurplePlugin *plugin) { + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); PurpleAccountOption *option; static gboolean init = FALSE; @@ -7212,9 +7189,11 @@ OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); - option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins", - OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + if (g_str_equal(purple_plugin_get_id(plugin), "prpl-aim")) { + option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins", + OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS); + prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + } if (init) return;
--- a/libpurple/protocols/oscar/oscar.h Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/oscar/oscar.h Fri Nov 06 17:23:40 2009 +0900 @@ -623,7 +623,7 @@ } chat; }; -int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen); +int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname); /* family_auth.c */
--- a/libpurple/protocols/oscar/oscarcommon.h Wed Nov 04 17:03:05 2009 +0900 +++ b/libpurple/protocols/oscar/oscarcommon.h Fri Nov 06 17:23:40 2009 +0900 @@ -94,4 +94,4 @@ gboolean oscar_offline_message(const PurpleBuddy *buddy); void oscar_format_username(PurpleConnection *gc, const char *nick); GList *oscar_actions(PurplePlugin *plugin, gpointer context); -void oscar_init(PurplePluginProtocolInfo *prpl_info); +void oscar_init(PurplePlugin *plugin);
--- a/pidgin.desktop.in Wed Nov 04 17:03:05 2009 +0900 +++ b/pidgin.desktop.in Fri Nov 06 17:23:40 2009 +0900 @@ -1,7 +1,7 @@ [Desktop Entry] _Name=Pidgin Internet Messenger _GenericName=Internet Messenger -_Comment=Send instant messages over multiple protocols +_Comment=Chat over IM. Supports AIM, Google Talk, Jabber/XMPP, MSN, Yahoo and more Exec=pidgin Icon=pidgin StartupNotify=true
--- a/pidgin/gtkmain.c Wed Nov 04 17:03:05 2009 +0900 +++ b/pidgin/gtkmain.c Fri Nov 06 17:23:40 2009 +0900 @@ -143,6 +143,10 @@ } #ifdef HAVE_SIGNAL_H +static char *segfault_message; + +static int signal_sockets[2]; + static void sighandler(int sig); /* @@ -168,31 +172,60 @@ } } -char *segfault_message; +static void sighandler(int sig) +{ + ssize_t written; + + /* + * We won't do any of the heavy lifting for the signal handling here + * because we have no idea what was interrupted. Previously this signal + * handler could result in some calls to malloc/free, which can cause + * deadlock in libc when the signal handler was interrupting a previous + * malloc or free. So instead we'll do an ugly hack where we write the + * signal number to one end of a socket pair. The other half of the + * socket pair is watched by our main loop. When the main loop sees new + * data on the socket it reads in the signal and performs the appropriate + * action without fear of interrupting stuff. + */ + if (sig == SIGSEGV) { + fprintf(stderr, "%s", segfault_message); + abort(); + return; + } -/* - * This signal handler shouldn't be touching this much stuff. - * It should just set a flag and return, and something else in - * Pidgin should monitor the flag to see if something needs to - * be done. Because the signal handler interrupts the program, - * it could be called in the middle of adding a new connection - * to the list of connections, and then if we try to disconnect - * all connections it could lead to a crash because the linked - * list of connections could be in a weird state. But, well, - * this signal handler probably isn't called very often, so it's - * not a big deal. - */ -static void -sighandler(int sig) + written = write(signal_sockets[0], &sig, sizeof(int)); + if (written < 0 || written != sizeof(int)) { + /* This should never happen */ + purple_debug_error("sighandler", "Received signal %d but only " + "wrote %" G_GSSIZE_FORMAT " bytes out of %" + G_GSIZE_FORMAT ": %s\n", + sig, written, sizeof(int), g_strerror(errno)); + exit(1); + } +} + +static gboolean +mainloop_sighandler(GIOChannel *source, GIOCondition cond, gpointer data) { + GIOStatus stat; + int sig; + gsize bytes_read; + GError *error = NULL; + + /* read the signal number off of the io channel */ + stat = g_io_channel_read_chars(source, (gchar *)&sig, sizeof(int), + &bytes_read, &error); + if (stat != G_IO_STATUS_NORMAL) { + purple_debug_error("sighandler", "Signal callback failed to read " + "from signal socket: %s", error->message); + purple_core_quit(); + return FALSE; + } + switch (sig) { case SIGHUP: purple_debug_warning("sighandler", "Caught signal %d\n", sig); break; - case SIGSEGV: - fprintf(stderr, "%s", segfault_message); - abort(); - break; #if defined(USE_GSTREAMER) && !defined(GST_CAN_DISABLE_FORKING) /* By default, gstreamer forks when you initialize it, and waitpids for the * child. But if libpurple reaps the child rather than leaving it to @@ -219,6 +252,8 @@ purple_debug_warning("sighandler", "Caught signal %d\n", sig); purple_core_quit(); } + + return TRUE; } #endif @@ -502,6 +537,8 @@ sigset_t sigset; RETSIGTYPE (*prev_sig_disp)(int); char errmsg[BUFSIZ]; + GIOChannel *signal_channel; + GIOStatus signal_status; #ifndef DEBUG char *segfault_message_tmp; GError *error = NULL; @@ -592,6 +629,29 @@ ); #endif + /* + * Create a socket pair for receiving unix signals from a signal + * handler. + */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, signal_sockets) < 0) { + perror("Failed to create sockets for GLib signal handling"); + exit(1); + } + signal_channel = g_io_channel_unix_new(signal_sockets[1]); + + /* + * Set the channel encoding to raw binary instead of the default of + * UTF-8, because we'll be sending integers across instead of strings. + */ + error = NULL; + signal_status = g_io_channel_set_encoding(signal_channel, NULL, &error); + if (signal_status != G_IO_STATUS_NORMAL) { + fprintf(stderr, "Failed to set the signal channel to raw " + "binary: %s", error->message); + exit(1); + } + g_io_add_watch(signal_channel, G_IO_IN, mainloop_sighandler, NULL); + /* Let's not violate any PLA's!!!! */ /* jseymour: whatever the fsck that means */ /* Robot101: for some reason things like gdm like to block *