# HG changeset patch # User Mikael Berthe # Date 1203371977 -3600 # Node ID a64778f5f26b40a13f2f4cef620323df6c37a172 # Parent b0cfd9ab4b9fe7aad08b42f314f52c524e1c5f40 Implement FIFO named command pipe diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/configure.ac --- 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 diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/mcabberrc.example --- 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: diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/src/Makefile.am --- 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 diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/src/fifo.c --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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... */ diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/src/fifo.h --- /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... */ diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/src/hooks.c --- 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, diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/src/jabglue.c --- 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); } diff -r b0cfd9ab4b9f -r a64778f5f26b mcabber/src/main.c --- 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