# HG changeset patch # User Myhailo Danylenko # Date 1261781993 -7200 # Node ID 1b3263c96cbebfbfa2a7eeb533d175e6eb8f317b # Parent e305d7e562c4aa193fb96093f5da3111c2dde77c Add cmd_header diff -r e305d7e562c4 -r 1b3263c96cbe TODO --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TODO Sat Dec 26 00:59:53 2009 +0200 @@ -0,0 +1,3 @@ + +Header template option? + diff -r e305d7e562c4 -r 1b3263c96cbe cmd.c --- 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); } diff -r e305d7e562c4 -r 1b3263c96cbe cmd.rc --- a/cmd.rc Wed Dec 02 21:05:12 2009 +0200 +++ b/cmd.rc Sat Dec 26 00:59:53 2009 +0200 @@ -7,5 +7,10 @@ # Redirect stderr to stdout. If not, stderr will be discarded. set cmd_redirect_stderr = 1 +# Set message header to [] $ +# Note, that on muc rooms it will just send command line prior +# to command output, as subject here sets room topic. +set cmd_header = 1 + load cmd