2 rx.c - rxpd plugin for xchat
5 2007, Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 //#include <sys/resource.h>
29 #include <netinet/in.h>
30 //#include <arpa/inet.h>
36 #include "xchat-plugin.h"
38 #define PNAME "RxpdPlugin"
39 #define PDESC "Uses rxpd to act on content";
40 #define PVERSION "0.1"
42 #define PREFIXCMP(str, pfx) (!strncmp (str, (pfx), sizeof (pfx)-1))
44 static xchat_plugin *ph; /* plugin handle */
46 static struct rx_plugin_data
53 int fd; /* the fd used for CHECK:list */
61 buffer_readline (struct rx_plugin_data* self)
65 if (self->eol < self->eob)
67 //there was a line pending, shift buffer left
68 memmove (self->buffer, self->eol+1, self->eob - self->eol - 1);
69 self->eob = (char*)(self->eob - (self->eol - self->buffer + 1));
70 self->eol = self->buffer;
75 // find next newline, terminate string there
77 for (i = self->buffer; i < self->eob; ++i)
83 // have line, return it
84 return (self->eob == self->buffer) ? NULL : self->buffer;
91 r = read (self->fd, self->eob, 4095 - (self->eob - self->buffer));
93 while (r == -1 && errno == EINTR);
106 xchat_plugin_get_info (char **name,
117 rxstart_cb (char *word[], char *word_eol[], void *userdata)
119 // server port list; enables and connects to rxpd", &rx_private);
120 struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
122 rx->server = strdup (word[2]);
123 rx->port = strdup (word[3]);
124 rx->list = strdup (word[4]);
126 struct addrinfo* addrs = NULL;
130 aierr = getaddrinfo (rx->server, rx->port, NULL, &addrs);
133 xchat_printf (ph, "could not resolve %s:%s, %s\n", rx->server, rx->port, gai_strerror (aierr));
134 return XCHAT_EAT_ALL;
137 rx->fd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
138 if (rx->fd == -1 || connect (rx->fd, addrs->ai_addr, addrs->ai_addrlen))
140 freeaddrinfo (addrs);
141 xchat_printf (ph, "error connecting %s:%s, %s\n", rx->server, rx->port, strerror (errno));
142 return XCHAT_EAT_ALL;
144 freeaddrinfo (addrs);
146 struct iovec cmd[3] =
148 {"CHECK:", sizeof("CHECK:")-1},
149 {(void*)rx->list, strlen (rx->list)},
153 ssize_t written = writev (rx->fd, cmd, 3);
154 if (written < cmd[0].iov_len + cmd[1].iov_len + cmd[2].iov_len)
156 xchat_printf (ph, "error writing check commmand\n");
159 return XCHAT_EAT_ALL;
163 xchat_printf (ph, "established rxpd connection to %s:%s\n", rx->server, rx->port);
165 return XCHAT_EAT_ALL;
169 rxstop_cb (char *word[], char *word_eol[], void *userdata)
171 struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
178 xchat_printf (ph, "closed rxpd connection to %s:%s\n", rx->server, rx->port);
182 xchat_printf (ph, "no rxpd connection established\n");
184 return XCHAT_EAT_ALL;
188 rxadd_cb (char *word[], char *word_eol[], void *userdata)
190 //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
191 return XCHAT_EAT_ALL; /* eat this command so xchat and other plugins can't process it */
195 rxdel_cb (char *word[], char *word_eol[], void *userdata)
197 //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
198 return XCHAT_EAT_ALL; /* eat this command so xchat and other plugins can't process it */
202 rxlist_cb (char *word[], char *word_eol[], void *userdata)
204 //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
205 return XCHAT_EAT_ALL; /* eat this command so xchat and other plugins can't process it */
209 rxraw_cb (char *word[], char *word_eol[], void *userdata)
211 //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
212 return XCHAT_EAT_ALL; /* eat this command so xchat and other plugins can't process it */
216 rxdebug_cb (char *word[], char *word_eol[], void *userdata)
218 struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
220 xchat_printf (ph, "Turned rxpd debugging %s\n", rx->debug?"on":"off");
221 return XCHAT_EAT_ALL;
225 rxinfo_cb (char *word[], char *word_eol[], void *userdata)
227 struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
228 xchat_printf (ph, "RX: debugging is %s\n", rx->debug?"on":"off");
231 xchat_printf (ph, "RX: connected to %s:%s\n", rx->server, rx->port);
232 xchat_printf (ph, "RX: using list %s\n", rx->list);
235 xchat_printf (ph, "RX: not connected\n");
237 return XCHAT_EAT_ALL;
241 rxhook_cb (char *word[], char *word_eol[], void *userdata)
243 struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
247 /* ok do the checking*/
249 struct iovec check[2] =
251 {(void*)word_eol[1], strlen (word_eol[1])},
255 ssize_t written = writev (rx->fd, check, 2);
256 if (written < check[0].iov_len + 1)
258 xchat_printf (ph, "RXPD: error writing\n");
261 return XCHAT_EAT_NONE;
264 char* line = buffer_readline (rx);
266 if (rx->debug && !PREFIXCMP(line, "ok:"))
267 xchat_printf (ph, "RXPD: '%s'\n", line);
269 if (PREFIXCMP(line, "ignore:"))
270 return XCHAT_EAT_XCHAT;
272 //else if (PREFIXCMP(line, "kick:"))
273 //else if (PREFIXCMP(line, "kickban:"))
274 //else if (PREFIXCMP(line, "ban:"))
275 //else if (PREFIXCMP(line, "op:"))
279 return XCHAT_EAT_NONE;
283 xchat_plugin_init(xchat_plugin *plugin_handle,
286 char **plugin_version,
289 /* we need to save this for use with any xchat_* functions */
292 /* tell xchat our info */
293 *plugin_name = PNAME;
294 *plugin_desc = PDESC;
295 *plugin_version = PVERSION;
297 rx_private.debug = 0;
298 rx_private.server = NULL;
299 rx_private.port = NULL;
300 rx_private.list = NULL;
302 rx_private.eol = rx_private.eob = rx_private.buffer;
303 rx_private.buffer [4095] = '\0';
305 xchat_hook_command (ph, "RXSTART", XCHAT_PRI_NORM, rxstart_cb,
306 "Usage: RXSTART server port list; enables and connects to rxpd", &rx_private);
308 xchat_hook_command (ph, "RXSTOP", XCHAT_PRI_NORM, rxstop_cb,
309 "Usage: RXSTOP; disconnects and stops rxpd plugin", &rx_private);
311 xchat_hook_command (ph, "RXADD", XCHAT_PRI_NORM, rxadd_cb,
312 "Usage: RXADD listname rule; adds rule to list", &rx_private);
314 xchat_hook_command (ph, "RXDEL", XCHAT_PRI_NORM, rxdel_cb,
315 "Usage: RXDEL list rule; removes rule from list", &rx_private);
317 xchat_hook_command (ph, "RXLIST", XCHAT_PRI_NORM, rxlist_cb,
318 "Usage: RXLIST [list]; shows list", &rx_private);
320 xchat_hook_command (ph, "RXRAW", XCHAT_PRI_NORM, rxraw_cb,
321 "Usage: RXRAW ...; sends a raw command to the rxpd", &rx_private);
323 xchat_hook_command (ph, "RXDEBUG", XCHAT_PRI_NORM, rxdebug_cb,
324 "Usage: RXDEBUG; toggle rxpd plugin debugging", &rx_private);
326 xchat_hook_command (ph, "RXINFO", XCHAT_PRI_NORM, rxinfo_cb,
327 "Usage: RXINFO; show some information about the rxpd plugin", &rx_private);
329 xchat_hook_server (ph, "RAW LINE", XCHAT_PRI_NORM, rxhook_cb, &rx_private);
331 xchat_print (ph, "Rxpd plugin loaded successfully!\n");
337 xchat_plugin_deinit (void)
339 if (rx_private.fd != -1)
340 close (rx_private.fd);
342 xchat_printf (ph, "rxpd plugin unloaded\n");