Add cmd_header
authorMyhailo Danylenko <isbear@ukrpost.net>
Sat, 26 Dec 2009 00:59:53 +0200
changeset 5 1b3263c96cbe
parent 4 e305d7e562c4
child 6 8e64b6d3302e
Add cmd_header
TODO
cmd.c
cmd.rc
--- /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?
+
--- 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);
 		}
--- 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 [<sequence number>] $ <command>
+# 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