diff options
Diffstat (limited to 'src/plugins/fifo/fifo.c')
-rw-r--r-- | src/plugins/fifo/fifo.c | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/plugins/fifo/fifo.c b/src/plugins/fifo/fifo.c new file mode 100644 index 000000000..9a6f50e77 --- /dev/null +++ b/src/plugins/fifo/fifo.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + +/* fifo.c: FIFO pipe for WeeChat remote control */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "weechat.h" +#include "fifo.h" +#include "command.h" +#include "log.h" +#include "weeconfig.h" +#include "../gui/gui.h" + + +int weechat_fifo = -1; +char *weechat_fifo_filename = NULL; +char *weechat_fifo_unterminated = NULL; + + +/* + * fifo_create: create FIFO pipe for remote control + */ + +void +fifo_create () +{ + int filename_length; + + if (cfg_irc_fifo_pipe) + { + /* build FIFO filename: "<weechat_home>/weechat_fifo_" + process PID */ + if (!weechat_fifo_filename) + { + filename_length = strlen (weechat_home) + 64; + weechat_fifo_filename = (char *) malloc (filename_length * sizeof (char)); + snprintf (weechat_fifo_filename, filename_length, "%s/weechat_fifo_%d", + weechat_home, (int) getpid()); + } + + /* create FIFO pipe, writable for user only */ + if ((weechat_fifo = mkfifo (weechat_fifo_filename, 0600)) != 0) + { + weechat_fifo = -1; + gui_printf (NULL, + _("%s unable to create FIFO pipe for remote control (%s)\n"), + WEECHAT_ERROR, weechat_fifo_filename); + weechat_log_printf (_("%s unable to create FIFO pipe for " + "remote control (%s)\n"), + WEECHAT_ERROR, weechat_fifo_filename); + return; + } + + /* open FIFO pipe in read-only (for WeeChat), non nlobking mode */ + if ((weechat_fifo = open (weechat_fifo_filename, O_RDONLY | O_NONBLOCK)) == -1) + { + gui_printf (NULL, + _("%s unable to open FIFO pipe (%s) for reading\n"), + WEECHAT_ERROR, weechat_fifo_filename); + weechat_log_printf (_("%s unable to open FIFO pipe (%s) for reading\n"), + WEECHAT_ERROR, weechat_fifo_filename); + return; + } + + weechat_log_printf (_("FIFO pipe is open\n")); + } +} + +/* + * fifo_exec: execute a command/text received by FIFO pipe + */ + +void +fifo_exec (char *text) +{ + char *pos_msg, *pos; + t_irc_server *ptr_server; + t_irc_channel *ptr_channel; + + pos = NULL; + ptr_server = NULL; + ptr_channel = NULL; + + /* look for server/channel at beginning of text */ + /* text may be: "server,channel *text" or "server *text" or "*text" */ + if (text[0] == '*') + { + pos_msg = text + 1; + if (gui_current_window->buffer->has_input) + { + ptr_server = GUI_SERVER(gui_current_window->buffer); + ptr_channel = GUI_CHANNEL(gui_current_window->buffer); + } + else + { + ptr_server = GUI_SERVER(gui_buffers); + ptr_channel = NULL; + } + } + else + { + pos_msg = strstr (text, " *"); + if (!pos_msg) + { + irc_display_prefix (NULL, NULL, GUI_PREFIX_ERROR); + gui_printf (NULL, _("%s invalid text received on FIFO pipe\n"), + WEECHAT_WARNING); + return; + } + pos_msg[0] = '\0'; + pos = pos_msg - 1; + pos_msg += 2; + while ((pos >= text) && (pos[0] == ' ')) + { + pos[0] = '\0'; + pos--; + } + + if (text[0]) + { + pos = strchr (text, ','); + if (pos) + pos[0] = '\0'; + ptr_server = irc_server_search (text); + if (!ptr_server || !ptr_server->buffer) + { + irc_display_prefix (NULL, NULL, GUI_PREFIX_ERROR); + gui_printf (NULL, _("%s server \"%s\" not found (FIFO pipe data)\n"), + WEECHAT_WARNING, text); + return; + } + if (ptr_server && pos) + { + ptr_channel = irc_channel_search_any (ptr_server, pos + 1); + if (!ptr_channel) + { + irc_display_prefix (NULL, NULL, GUI_PREFIX_ERROR); + gui_printf (NULL, + _("%s channel \"%s\" not found (FIFO pipe data)\n"), + WEECHAT_WARNING, pos + 1); + return; + } + } + } + } + + user_command (ptr_server, ptr_channel, pos_msg, 0); +} + +/* + * fifo_read: read data in FIFO pipe + */ + +void +fifo_read () +{ + static char buffer[4096 + 2]; + char *buf2, *pos, *ptr_buf, *next_ptr_buf; + int num_read; + + num_read = read (weechat_fifo, buffer, sizeof (buffer) - 2); + if (num_read > 0) + { + buffer[num_read] = '\0'; + + buf2 = NULL; + ptr_buf = buffer; + if (weechat_fifo_unterminated) + { + buf2 = (char *) malloc (strlen (weechat_fifo_unterminated) + + strlen (buffer) + 1); + if (buf2) + { + strcpy (buf2, weechat_fifo_unterminated); + strcat (buf2, buffer); + } + ptr_buf = buf2; + free (weechat_fifo_unterminated); + weechat_fifo_unterminated = NULL; + } + + while (ptr_buf && ptr_buf[0]) + { + next_ptr_buf = NULL; + pos = strstr (ptr_buf, "\r\n"); + if (pos) + { + pos[0] = '\0'; + next_ptr_buf = pos + 2; + } + else + { + pos = strstr (ptr_buf, "\n"); + if (pos) + { + pos[0] = '\0'; + next_ptr_buf = pos + 1; + } + else + { + weechat_fifo_unterminated = strdup (ptr_buf); + ptr_buf = NULL; + next_ptr_buf = NULL; + } + } + + if (ptr_buf) + fifo_exec (ptr_buf); + + ptr_buf = next_ptr_buf; + } + + if (buf2) + free (buf2); + } + else + { + if (num_read < 0) + { + gui_printf (NULL, + _("%s error reading FIFO pipe, closing it\n"), + WEECHAT_ERROR); + weechat_log_printf (_("%s error reading FIFO pipe, closing it\n"), + WEECHAT_ERROR); + fifo_remove (); + } + else + { + close (weechat_fifo); + weechat_fifo = open (weechat_fifo_filename, O_RDONLY | O_NONBLOCK); + } + } +} + +/* + * fifo_remove: remove FIFO pipe + */ + +void +fifo_remove () +{ + if (weechat_fifo != -1) + { + /* close FIFO pipe */ + close (weechat_fifo); + weechat_fifo = -1; + } + + /* remove FIFO from disk */ + if (weechat_fifo_filename) + unlink (weechat_fifo_filename); + + if (weechat_fifo_unterminated) + { + free (weechat_fifo_unterminated); + weechat_fifo_unterminated = NULL; + } + + if (weechat_fifo_filename) + { + free (weechat_fifo_filename); + weechat_fifo_filename = NULL; + } + + weechat_log_printf (_("FIFO pipe is closed\n")); +} |