changeset 1426:a64778f5f26b

Implement FIFO named command pipe
author Mikael Berthe <mikael@lilotux.net>
date Mon, 18 Feb 2008 22:59:37 +0100
parents b0cfd9ab4b9f
children a8eb9aba2ed2
files mcabber/configure.ac mcabber/mcabberrc.example mcabber/src/Makefile.am mcabber/src/fifo.c mcabber/src/fifo.h mcabber/src/hooks.c mcabber/src/jabglue.c mcabber/src/main.c
diffstat 8 files changed, 243 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/configure.ac	Sun Feb 17 21:19:58 2008 +0100
+++ b/mcabber/configure.ac	Mon Feb 18 22:59:37 2008 +0100
@@ -227,10 +227,18 @@
     CFLAGS="-O2 $CFLAGS"
 fi
 
+AC_ARG_ENABLE(fifo,
+    [AC_HELP_STRING(--enable-fifo, Enable FIFO named pipe)],
+    fifo=$enableval, fifo="")
+AM_CONDITIONAL([FIFO], [test x$fifo = xyes])
+if test x"${fifo}" = x"yes"; then
+    AC_DEFINE_UNQUOTED([ENABLE_FIFO],[1],[Named pipe support])
+fi
+
 AC_ARG_ENABLE(hgcset,
     [AC_HELP_STRING(--disable-hgcset, Do not use Mercurial changeset value)],
     hgcset=$enableval, hgcset="yes")
-AM_CONDITIONAL(HGCSET, test x$hgcset = xyes)
+AM_CONDITIONAL(HGCSET, [test x$hgcset = xyes])
 if test "${hgcset}" = "yes"; then
     AC_DEFINE(ENABLE_HGCSET, 1, [Use Mercurial changeset])
 fi
--- a/mcabber/mcabberrc.example	Sun Feb 17 21:19:58 2008 +0100
+++ b/mcabber/mcabberrc.example	Mon Feb 18 22:59:37 2008 +0100
@@ -212,6 +212,11 @@
 # the server.
 #set hook-pre-disconnect = say_to foo@bar Goodbye!
 
+# FIFO
+# mcabber can create a FIFO named pipe and listen to this pipe for commands.
+# (The FIFO support has to be compiled in.)  Default: disabled.
+#set fifo_name = ~/.mcabber/mcabber.fifo
+
 # Traces logging
 # If you want advanced traces, please specify a file and a level here.
 # There are currently 2 traceloglog levels:
--- a/mcabber/src/Makefile.am	Sun Feb 17 21:19:58 2008 +0100
+++ b/mcabber/src/Makefile.am	Mon Feb 18 22:59:37 2008 +0100
@@ -7,6 +7,10 @@
 		  histolog.c histolog.h utils.c utils.h pgp.c pgp.h \
 		  help.c help.h
 
+if FIFO
+mcabber_SOURCES += fifo.c fifo.h
+endif
+
 if OTR
 mcabber_SOURCES += otr.c otr.h
 endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/src/fifo.c	Mon Feb 18 22:59:37 2008 +0100
