# HG changeset patch # User Sean Egan # Date 1017346065 0 # Node ID da324fe688b31f5288ea672efca099544b73b8f1 # Parent 1b8b05f76ae9c1e7830c7d02d17297b2c85e8b75 [gaim-migrate @ 3119] Jabber improvements (Jim Seymour) and good handling of sigchld (Jim Seymour and Luke Schierer) committer: Tailor Script diff -r 1b8b05f76ae9 -r da324fe688b3 ChangeLog --- a/ChangeLog Thu Mar 28 19:58:58 2002 +0000 +++ b/ChangeLog Thu Mar 28 20:07:45 2002 +0000 @@ -1,8 +1,7 @@ Gaim: The Pimpin' Penguin IM Clone thats good for the soul! version 0.55: - * Better Jabber list management when using multiple - resources (Thanks Jim Seymour) + * Jabber improvements (Thanks Jim Seymour) * Various sound cleanups (Thanks Robert McQueen) * Login process shown in single window (Thanks Michael Golden) diff -r 1b8b05f76ae9 -r da324fe688b3 src/aim.c --- a/src/aim.c Thu Mar 28 19:58:58 2002 +0000 +++ b/src/aim.c Thu Mar 28 20:07:45 2002 +0000 @@ -84,6 +84,28 @@ void BuddyTickerCreateWindow(void); +#if HAVE_SIGNAL_H +/* + * Lists of signals we wish to catch and those we wish to ignore. + * Each list terminated with -1 + */ +static int catch_sig_list[] = { + SIGSEGV, + SIGHUP, + SIGINT, + SIGTERM, + SIGQUIT, + SIGCHLD, + -1 +}; + +static int ignore_sig_list[] = { + SIGPIPE, + -1 +}; +#endif + + void cancel_logon(void) { #ifdef USE_APPLET @@ -408,6 +430,9 @@ break; case SIGCHLD: clean_pid(); +#if HAVE_SIGNAL_H + signal(SIGCHLD, sighandler); /* restore signal catching on this one! */ +#endif break; default: debug_printf("caught signal %d\n", sig); @@ -527,6 +552,10 @@ { int opt_acct = 0, opt_help = 0, opt_version = 0, opt_login = 0, do_login_ret = -1; char *opt_user_arg = NULL, *opt_login_arg = NULL; +#if HAVE_SIGNAL_H + int sig_indx; /* for setting up signal catching */ + void (*prev_sig_disp)(); +#endif #ifndef USE_APPLET int opt, opt_user = 0; int i; @@ -573,13 +602,23 @@ #if HAVE_SIGNAL_H /* Let's not violate any PLA's!!!! */ - signal(SIGSEGV, sighandler); - signal(SIGHUP, sighandler); - signal(SIGINT, sighandler); - signal(SIGTERM, sighandler); - signal(SIGQUIT, sighandler); - signal(SIGPIPE, SIG_IGN); - signal(SIGCHLD, sighandler); + /* jseymour: whatever the fsck that means */ + for(sig_indx = 0; catch_sig_list[sig_indx] != -1; ++sig_indx) { + if((prev_sig_disp = signal(catch_sig_list[sig_indx], sighandler)) == SIG_ERR) { + char errmsg[BUFSIZ]; + sprintf(errmsg, "Warning: couldn't set signal %d for catching", + catch_sig_list[sig_indx]); + perror(errmsg); + } + } + for(sig_indx = 0; ignore_sig_list[sig_indx] != -1; ++sig_indx) { + if((prev_sig_disp = signal(ignore_sig_list[sig_indx], SIG_IGN)) == SIG_ERR) { + char errmsg[BUFSIZ]; + sprintf(errmsg, "Warning: couldn't set signal %d to ignore", + ignore_sig_list[sig_indx]); + perror(errmsg); + } + } #endif diff -r 1b8b05f76ae9 -r da324fe688b3 src/gtkspell.c --- a/src/gtkspell.c Thu Mar 28 19:58:58 2002 +0000 +++ b/src/gtkspell.c Thu Mar 28 20:07:45 2002 +0000 @@ -55,7 +55,18 @@ static void set_up_signal(); int gtkspell_running() { - return (spell_pid > 0); + return (spell_pid > 0? spell_pid : 0); +} + +/* + * Set to "gtkspell not running" status + * + * May seem a bit silly, but it allows us to keep the file-global + * variable from going program-global. And if we need to do + * something else additional later, well... + */ +void gtkspell_notrunning() { + spell_pid = 0; } /* @@ -170,11 +181,6 @@ gtkspell_stop(); } - if (!signal_set_up) { - set_up_signal(); - signal_set_up = 1; - } - pipe(fd_write); pipe(fd_read); pipe(fd_error); @@ -689,21 +695,3 @@ gtkspell_uncheck_all(gtktext); } -static void sigchld(int param) { - if (gtkspell_running() && - (waitpid(spell_pid, NULL, WNOHANG) == spell_pid)) { - spell_pid = 0; - } else { - /* a default SIGCHLD handler. - * what else to do here? */ - waitpid(-1, NULL, WNOHANG); - } -} - -static void set_up_signal() { - struct sigaction sigact; - memset(&sigact, 0, sizeof(struct sigaction)); - - sigact.sa_handler = sigchld; - sigaction(SIGCHLD, &sigact, NULL); -} diff -r 1b8b05f76ae9 -r da324fe688b3 src/gtkspell.h --- a/src/gtkspell.h Thu Mar 28 19:58:58 2002 +0000 +++ b/src/gtkspell.h Thu Mar 28 20:07:45 2002 +0000 @@ -55,7 +55,7 @@ /* Is gtkspell running? * * Return: - * nonzero if it running + * nonzero, positive pid if it's running * zero if is not running * * Example: @@ -63,6 +63,17 @@ * printf("gtkspell is running.\n"); */ +extern void gtkspell_notrunning(void); +/* + * Set gtkspell status to "not running" + * Intended to be used only by signal-catcher + * when the SIGCHLD signal it catches matches + * the gtkspell process i.d. + * + * Example: + * gtkspell_notrunning(); + */ + extern void gtkspell_attach(GtkText *text); /* Attach GtkSpell to a GtkText Widget. * This enables checking as you type and the popup menu. diff -r 1b8b05f76ae9 -r da324fe688b3 src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Thu Mar 28 19:58:58 2002 +0000 +++ b/src/protocols/jabber/jabber.c Thu Mar 28 20:07:45 2002 +0000 @@ -401,14 +401,14 @@ if (!gjc || gjc->state == JCONN_STATE_OFF) return; - if ((len = read(gjc->fd, buf, sizeof(buf) - 1))) { + if ((len = read(gjc->fd, buf, sizeof(buf))) > 0) { struct jabber_data *jd = GJ_GC(gjc)->proto_data; buf[len] = '\0'; debug_printf("input (len %d): %s\n", len, buf); XML_Parse(gjc->parser, buf, len, 0); if (jd->die) signoff(GJ_GC(gjc)); - } else if (len <= 0) { + } else if (len < 0 || errno != EAGAIN) { STATE_EVT(JCONN_STATE_OFF) } } @@ -686,7 +686,7 @@ /* * keep track of away msg same as yahoo plugin */ -static void jabber_track_away(gjconn gjc, jpacket p, char *name) +static void jabber_track_away(gjconn gjc, jpacket p, char *name, char *type) { struct jabber_data *jd = GJ_GC(gjc)->proto_data; gpointer val = g_hash_table_lookup(jd->hash, name); @@ -695,15 +695,19 @@ char *status = NULL; char *msg = NULL; - if((show = xmlnode_get_tag_data(p->x, "show")) != NULL) { - if (!strcasecmp(show, "away")) { - vshow = _("Away"); - } else if (!strcasecmp(show, "chat")) { - vshow = _("Online"); - } else if (!strcasecmp(show, "xa")) { - vshow = _("Extended Away"); - } else if (!strcasecmp(show, "dnd")) { - vshow = _("Do Not Disturb"); + if (type && (strcasecmp(type, "unavailable") == 0)) { + vshow = _("Unavailable"); + } else { + if((show = xmlnode_get_tag_data(p->x, "show")) != NULL) { + if (!strcasecmp(show, "away")) { + vshow = _("Away"); + } else if (!strcasecmp(show, "chat")) { + vshow = _("Online"); + } else if (!strcasecmp(show, "xa")) { + vshow = _("Extended Away"); + } else if (!strcasecmp(show, "dnd")) { + vshow = _("Do Not Disturb"); + } } } @@ -715,6 +719,8 @@ (vshow == NULL? "" : vshow), (vshow == NULL || status == NULL? "" : ": "), (status == NULL? "" : status)); + } else { + msg = g_strdup(_("Online")); } if (val) { @@ -845,11 +851,12 @@ if (!find_chat_buddy(jc->b, p->from->resource)) { add_chat_buddy(jc->b, p->from->resource); } else if ((y = xmlnode_get_tag(p->x, "status"))) { - char buf[8192]; - - g_snprintf(buf, sizeof(buf), "%s@%s/%s", + char *buf; + + buf = g_strdup_printf("%s@%s/%s", p->from->user, p->from->server, p->from->resource); - jabber_track_away(gjc, p, buf); + jabber_track_away(gjc, p, buf, NULL); + g_free(buf); } } else if (jc->b && msg) { @@ -949,6 +956,9 @@ resources = resources->next; } + /* keep track of away msg same as yahoo plugin */ + jabber_track_away(gjc, p, normalize(b->name), type); + if (type && (strcasecmp(type, "unavailable") == 0)) { if (resources) { g_free(resources->data); @@ -958,9 +968,6 @@ serv_got_update(GJ_GC(gjc), buddy, 0, 0, 0, 0, 0, 0); } } else { - /* keep track of away msg same as yahoo plugin */ - jabber_track_away(gjc, p, normalize(b->name)); - if (!resources) { b->proto_data = g_slist_append(b->proto_data, g_strdup(res)); } @@ -970,6 +977,12 @@ } } else { if (who->resource) { + char *buf; + + buf = g_strdup_printf("%s@%s/%s", who->user, who->server, who->resource); + jabber_track_away(gjc, p, buf, type); + g_free(buf); + if (type && !strcasecmp(type, "unavailable")) { struct jabber_data *jd; if (!jc && !(jc = find_existing_chat(GJ_GC(gjc), who))) { @@ -998,11 +1011,6 @@ } if (!find_chat_buddy(jc->b, who->resource)) { add_chat_buddy(jc->b, who->resource); - } else { - char buf[8192]; - g_snprintf(buf, sizeof(buf), "%s@%s/%s", - who->user, who->server, who->resource); - jabber_track_away(gjc, p, buf); } } } @@ -1544,6 +1552,63 @@ return 1; } +/* + * Add/update buddy's roster entry on server + */ +static void jabber_roster_update(struct gaim_connection *gc, char *name) +{ + xmlnode x, y; + char *realwho; + gjconn gjc; + struct buddy *buddy = NULL; + struct group *buddy_group = NULL; + + if(gc && gc->proto_data && ((struct jabber_data *)gc->proto_data)->gjc && name) { + gjc = ((struct jabber_data *)gc->proto_data)->gjc; + + if (!strchr(name, '@')) + realwho = g_strdup_printf("%s@%s", name, gjc->user->server); + else { + jid who = jid_new(gjc->p, name); + if (who->user == NULL) { + /* FIXME: transport */ + return; + } + realwho = g_strdup_printf("%s@%s", who->user, who->server); + } + + + x = jutil_iqnew(JPACKET__SET, NS_ROSTER); + y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); + xmlnode_put_attrib(y, "jid", realwho); + + + /* If we can find the buddy, there's an alias for him, it's not 0-length + * and it doesn't match his JID, add the "name" attribute. + */ + if((buddy = find_buddy(gc, realwho)) != NULL && + buddy->show != NULL && strcmp(realwho, buddy->show)) { + + xmlnode_put_attrib(y, "name", buddy->show); + } + + /* + * Find out what group the buddy's in and send that along + * with the roster item. + */ + if((buddy_group = find_group_by_buddy(gc, realwho)) != NULL) { + xmlnode z; + z = xmlnode_insert_tag(y, "group"); + xmlnode_insert_cdata(z, buddy_group->name, -1); + } + + gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); + + xmlnode_free(x); + g_free(realwho); + } +} + static void jabber_add_buddy(struct gaim_connection *gc, char *name) { xmlnode x, y; @@ -1572,39 +1637,14 @@ realwho = g_strdup_printf("%s@%s", who->user, who->server); } - - x = jutil_iqnew(JPACKET__SET, NS_ROSTER); - y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); - xmlnode_put_attrib(y, "jid", realwho); - - /* If we can find the buddy, there's an alias for him and - * it's not 0-length, add the "name" attribute. - */ - if((buddy = find_buddy(gc, realwho)) != NULL && - buddy->show != NULL && (buddy->show)[0] != '\0') { - - xmlnode_put_attrib(y, "name", buddy->show); - } - - /* - * Find out what group the buddy's in and send that along - * with the roster item. - */ - if((buddy_group = find_group_by_buddy(gc, realwho)) != NULL) { - xmlnode z; - z = xmlnode_insert_tag(y, "group"); - xmlnode_insert_cdata(z, buddy_group->name, -1); - } - - gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); - xmlnode_free(x); - x = xmlnode_new_tag("presence"); xmlnode_put_attrib(x, "to", realwho); xmlnode_put_attrib(x, "type", "subscribe"); gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); xmlnode_free(x); + jabber_roster_update(gc, realwho); + g_free(realwho); } @@ -1976,7 +2016,7 @@ *ap++ = g_strdup_printf("Jabber ID: %s
\n", realwho); if((status = g_hash_table_lookup(jd->hash, realwho)) == NULL) { - status = _("Online"); + status = _("Unknown"); } *ap++ = g_strdup_printf("Status: %s
\n", status); @@ -2315,7 +2355,7 @@ } if((status = g_hash_table_lookup(jd->hash, buddy)) == NULL) { - status = _("Online"); + status = _("Unknown"); } *ap++ = g_strdup_printf("Status: %s
\n", status); diff -r 1b8b05f76ae9 -r da324fe688b3 src/util.c --- a/src/util.c Thu Mar 28 19:58:58 2002 +0000 +++ b/src/util.c Thu Mar 28 20:07:45 2002 +0000 @@ -35,6 +35,7 @@ #include #include "gaim.h" #include "prpl.h" +#include "gtkspell.h" char *full_date() { @@ -616,10 +617,18 @@ void clean_pid(void) { int status; - pid_t pid; + pid_t pid, spell_pid; - printf ("clean_pid\n"); - pid = waitpid(-1, &status, WNOHANG); + while((pid = waitpid(-1, &status, WNOHANG)) > 0) { + if((spell_pid = gtkspell_running()) != 0 && pid == spell_pid) { + gtkspell_notrunning(); + } + } + if(pid < 0 && errno != ECHILD) { + char errmsg[BUFSIZ]; + sprintf(errmsg, "Warning: waitpid() returned %d", pid); + perror(errmsg); + } } struct aim_user *find_user(const char *name, int protocol)