--- a/cmd.c Wed Dec 02 21:05:12 2009 +0200
+++ b/cmd.c Sat Dec 26 00:59:53 2009 +0200
@@ -36,22 +36,54 @@
typedef struct {
gchar *jid;
GString *input;
+ gchar *subject;
+ guint seq;
guint source;
GIOChannel *channel;
} cmd_cb_t;
-static GSList *cmd_channels = NULL;
+static GSList *cmd_channels = NULL;
+
+static gboolean is_room (const gchar *jid)
+{
+ return roster_find (jid, jidsearch, ROSTER_TYPE_ROOM) ? TRUE : FALSE;
+}
+
+static gboolean cmd_send_msg (const gchar *to, const gchar *subject, const gchar *body)
+{
+ gboolean room = is_room (to);
+ gpointer xep184 = NULL;
+ gint crypted;
+
+ xmpp_send_msg (to, body, room ? ROSTER_TYPE_ROOM : ROSTER_TYPE_USER, room ? NULL : subject, FALSE /* ? */, &crypted, LM_MESSAGE_SUB_TYPE_NOT_SET, &xep184);
+
+ if (crypted == -1) {
+ scr_LogPrint (LPRINT_LOGNORM, "cmd: Encryption error. Message not sent.");
+ return FALSE;
+ }
+
+ if (!room)
+ hk_message_out (to, subject, 0, body, crypted, xep184);
+
+ return TRUE;
+}
static gboolean cmd_reader (GIOChannel *channel, GIOCondition condition, gpointer data)
{
cmd_cb_t *cb = (cmd_cb_t *) data;
if (condition & (G_IO_IN|G_IO_PRI)) {
- GIOStatus chstat;
- static gchar buf[HBB_BLOCKSIZE];
- gsize endpos;
+ GIOStatus chstat;
+ static gchar buf[HBB_BLOCKSIZE];
+ gsize endpos;
+ GError *error = NULL;
- chstat = g_io_channel_read_chars (channel, buf, HBB_BLOCKSIZE, &endpos, NULL);
+ chstat = g_io_channel_read_chars (channel, buf, HBB_BLOCKSIZE, &endpos, &error);
+
+ if (error) {
+ scr_LogPrint (LPRINT_DEBUG, "cmd: Reading error: %s.", error -> message);
+ g_clear_error (&error);
+ }
if (chstat == G_IO_STATUS_ERROR || chstat == G_IO_STATUS_EOF) {
cb->source = 0;
@@ -62,7 +94,6 @@
GString *input = cb->input;
gsize bread = 0;
gsize written = 0;
- GError *err = NULL;
gchar *utf8 = NULL;
g_string_append_len (input, buf, endpos);
@@ -75,23 +106,22 @@
// usual g_locale_to_utf8 seem to be unable to detect locale charset
// maybe, proper solution will be to call setlocale on module loading,
// but mcabber already does this, and I do not want to mess with it
- utf8 = g_convert (input->str, input->len, LocaleCharSet, "UTF-8", &bread, &written, &err);
+ utf8 = g_convert (input->str, input->len, LocaleCharSet, "UTF-8", &bread, &written, &error);
- if (err && err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE && bread) {
- err = NULL;
+ if (error && error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE && bread) {
written = 0;
- utf8 = g_convert (input->str, bread, LocaleCharSet, "UTF-8", &bread, &written, &err);
+ g_clear_error (&error);
+ utf8 = g_convert (input->str, bread, LocaleCharSet, "UTF-8", &bread, &written, &error);
}
if (written) {
gsize sent = 0;
while (sent < written) {
- gint crypted;
- gpointer xep184 = NULL;
gsize len = 0;
gchar *bbuf = NULL;
- int type = roster_find (cb->jid, jidsearch, ROSTER_TYPE_ROOM) ? ROSTER_TYPE_ROOM : ROSTER_TYPE_USER;
+ gchar *subject = NULL;
+ gboolean ret;
if (written - sent > HBB_BLOCKSIZE) {
gchar *c = utf8 + sent + HBB_BLOCKSIZE;
@@ -106,23 +136,16 @@
bbuf = g_strndup (utf8 + sent, len);
}
- // XXX add command/sequence number as title?
- xmpp_send_msg (cb->jid, len ? bbuf : (utf8 + sent), type, NULL, FALSE /* ? */, &crypted, LM_MESSAGE_SUB_TYPE_NOT_SET, &xep184);
+ cb -> seq += 1;
- if (crypted == -1) {
+ if (cb -> subject)
+ subject = g_strdup_printf (cb -> subject, cb -> seq);
+ if (!cmd_send_msg (cb->jid, subject, len ? bbuf : (utf8 + sent)))
scr_LogPrint (LPRINT_LOGNORM, "cmd: Encryption error. Message not sent.");
- if (!len)
- break;
-
- g_free (bbuf);
-
- continue;
- }
-
- if (type != ROSTER_TYPE_ROOM)
- hk_message_out (cb->jid, NULL, 0, len ? bbuf : (utf8 + sent), crypted, xep184);
+ if (subject)
+ g_free (subject);
if (!len)
break;
@@ -138,7 +161,8 @@
} else {
- scr_LogPrint (LPRINT_LOGNORM, "cmd: Character conversion error: %s", err->message);
+ scr_LogPrint (LPRINT_LOGNORM, "cmd: Character conversion error: %s", error->message);
+ g_error_free (error);
cb->source = 0;
return FALSE;
}
@@ -158,11 +182,12 @@
cmd_channels = g_slist_remove (cmd_channels, data);
- // May conflict - will be called during source removal?
-// if (cb->source)
-// g_source_remove (cb->source);
+ if (cb->source)
+ g_source_remove (cb->source);
if (cb->channel)
g_io_channel_unref (cb->channel);
+ if (cb -> subject)
+ g_free (cb -> subject);
g_free (cb->jid);
g_free (cb);
}
@@ -176,17 +201,18 @@
return;
if (!jid) {
- scr_LogPrint (LPRINT_LOGNORM, "Unsuitable buddy selected");
+ scr_LogPrint (LPRINT_LOGNORM, "Unsuitable buddy selected.");
return;
}
if (pipe (fd)) {
- scr_LogPrint (LPRINT_LOGNORM, "Cannot create pipe: %s", strerror (errno));
+ scr_LogPrint (LPRINT_LOGNORM, "Cannot create pipe: %s.", strerror (errno));
return;
}
{
- int res = fork ();
+ GIOChannel *channel;
+ int res = fork ();
if (!res) {
@@ -210,7 +236,7 @@
}
if (res == -1) {
- scr_LogPrint (LPRINT_NORMAL, "Cannot fork child: %s", strerror (errno));
+ scr_LogPrint (LPRINT_NORMAL, "Cannot fork child: %s.", strerror (errno));
close (fd[0]);
close (fd[1]);
return;
@@ -218,21 +244,49 @@
close (fd[1]);
- GIOChannel *channel = g_io_channel_unix_new (fd[0]);
+ {
+ GError *error = NULL;
+
+ channel = g_io_channel_unix_new (fd[0]);
- g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
- g_io_channel_set_encoding (channel, NULL, NULL);
- g_io_channel_set_close_on_unref (channel, TRUE);
- g_io_channel_set_buffered (channel, FALSE);
+ g_io_channel_set_encoding (channel, NULL, &error);
+ if (error) {
+ scr_LogPrint (LPRINT_DEBUG, "cmd: Cannot unset channel encoding: %s.", error -> message);
+ g_clear_error (&error);
+ }
+ g_io_channel_set_buffered (channel, FALSE);
+ g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
+ if (error) {
+ scr_LogPrint (LPRINT_DEBUG, "cmd: Cannot set nonblocking flag on channel: %s.", error -> message);
+ g_error_free (error);
+ }
+ g_io_channel_set_close_on_unref (channel, TRUE);
+ }
{
cmd_cb_t *cb = g_new (cmd_cb_t, 1);
- cb->jid = g_strdup (jid);
- cb->input = g_string_new (NULL);
- cb->channel = channel;
- cb->source = g_io_add_watch_full (channel, 0, G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
- cmd_reader, (gpointer) cb, cmd_destroy_data);
+ if (settings_opt_get_int ("cmd_header")) {
+ if (is_room (jid)) {
+ gchar *mesg = g_strdup_printf ("$ %s", arg);
+ gchar *utf = to_utf8 (mesg);
+ g_free (mesg);
+ cmd_send_msg (jid, NULL, utf);
+ g_free (utf);
+ cb -> subject = NULL;
+ } else {
+ gchar *header = g_strdup_printf ("[%%02d] $ %s", arg);
+ cb -> subject = to_utf8 (header);
+ g_free (header);
+ }
+ }
+
+ cb -> jid = g_strdup (jid);
+ cb -> input = g_string_new (NULL);
+ cb -> seq = 0;
+ cb -> channel = channel;
+ cb -> source = g_io_add_watch_full (channel, 0, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ cmd_reader, (gpointer) cb, cmd_destroy_data);
cmd_channels = g_slist_append (cmd_channels, cb);
}