@@ -0,0 +1,174 @@
+/*
+ * fifo.c       -- Read commands from a named pipe
+ *
+ * Copyright (C) 2008 Mikael Berthe <mikael@lilotux.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "commands.h"
+#include "logprint.h"
+#include "utils.h"
+
+#include "hbuf.h"   // For HBB_BLOCKSIZE
+
+static FILE *sfd;
+static char *fifo_name;
+
+
+//  fifo_init(fifo_path)
+// Create and open the FIFO file.
+// If fifo_path is NULL, reopen the current pipe.
+// Return 0 (success) or -1 (failure).
+int fifo_init(const char *fifo_path)
+{
+  struct stat buf;
+  int fd;
+  char *fifo_path_xp;
+
+  if (!sfd && !fifo_path)
+    return -1;  // Nothing to do...
+
+  if (sfd && !fifo_path) {  // We want to reinitialize the pipe
+    fclose(sfd);
+    sfd = NULL;
+    if (fifo_name)
+      goto fifo_init_open;
+  }
+  sfd = NULL;
+
+  fifo_path_xp = expand_filename(fifo_path);
+
+  if (!stat(fifo_path_xp, &buf)) {
+    if (!S_ISFIFO(buf.st_mode)) {
+      scr_LogPrint(LPRINT_LOGNORM, "WARNING: Cannot create the FIFO. "
+                   "%s already exists and is not a pipe", fifo_path_xp);
+      g_free(fifo_path_xp);
+      return -1;
+    }
+
+    if (unlink(fifo_path_xp)) {
+      scr_LogPrint(LPRINT_LOGNORM, "WARNING: Unable to unlink FIFO %s [%s]",
+                   fifo_path_xp, g_strerror(errno));
+      g_free(fifo_path_xp);
+      return -1;
+    }
+  }
+
+  if (mkfifo(fifo_path_xp, S_IWUSR | S_IRUSR)) {
+    scr_LogPrint(LPRINT_LOGNORM, "WARNING: Cannot create the FIFO [%s]",
+                 g_strerror(errno));
+    g_free(fifo_path_xp);
+    return -1;
+  }
+
+  fifo_name = fifo_path_xp;
+
+fifo_init_open:
+  fd = open(fifo_name, O_RDONLY | O_NONBLOCK);
+  if (!fd)
+    return -1;
+
+  sfd = fdopen(fd, "r");
+  if (fifo_path)
+    scr_LogPrint(LPRINT_LOGNORM, "FIFO initialized (%s)", fifo_name);
+  return 0;
+}
+
+//  fifo_deinit()
+// Close the current FIFO pipe and delete it.
+void fifo_deinit(void)
+{
+  if (sfd) {
+    fclose(sfd);
+    sfd = NULL;
+  }
+  if (fifo_name) {
+    unlink(fifo_name);
+    g_free(fifo_name);
+    fifo_name = NULL;
+  }
+}
+
+//  fifo_read()
+// Read a line from the FIFO pipe (if available), and execute it.
+void fifo_read(void)
+{
+  struct timeval tv;
+  fd_set fds;
+  char *getbuf;
+  char buf[HBB_BLOCKSIZE+1];
+  int fd;
+
+  if (!sfd) {
+    return;
+  }
+
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+
+  fd = fileno(sfd);
+
+  FD_ZERO(&fds);
+  FD_SET(fd, &fds);
+
+  select(fd + 1, &fds, NULL, NULL, &tv);
+
+  if (!FD_ISSET(fd, &fds)) {
+    return;
+  }
+
+  getbuf = fgets(buf, HBB_BLOCKSIZE, sfd);
+  if (getbuf) {
+    char *eol = buf;
+
+    // Strip trailing newlines
+    for ( ; *eol ; eol++)
+      ;
+    if (eol > buf)
+      eol--;
+    while (eol > buf && *eol == '\n')
+      *eol-- = 0;
+
+    scr_LogPrint(LPRINT_LOGNORM, "Executing FIFO command: %s", buf);
+    if (process_command(buf, TRUE) == 255)
+      mcabber_set_terminate_ui();
+  } else {
+    if (feof(sfd))
+      fifo_init(NULL);  // Reopen the FIFO on EOF
+  }
+}
+
+//  fifo_get_fd()
+// Return the FIFO file descriptor (-1 if none).
+int fifo_get_fd(void)
+{
+  if (sfd)
+    return fileno(sfd);
+  return -1;
+}
+
+/* vim: set expandtab cindent cinoptions=>2\:2(0:  For Vim users... */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mcabber/src/fifo.h	Mon Feb 18 22:59:37 2008 +0100
@@ -0,0 +1,11 @@
+#ifndef __FIFO_H__
+#define __FIFO_H__ 1
+
+int  fifo_init(const char *fifo_path);
+void fifo_deinit(void);
+void fifo_read(void);
+int  fifo_get_fd(void);
+
+#endif /* __FIFO_H__ */
+
+/* vim: set expandtab cindent cinoptions=>2\:2(0:  For Vim users... */
--- a/mcabber/src/hooks.c	Sun Feb 17 21:19:58 2008 +0100
+++ b/mcabber/src/hooks.c	Mon Feb 18 22:59:37 2008 +0100
@@ -33,6 +33,10 @@
 #include "utf8.h"
 #include "commands.h"
 
+#ifdef ENABLE_FIFO
+# include "fifo.h"
+#endif
+
 static char *extcmd;
 
 static const char *COMMAND_ME = "/me ";
@@ -50,6 +54,9 @@
     last = now;
   }
   */
+#ifdef ENABLE_FIFO
+  fifo_read();
+#endif
 }
 
 void hk_message_in(const char *bjid, const char *resname,
--- a/mcabber/src/jabglue.c	Sun Feb 17 21:19:58 2008 +0100
+++ b/mcabber/src/jabglue.c	Mon Feb 18 22:59:37 2008 +0100
@@ -35,6 +35,10 @@
 #include "pgp.h"
 #include "otr.h"
 
+#ifdef ENABLE_FIFO
+# include "fifo.h"
+#endif
+
 #define JABBERPORT      5222
 #define JABBERSSLPORT   5223
 
@@ -231,6 +235,10 @@
   long tmout;
   struct timeval tv;
   static time_t last_eviqs_check = 0L;
+  int maxfd;
+#ifdef ENABLE_FIFO
+  int fifofd;
+#endif
 
   if (!online) {
     safe_usleep(10000);
@@ -247,6 +255,15 @@
   FD_ZERO(&fds);
   FD_SET(0, &fds);
   FD_SET(jc->fd, &fds);
+  maxfd = jc->fd;
+
+#ifdef ENABLE_FIFO
+  fifofd = fifo_get_fd();
+  if (fifofd > 0) {
+    FD_SET(fifofd, &fds);
+    maxfd = MAX(maxfd, fifofd);
+  }
+#endif
 
   tv.tv_sec = 60;
   tv.tv_usec = 0;
@@ -276,7 +293,7 @@
     tv.tv_usec = 350000;
 
   scr_DoUpdate();
-  if (select(jc->fd + 1, &fds, NULL, NULL, &tv) > 0) {
+  if (select(maxfd + 1, &fds, NULL, NULL, &tv) > 0) {
     if (FD_ISSET(jc->fd, &fds))
       jab_poll(jc, 0);
   }
--- a/mcabber/src/main.c	Sun Feb 17 21:19:58 2008 +0100
+++ b/mcabber/src/main.c	Mon Feb 18 22:59:37 2008 +0100
@@ -43,6 +43,10 @@
 #include "pgp.h"
 #include "otr.h"
 
+#ifdef ENABLE_FIFO
+# include "fifo.h"
+#endif
+
 #ifdef ENABLE_HGCSET
 # include "hgcset.h"
 #endif
@@ -291,6 +295,9 @@
 #ifdef WITH_ASPELL
   puts("Compiled with Aspell support.");
 #endif
+#ifdef ENABLE_FIFO
+  puts("Compiled with FIFO support.");
+#endif
 #ifdef ENABLE_DEBUG
   puts("Compiled with debugging support.");
 #endif
@@ -487,6 +494,11 @@
 
   chatstates_disabled = settings_opt_get_int("disable_chatstates");
 
+#ifdef ENABLE_FIFO
+  /* Initialize FIFO named pipe */
+  fifo_init(settings_opt_get("fifo_name"));
+#endif
+
   if (ret < 0) {
     scr_LogPrint(LPRINT_NORMAL, "No configuration file has been found.");
     scr_ShowBuddyWindow();
@@ -515,6 +527,9 @@
   }
 
   scr_TerminateCurses();
+#ifdef ENABLE_FIFO
+  fifo_deinit();
+#endif
 #ifdef HAVE_LIBOTR
   otr_terminate();
 #endif