ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/irc.c
(Generate patch)

Comparing hopm/trunk/src/irc.c (file contents):
Revision 5077 by michael, Mon Dec 22 18:34:34 2014 UTC vs.
Revision 5367 by michael, Mon Jan 12 20:13:22 2015 UTC

# Line 1 | Line 1
1 /* vim: set shiftwidth=3 softtabstop=3 expandtab: */
2
1   /*
2 < * Copyright (C) 2002-2003  Erik Fears
3 < *
6 < * This program is free software; you can redistribute it and/or
7 < * modify it under the terms of the GNU General Public License
8 < * as published by the Free Software Foundation; either version 2
9 < * of the License, or (at your option) any later version.
10 < *
11 < * This program is distributed in the hope that it will be useful,
12 < * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 < * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 < * GNU General Public License for more details.
15 < *
16 < * You should have received a copy of the GNU General Public License
17 < * along with this program; if not, write to
18 < *
19 < *       The Free Software Foundation, Inc.
20 < *       59 Temple Place - Suite 330
21 < *       Boston, MA  02111-1307, USA.
22 < *
2 > *  Copyright (c) 2002-2003 Erik Fears
3 > *  Copyright (c) 2014-2015 ircd-hybrid development team
4   *
5 + *  This program is free software; you can redistribute it and/or modify
6 + *  it under the terms of the GNU General Public License as published by
7 + *  the Free Software Foundation; either version 2 of the License, or
8 + *  (at your option) any later version.
9 + *
10 + *  This program is distributed in the hope that it will be useful,
11 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 + *  GNU General Public License for more details.
14 + *
15 + *  You should have received a copy of the GNU General Public License
16 + *  along with this program; if not, write to the Free Software
17 + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18 + *  USA
19   */
20  
21   #include "setup.h"
22  
23   #include <stdio.h>
24   #include <unistd.h>
25 <
26 < #ifdef STDC_HEADERS
32 < # include <stdlib.h>
33 < # include <string.h>
34 < #endif
35 <
36 < #ifdef HAVE_STRINGS_H
37 < # include <strings.h>
38 < #endif
39 <
25 > #include <stdlib.h>
26 > #include <string.h>
27   #include <sys/types.h>
28   #include <sys/socket.h>
29 + #include <netdb.h>
30   #include <netinet/in.h>
31   #include <arpa/inet.h>
32 <
33 < #ifdef TIME_WITH_SYS_TIME
34 < # include <sys/time.h>
47 < # include <time.h>
48 < #else
49 < # ifdef HAVE_SYS_TIME_H
50 < #  include <sys/time.h>
51 < # else
52 < #  include <time.h>
53 < # endif
54 < #endif
32 > #include <poll.h>
33 > #include <sys/time.h>
34 > #include <time.h>
35  
36   #include <errno.h>
37   #include <stdarg.h>
# Line 64 | Line 44
44   #include "scan.h"
45   #include "dnsbl.h"
46   #include "stats.h"
67 #include "extern.h"
47   #include "options.h"
48   #include "match.h"
49   #include "compat.h"
50   #include "negcache.h"
51 < #include "malloc.h"
51 > #include "memory.h"
52   #include "main.h"
53  
75 RCSID("$Id: irc.c,v 1.27 2003/11/29 19:56:19 strtok Exp $");
54  
55   static void irc_init(void);
56   static void irc_connect(void);
# Line 85 | Line 63 | static struct ChannelConf *get_channel(c
63   static struct UserInfo *userinfo_create(char *);
64   static void userinfo_free(struct UserInfo *source);
65  
66 < static void m_ping(char **, unsigned int, char *, struct UserInfo *);
67 < static void m_invite(char **, unsigned int, char *, struct UserInfo *);
68 < static void m_privmsg(char **, unsigned int, char *, struct UserInfo *);
69 < static void m_ctcp(char **, unsigned int, char *, struct UserInfo *);
70 < static void m_notice(char **, unsigned int, char *, struct UserInfo *);
71 < static void m_perform(char **, unsigned int, char *, struct UserInfo *);
72 < static void m_userhost(char **, unsigned int, char *, struct UserInfo *);
73 < static void m_cannot_join(char **, unsigned int, char *, struct UserInfo *);
74 < static void m_kill(char **, unsigned int, char *, struct UserInfo *);
66 > static void m_ping(char *[], unsigned int, char *, const struct UserInfo *);
67 > static void m_invite(char *[], unsigned int, char *, const struct UserInfo *);
68 > static void m_privmsg(char *[], unsigned int, char *, const struct UserInfo *);
69 > static void m_ctcp(char *[], unsigned int, char *, const struct UserInfo *);
70 > static void m_notice(char *[], unsigned int, char *, const struct UserInfo *);
71 > static void m_perform(char *[], unsigned int, char *, const struct UserInfo *);
72 > static void m_userhost(char *[], unsigned int, char *, const struct UserInfo *);
73 > static void m_cannot_join(char *[], unsigned int, char *, const struct UserInfo *);
74 > static void m_kill(char *[], unsigned int, char *, const struct UserInfo *);
75  
98 extern struct cnode *nc_head;
76  
77   /*
78   * Certain variables we don't want to allocate memory for over and over
79   * again so global scope is given.
80   */
81  
82 < char                 IRC_RAW[MSGLENMAX];         /* Buffer to read data into              */
83 < char                 IRC_SENDBUFF[MSGLENMAX];    /* Send buffer                           */
84 < char                 IRC_CHANNELS[MSGLENMAX];    /* Stores comma delim list of channels   */
85 < int                  IRC_RAW_LEN    = 0;         /* Position of IRC_RAW                   */
86 <
87 < int                  IRC_FD         = 0;        /* File descriptor for IRC client        */
88 <
89 < struct bopm_sockaddr IRC_SVR;                   /* Sock Address Struct for IRC server    */
90 < struct bopm_ircaddr  IRC_LOCAL;                 /* Sock Address Struct for Bind          */
91 <
92 < fd_set               IRC_READ_FDSET;             /* fd_set for IRC (read) data for select()*/
93 < struct timeval       IRC_TIMEOUT;                /* timeval struct for select() timeout   */
94 <
95 < time_t               IRC_LAST = 0;               /* Last full line of data from irc server*/
96 < time_t               IRC_LASTRECONNECT = 0;      /* Time of last reconnection */
97 <
98 < /* Table should be ordered with most occuring (or priority)
99 <   commands at the top of the list. */
100 <
101 < static struct CommandHash COMMAND_TABLE[] = {
102 <         {"NOTICE",               m_notice         },
103 <         {"PRIVMSG",              m_privmsg        },
104 <         {"PING",                 m_ping           },
105 <         {"INVITE",               m_invite         },
106 <         {"001",                  m_perform        },
107 <         {"302",                  m_userhost       },
108 <         {"471",                  m_cannot_join    },
109 <         {"473",                  m_cannot_join    },
133 <         {"474",                  m_cannot_join    },
134 <         {"475",                  m_cannot_join    },
135 <         {"KILL",                 m_kill           }
136 <      };
82 > static char          IRC_RAW[MSGLENMAX];         /* Buffer to read data into              */
83 > static unsigned int  IRC_RAW_LEN    = 0;         /* Position of IRC_RAW                   */
84 > static int           IRC_FD         = 0;         /* File descriptor for IRC client        */
85 >
86 > static struct sockaddr_storage IRC_SVR;          /* Sock Address Struct for IRC server    */
87 >
88 > static time_t IRC_LAST = 0;                      /* Last full line of data from irc server*/
89 > static time_t IRC_LASTRECONNECT = 0;             /* Time of last reconnection */
90 >
91 > /*
92 > * Table should be ordered with most occuring (or priority)
93 > * commands at the top of the list.
94 > */
95 > static struct CommandHash COMMAND_TABLE[] =
96 > {
97 >  { "NOTICE",   m_notice      },
98 >  { "PRIVMSG",  m_privmsg     },
99 >  { "PING",     m_ping        },
100 >  { "INVITE",   m_invite      },
101 >  { "001",      m_perform     },
102 >  { "302",      m_userhost    },
103 >  { "471",      m_cannot_join },
104 >  { "473",      m_cannot_join },
105 >  { "474",      m_cannot_join },
106 >  { "475",      m_cannot_join },
107 >  { "KILL",     m_kill        },
108 >  { NULL,       NULL          }
109 > };
110  
111   /* irc_cycle
112   *
# Line 144 | Line 117 | static struct CommandHash COMMAND_TABLE[
117   *
118   * Return:
119   *    None
147 *
120   */
121 <
122 < void irc_cycle(void)
121 > void
122 > irc_cycle(void)
123   {
124 <   if (IRC_FD <= 0)
153 <   {
154 <      /* Initialise negative cache. */
155 <      if (OptionsItem->negcache > 0)
156 <         nc_init(&nc_head);
157 <
158 <      /* Resolve remote host. */
159 <      irc_init();
160 <
161 <      /* Connect to remote host. */
162 <      irc_connect();
163 <
164 <      return;      /* In case connect() immediately failed */
165 <  }
166 <
167 <   IRC_TIMEOUT.tv_sec  = 0;
168 <   /* Block .025 seconds to avoid excessive CPU use on select(). */
169 <   IRC_TIMEOUT.tv_usec = 25000;
170 <
171 <   FD_ZERO(&IRC_READ_FDSET);
172 <   FD_SET(IRC_FD, &IRC_READ_FDSET);
173 <
174 <   switch (select((IRC_FD + 1), &IRC_READ_FDSET, 0, 0, &IRC_TIMEOUT))
175 <   {
176 <      case -1:
177 <         return;
178 <         break;
179 <      case 0:
180 <         break;
181 <      default:
182 <         /* Check if IRC data is available. */
183 <         if (FD_ISSET(IRC_FD, &IRC_READ_FDSET))
184 <            irc_read();
185 <         break;
186 <   }
187 < }
124 >  static struct pollfd pfd;
125  
126 +  if (IRC_FD <= 0)
127 +  {
128 +    /* Initialise negative cache. */
129 +    if (OptionsItem->negcache > 0)
130 +      nc_init(&nc_head);
131 +
132 +    /* Resolve remote host. */
133 +    irc_init();
134 +
135 +    /* Connect to remote host. */
136 +    irc_connect();
137 +    return;  /* In case connect() immediately failed */
138 +  }
139  
140 +  pfd.fd = IRC_FD;
141 +  pfd.events = POLLIN;
142  
143 +  /* Block .025 seconds to avoid excessive CPU use on poll(). */
144 +  switch (poll(&pfd, 1, 25))
145 +  {
146 +    case  0:
147 +    case -1:
148 +      break;
149 +    default:
150 +      /* Check if IRC data is available. */
151 +      if (pfd.revents & POLLIN)
152 +        irc_read();
153 +
154 +      break;
155 +  }
156 + }
157  
158   /* irc_init
159   *
# Line 198 | Line 164 | void irc_cycle(void)
164   *
165   * Return:
166   *    None
201 *
167   */
168 <
169 < static void irc_init(void)
168 > static void
169 > irc_init(void)
170   {
171 <   node_t *node;
207 <   struct ChannelConf *chan;
208 <   struct bopm_sockaddr bsaddr;
209 <   struct in_addr *irc_host;
210 <
211 <
212 <   if (IRC_FD)
213 <      close(IRC_FD);
214 <
215 <   memset(&IRC_SVR, 0, sizeof(IRC_SVR));
216 <   memset(&IRC_LOCAL, 0, sizeof(IRC_LOCAL));
217 <   memset(&bsaddr, 0, sizeof(struct bopm_sockaddr));
218 <
219 <   /* Resolve IRC host. */
220 <   if ((irc_host = firedns_resolveip4(IRCItem->server)) == NULL)
221 <   {
222 <      log_printf("IRC -> firedns_resolveip4(\"%s\"): %s", IRCItem->server,
223 <            firedns_strerror(fdns_errno));
224 <      exit(EXIT_FAILURE);
225 <   }
171 >  const void *address = NULL;
172  
173 <   IRC_SVR.sa4.sin_family = AF_INET;
174 <   IRC_SVR.sa4.sin_port = htons(IRCItem->port);
175 <   IRC_SVR.sa4.sin_addr = *irc_host;
176 <
231 <   if (IRC_SVR.sa4.sin_addr.s_addr == INADDR_NONE)
232 <   {
233 <      log_printf("IRC -> Unknown error resolving remote host (%s)",
234 <          IRCItem->server);
235 <      exit(EXIT_FAILURE);
236 <   }
173 >  if (IRC_FD)
174 >    close(IRC_FD);
175 >
176 >  memset(&IRC_SVR, 0, sizeof(IRC_SVR));
177  
178 <   /* Request file desc for IRC client socket */
179 <   IRC_FD = socket(AF_INET, SOCK_STREAM, 0);
178 >  /* Resolve IRC host. */
179 >  if ((address = firedns_resolveip6(IRCItem->server)))
180 >  {
181 >    struct sockaddr_in6 *in = (struct sockaddr_in6 *)&IRC_SVR;
182  
183 <   if (IRC_FD == -1)
184 <   {
185 <      switch(errno)
186 <      {
187 <         case EINVAL:
188 <         case EPROTONOSUPPORT:
189 <            log_printf("IRC -> socket(): SOCK_STREAM is not "
190 <                "supported on this domain");
191 <            break;
192 <         case ENFILE:
193 <            log_printf("IRC -> socket(): Not enough free file "
194 <                "descriptors to allocate IRC socket");
195 <            break;
196 <         case EMFILE:
197 <            log_printf("IRC -> socket(): Process table overflow when "
198 <                "requesting file descriptor");
199 <            break;
200 <         case EACCES:
201 <            log_printf("IRC -> socket(): Permission denied to create "
202 <                "socket of type SOCK_STREAM");
203 <            break;
204 <         case ENOMEM:
205 <            log_printf("IRC -> socket(): Insufficient memory to "
206 <                "allocate socket");
207 <            break;
208 <         default:
209 <            log_printf("IRC -> socket(): Unknown error allocating "
210 <                "socket");
211 <            break;
212 <      }
183 >    IRC_SVR.ss_family = AF_INET6;
184 >    in->sin6_port = htons(IRCItem->port);
185 >    memcpy(&in->sin6_addr, address, sizeof(in->sin6_addr));
186 >  }
187 >  else if ((address = firedns_resolveip4(IRCItem->server)))
188 >  {
189 >    struct sockaddr_in *in = (struct sockaddr_in *)&IRC_SVR;
190 >
191 >    IRC_SVR.ss_family = AF_INET;
192 >    in->sin_port = htons(IRCItem->port);
193 >    memcpy(&in->sin_addr, address, sizeof(in->sin_addr));
194 >  }
195 >  else
196 >  {
197 >    log_printf("IRC -> firedns_resolveip(\"%s\"): %s", IRCItem->server,
198 >               firedns_strerror(fdns_errno));
199 >    exit(EXIT_FAILURE);
200 >  }
201 >
202 >  /* Request file desc for IRC client socket */
203 >  IRC_FD = socket(IRC_SVR.ss_family, SOCK_STREAM, 0);
204 >
205 >  if (IRC_FD == -1)
206 >  {
207 >    log_printf("IRC -> socket(): error creating socket: %s", strerror(errno));
208 >    exit(EXIT_FAILURE);
209 >  }
210 >
211 >  /* Bind */
212 >  if (!EmptyString(IRCItem->vhost))
213 >  {
214 >    struct addrinfo hints, *res;
215 >
216 >    memset(&hints, 0, sizeof(hints));
217 >
218 >    hints.ai_family = AF_UNSPEC;
219 >    hints.ai_socktype = SOCK_STREAM;
220 >    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
221 >
222 >    if (getaddrinfo(IRCItem->vhost, NULL, &hints, &res))
223 >    {
224 >      log_printf("IRC -> bind(): %s is an invalid address", IRCItem->vhost);
225 >      exit(EXIT_FAILURE);
226 >    }
227 >    else if (bind(IRC_FD, res->ai_addr, res->ai_addrlen))
228 >    {
229 >      log_printf("IRC -> bind(): error binding to %s: %s", IRCItem->vhost, strerror(errno));
230        exit(EXIT_FAILURE);
231 <   }
231 >    }
232  
233 <   /* Bind */
234 <   if (!EmptyString(IRCItem->vhost))
276 <   {
277 <      int bindret = 0;
278 <      if (!inet_pton(AF_INET, IRCItem->vhost, &(IRC_LOCAL.in4.s_addr)))
279 <      {
280 <         log_printf("IRC -> bind(): %s is an invalid address", IRCItem->vhost);
281 <         exit(EXIT_FAILURE);
282 <      }
283 <      bsaddr.sa4.sin_addr.s_addr = IRC_LOCAL.in4.s_addr;
284 <      bsaddr.sa4.sin_family = AF_INET;
285 <      bsaddr.sa4.sin_port = htons(0);
286 <
287 <      bindret = bind(IRC_FD, (struct sockaddr *) &(bsaddr.sa4), sizeof(bsaddr.sa4));
288 <
289 <      if (bindret)
290 <      {
291 <         switch(errno)
292 <         {
293 <            case EACCES:
294 <               log_printf("IRC -> bind(): No access to bind to %s",
295 <                   IRCItem->vhost);
296 <               break;
297 <            default:
298 <               log_printf("IRC -> bind(): Error binding to %s (%d)",
299 <                   IRCItem->vhost, errno);
300 <               break;
301 <         }
302 <         exit(EXIT_FAILURE);
303 <      }
304 <
305 <   }
306 <
307 <   /* Setup target list for irc_send_channels */
308 <   IRC_CHANNELS[0] = '\0';
309 <   LIST_FOREACH(node, IRCItem->channels->head)
310 <   {
311 <      chan = (struct ChannelConf *) node->data;
312 <      strlcat(IRC_CHANNELS, chan->name, sizeof(IRC_CHANNELS));
313 <
314 <      if(node->next)
315 <         strlcat(IRC_CHANNELS, ",", sizeof(IRC_CHANNELS));
316 <   }
233 >    freeaddrinfo(res);
234 >  }
235   }
236  
319
237   /* irc_send
238   *
239   *    Send data to remote IRC host.
# Line 327 | Line 244 | static void irc_init(void)
244   *
245   * Return: NONE
246   */
247 <
248 <
332 < void irc_send(const char *data, ...)
247 > void
248 > irc_send(const char *data, ...)
249   {
250 <   va_list arglist;
251 <   char    data2[MSGLENMAX];
252 <   char    tosend[MSGLENMAX];
253 <
254 <   va_start(arglist, data);
255 <   vsnprintf(data2, MSGLENMAX, data, arglist);
256 <   va_end(arglist);
257 <
258 <   if (OPT_DEBUG >= 2)
259 <      log_printf("IRC SEND -> %s", data2);
260 <
261 <   snprintf(tosend, MSGLENMAX, "%s\n", data2);
262 <
263 <   if (send(IRC_FD, tosend, strlen(tosend), 0) == -1)
264 <   {
265 <      /* Return of -1 indicates error sending data; we reconnect. */
266 <      log_printf("IRC -> Error sending data to server\n");
267 <      irc_reconnect();
268 <   }
250 >  va_list arglist;
251 >  char buf[MSGLENMAX];
252 >  size_t len = 0;
253 >
254 >  va_start(arglist, data);
255 >  len = vsnprintf(buf, sizeof(buf), data, arglist);
256 >  va_end(arglist);
257 >
258 >  if (OPT_DEBUG >= 2)
259 >    log_printf("IRC SEND -> %s", buf);
260 >
261 >  if (len > 510)
262 >    len = 510;
263 >
264 >  buf[len++] = '\r';
265 >  buf[len++] = '\n';
266 >
267 >  if (send(IRC_FD, buf, len, 0) == -1)
268 >  {
269 >    /* Return of -1 indicates error sending data; we reconnect. */
270 >    log_printf("IRC -> Error sending data to server: %s", strerror(errno));
271 >    irc_reconnect();
272 >  }
273   }
274  
275   /* irc_send
# Line 362 | Line 282 | void irc_send(const char *data, ...)
282   *
283   * Return: NONE
284   */
285 <
286 < void irc_send_channels(const char *data, ...)
285 > void
286 > irc_send_channels(const char *data, ...)
287   {
288 <   va_list arglist;
289 <   char    data2[MSGLENMAX];
290 <   char    tosend[MSGLENMAX];
288 >  const node_t *node;
289 >  va_list arglist;
290 >  char buf[MSGLENMAX];
291 >
292 >  va_start(arglist, data);
293 >  vsnprintf(buf, sizeof(buf), data, arglist);
294 >  va_end(arglist);
295 >
296 >  LIST_FOREACH(node, IRCItem->channels->head)
297 >  {
298 >    const struct ChannelConf *chan = node->data;
299  
300 <   va_start(arglist, data);
301 <   vsnprintf(data2, MSGLENMAX, data, arglist);
374 <   va_end(arglist);
375 <
376 <   snprintf(tosend, MSGLENMAX, "PRIVMSG %s :%s", IRC_CHANNELS, data2);
377 <
378 <   irc_send("%s", tosend);
300 >    irc_send("PRIVMSG %s :%s", chan->name, buf);
301 >  }
302   }
303  
381
382
383
304   /* irc_connect
305   *
306   *    Connect to IRC server.
# Line 388 | Line 308 | void irc_send_channels(const char *data,
308   *
309   * Parameters: NONE
310   * Return: NONE
391 *
311   */
312 <
313 < static void irc_connect(void)
312 > static void
313 > irc_connect(void)
314   {
315 <   /* Connect to IRC server as client. */
316 <   if (connect(IRC_FD, (struct sockaddr *) &IRC_SVR,
317 <               sizeof(IRC_SVR)) == -1)
318 <   {
319 <      switch(errno)
320 <      {
321 <         case EISCONN:
403 <            /* Already connected */
404 <            return;
405 <         case ECONNREFUSED:
406 <            log_printf("IRC -> connect(): Connection refused by (%s)",
407 <                IRCItem->server);
408 <            break;
409 <         case ETIMEDOUT:
410 <            log_printf("IRC -> connect(): Timed out connecting to (%s)",
411 <                IRCItem->server);
412 <            break;
413 <         case ENETUNREACH:
414 <            log_printf("IRC -> connect(): Network unreachable");
415 <            break;
416 <         case EALREADY:
417 <            /* Previous attempt not complete */
418 <            return;
419 <         default:
420 <            log_printf("IRC -> connect(): Unknown error connecting to (%s)",
421 <                IRCItem->server);
422 <
423 <            if (OPT_DEBUG >= 1)
424 <               log_printf("%s", strerror(errno));
425 <      }
426 <      /* Try to connect again */
427 <      irc_reconnect();
315 >  /* Connect to IRC server as client. */
316 >  if (connect(IRC_FD, (struct sockaddr *)&IRC_SVR, sizeof(IRC_SVR)) == -1)
317 >  {
318 >    log_printf("IRC -> connect(): error connecting to %s: %s",
319 >               IRCItem->server, strerror(errno));
320 >
321 >    if (errno == EISCONN /* Already connected */ || errno == EALREADY /* Previous attempt not complete */)
322        return;
429   }
323  
324 <   irc_send("NICK %s", IRCItem->nick);
324 >    /* Try to connect again */
325 >    irc_reconnect();
326 >    return;
327 >  }
328  
329 <   if (!EmptyString(IRCItem->password))
434 <      irc_send("PASS %s", IRCItem->password);
329 >  irc_send("NICK %s", IRCItem->nick);
330  
331 <   irc_send("USER %s %s %s :%s",
332 <            IRCItem->username, IRCItem->username, IRCItem->username,
438 <            IRCItem->realname);
331 >  if (!EmptyString(IRCItem->password))
332 >    irc_send("PASS %s", IRCItem->password);
333  
334 <   time(&IRC_LAST);
334 >  irc_send("USER %s %s %s :%s",
335 >           IRCItem->username,
336 >           IRCItem->username,
337 >           IRCItem->username,
338 >           IRCItem->realname);
339 >  time(&IRC_LAST);
340   }
341  
443
342   /* irc_reconnect
343   *
344   *    Close connection to IRC server.
# Line 449 | Line 347 | static void irc_connect(void)
347   *
348   * Return: NONE
349   */
350 <
351 < static void irc_reconnect(void)
350 > static void
351 > irc_reconnect(void)
352   {
353 +  time_t present;
354  
355 <   time_t present;
457 <  
458 <   time(&present);
459 <  
460 <   /* Only try to reconnect every RECONNECT_INTERVAL seconds */
461 <   if((present - IRC_LASTRECONNECT) < RECONNECTINTERVAL)
462 <   {
463 <      /* Sleep to avoid excessive CPU */
464 <      sleep(1);
465 <      return;
466 <   }
467 <
468 <   time(&IRC_LASTRECONNECT);
355 >  time(&present);
356  
357 <   if(IRC_FD > 0)
358 <      close(IRC_FD);
357 >  /* Only try to reconnect every RECONNECT_INTERVAL seconds */
358 >  if ((present - IRC_LASTRECONNECT) < RECONNECTINTERVAL)
359 >  {
360 >    /* Sleep to avoid excessive CPU */
361 >    sleep(1);
362 >    return;
363 >  }
364  
365 <   /* Set IRC_FD 0 for reconnection on next irc_cycle(). */
474 <   IRC_FD = 0;
365 >  time(&IRC_LASTRECONNECT);
366  
367 <   log_printf("IRC -> Connection to (%s) failed, reconnecting.", IRCItem->server);
368 < }
367 >  if (IRC_FD > 0)
368 >    close(IRC_FD);
369  
370 +  /* Set IRC_FD 0 for reconnection on next irc_cycle(). */
371 +  IRC_FD = 0;
372  
373 +  log_printf("IRC -> Connection to (%s) failed, reconnecting.", IRCItem->server);
374 + }
375  
376   /* irc_read
377   *
378   *    irc_read is called my irc_cycle when new data is ready to be
379 < *    read from the irc server.
379 > *    read from the irc server.
380   *
381   * Parameters: NONE
382   * Return: NONE
488 *
383   */
384 <
385 < static void irc_read(void)
384 > static void
385 > irc_read(void)
386   {
387 <   int len;
388 <   char c;
387 >  int len;
388 >  char c;
389  
390 <   while ((len = read(IRC_FD, &c, 1)) > 0)
391 <   {
392 <      if (c == '\r')
393 <         continue;
394 <
395 <      if (c == '\n')
396 <      {
397 <         /* Null string. */
398 <         IRC_RAW[IRC_RAW_LEN] = '\0';
399 <         /* Parse line. */
400 <         irc_parse();
401 <         /* Reset counter. */
402 <         IRC_RAW_LEN = 0;
403 <         break;
510 <      }
511 <
512 <      if (c != '\r' && c != '\n' && c != '\0')
513 <         IRC_RAW[IRC_RAW_LEN++] = c;
514 <   }
515 <
516 <   if((len <= 0) && (errno != EAGAIN))
517 <   {
518 <      if(OPT_DEBUG >= 2)
519 <         log_printf("irc_read -> errno=%d len=%d", errno, len);
520 <      irc_reconnect();
390 >  while ((len = read(IRC_FD, &c, 1)) > 0)
391 >  {
392 >    if (c == '\r')
393 >      continue;
394 >
395 >    if (c == '\n')
396 >    {
397 >      /* Null string. */
398 >      IRC_RAW[IRC_RAW_LEN] = '\0';
399 >
400 >      /* Parse line. */
401 >      irc_parse();
402 >
403 >      /* Reset counter. */
404        IRC_RAW_LEN = 0;
405 <      return;
406 <   }
407 < }
405 >      break;
406 >    }
407 >
408 >    if (c != '\0')
409 >      IRC_RAW[IRC_RAW_LEN++] = c;
410 >  }
411  
412 +  if ((len <= 0) && (errno != EAGAIN))
413 +  {
414 +    if (OPT_DEBUG >= 2)
415 +      log_printf("irc_read -> errno=%d len=%d", errno, len);
416 +
417 +    irc_reconnect();
418 +    IRC_RAW_LEN = 0;
419 +    return;
420 +  }
421 + }
422  
423   /* irc_parse
424   *
# Line 531 | Line 427 | static void irc_read(void)
427   *
428   * Parameters: NONE
429   * Return: NONE
534 *
430   */
431 <
432 <
538 < static void irc_parse(void)
431 > static void
432 > irc_parse(void)
433   {
434 <   struct UserInfo *source_p;
435 <   char *pos;
542 <   unsigned int i;
543 <
544 <   /*
545 <      parv stores the parsed token, parc is the count of the parsed
546 <      tokens
547 <    
548 <      parv[0] is ALWAYS the source, and is the server name of the source
549 <      did not exist
550 <   */
551 <
552 <   static char            *parv[17];
553 <   static unsigned int     parc;
554 <   static char             msg[MSGLENMAX];    /* Temporarily stores IRC msg to pass to handlers */
555 <
556 <   parc = 1;
434 >  struct UserInfo *source_p;
435 >  char *pos;
436  
437 <   if(IRC_RAW_LEN <= 0)
438 <      return;
439 <
440 <   if (OPT_DEBUG >= 2)
441 <      log_printf("IRC READ -> %s", IRC_RAW);
442 <
443 <   time(&IRC_LAST);
437 >  /*
438 >   * parv stores the parsed token, parc is the count of the parsed
439 >   * tokens
440 >   *
441 >   * parv[0] is ALWAYS the source, and is the server name of the source
442 >   * did not exist
443 >   */
444 >  char            *parv[17];
445 >  unsigned int     parc = 1;
446 >  char             msg[MSGLENMAX];    /* Temporarily stores IRC msg to pass to handlers */
447 >
448 >  if (IRC_RAW_LEN == 0)
449 >    return;
450 >
451 >  if (OPT_DEBUG >= 2)
452 >    log_printf("IRC READ -> %s", IRC_RAW);
453 >
454 >  time(&IRC_LAST);
455 >
456 >  /* Store a copy of IRC_RAW for the handlers (for functions that need PROOF) */
457 >  strlcpy(msg, IRC_RAW, sizeof(msg));
458 >
459 >  /* parv[0] is always the source */
460 >  if (IRC_RAW[0] == ':')
461 >    parv[0] = IRC_RAW + 1;
462 >  else
463 >  {
464 >    parv[0] = IRCItem->server;
465 >    parv[parc++] = IRC_RAW;
466 >  }
467  
468 <   /* Store a copy of IRC_RAW for the handlers (for functions that need PROOF) */
567 <   strlcpy(msg, IRC_RAW, sizeof(msg));
468 >  pos = IRC_RAW;
469  
470 <   /* parv[0] is always the source */
471 <   if(IRC_RAW[0] == ':')
472 <      parv[0] = IRC_RAW + 1;
473 <   else
474 <   {
574 <      parv[0] = IRCItem->server;
575 <      parv[parc++] = IRC_RAW;
576 <   }
577 <
578 <   pos = IRC_RAW;
579 <
580 <   while((pos = strchr(pos, ' ')) && parc <= 17)
581 <   {
582 <
583 <      /* Avoid excessive spaces and end of IRC_RAW */
584 <      if(*(pos + 1) == ' ' && *(pos + 1) == '\0')
585 <      {
586 <         pos++;
587 <         continue;
588 <      }
589 <
590 <      /* Anything after a : is considered the final string of the
591 <            message */
592 <      if(*(pos + 1) == ':')
593 <      {
594 <         parv[parc++] = pos + 2;
595 <         *pos = '\0';
596 <         break;
597 <      }
598 <
599 <      /* Set the next parv at this position and replace the space with a
600 <         \0 for the previous parv */
601 <      parv[parc++] = pos + 1;
602 <      *pos = '\0';
470 >  while ((pos = strchr(pos, ' ')) && parc <= 17)
471 >  {
472 >    /* Avoid excessive spaces and end of IRC_RAW */
473 >    if (*(pos + 1) == ' ' || *(pos + 1) == '\0')
474 >    {
475        pos++;
476 <   }
476 >      continue;
477 >    }
478  
479 <   /* Generate a UserInfo struct from the source */
479 >    /* Anything after a : is considered the final string of the message */
480 >    if (*(pos + 1) == ':')
481 >    {
482 >      parv[parc++] = pos + 2;
483 >      *pos = '\0';
484 >      break;
485 >    }
486  
487 <   source_p = userinfo_create(parv[0]);
487 >    /*
488 >     * Set the next parv at this position and replace the space with a
489 >     * \0 for the previous parv
490 >     */
491 >    parv[parc++] = pos + 1;
492 >    *pos = '\0';
493 >    pos++;
494 >  }
495  
496 <   /* Determine which command this is from the command table
497 <      and let the handler for that command take control */
496 >  /* Generate a UserInfo struct from the source */
497 >  source_p = userinfo_create(parv[0]);
498  
499 <   for(i = 0; i < (sizeof(COMMAND_TABLE) / sizeof(struct CommandHash)); i++)
500 <      if(strcasecmp(COMMAND_TABLE[i].command, parv[1]) == 0)
501 <      {
502 <         (*COMMAND_TABLE[i].handler)(parv, parc, msg, source_p);
503 <         break;
504 <      }
499 >  /*
500 >   * Determine which command this is from the command table
501 >   * and let the handler for that command take control
502 >   */
503 >  for (const struct CommandHash *cmd = COMMAND_TABLE; cmd->command; ++cmd)
504 >  {
505 >    if (strcasecmp(cmd->command, parv[1]) == 0)
506 >    {
507 >      cmd->handler(parv, parc, msg, source_p);
508 >      break;
509 >    }
510 >  }
511  
512 <   userinfo_free(source_p);
512 >  userinfo_free(source_p);
513   }
514  
623
624
625
515   /* irc_timer
516   *
517   *    Functions to be performed every ~seconds.
518   *
519   * Parameters: NONE
520   * Return: NONE
632 *
521   */
522 <
523 < void irc_timer(void)
522 > void
523 > irc_timer(void)
524   {
525 <   time_t present, delta;
525 >  time_t present, delta;
526  
527 <   time(&present);
527 >  time(&present);
528  
529 <   delta = present - IRC_LAST;
529 >  delta = present - IRC_LAST;
530  
531 <   /* No data in NODATA_TIMEOUT minutes (set in options.h). */
532 <   if (delta >= NODATA_TIMEOUT)
533 <   {
534 <      log_printf("IRC -> Timeout awaiting data from server.");
535 <      irc_reconnect();
648 <      /* Make sure we dont do this again for a while */
649 <      time(&IRC_LAST);
650 <   }
651 <   else if (delta >= NODATA_TIMEOUT / 2)
652 <   {
653 <      /*
654 <       * Generate some data so high ping times or bugs in certain
655 <       * ircds (*cough* unreal *cough*) don't cause uneeded
656 <       * reconnections
657 <       */
658 <      irc_send("PING :HOPM");
659 <   }
531 >  /* No data in IRCItem->readtimeout seconds */
532 >  if (delta >= IRCItem->readtimeout)
533 >  {
534 >    log_printf("IRC -> Timeout awaiting data from server.");
535 >    irc_reconnect();
536  
537 +    /* Make sure we don't do this again for a while */
538 +    time(&IRC_LAST);
539 +  }
540 +  else if (delta >= IRCItem->readtimeout / 2)
541 +  {
542 +    /*
543 +     * Generate some data so high ping times don't cause uneeded
544 +     * reconnections
545 +     */
546 +    irc_send("PING :HOPM");
547 +  }
548   }
549  
663
664
665
550   /* get_channel
551   *
552   *    Check if a channel is defined in our conf. If so return
# Line 673 | Line 557 | void irc_timer(void)
557   *
558   * Return: Pointer to ChannelConf containing the channel
559   */
560 <
561 < static struct ChannelConf *get_channel(const char *channel)
560 > static struct ChannelConf *
561 > get_channel(const char *channel)
562   {
563 <   node_t *node;
680 <   struct ChannelConf *item;
563 >  node_t *node;
564  
565 <   LIST_FOREACH(node, IRCItem->channels->head)
566 <   {
567 <      item = node->data;
565 >  LIST_FOREACH(node, IRCItem->channels->head)
566 >  {
567 >    struct ChannelConf *item = node->data;
568  
569 <      if(strcasecmp(item->name, channel) == 0)
570 <         return item;
571 <   }
569 >    if (strcasecmp(item->name, channel) == 0)
570 >      return item;
571 >  }
572  
573 <   return NULL;
573 >  return NULL;
574   }
575  
693
576   /* userinfo_create
577   *
578   *    Parse a nick!user@host into a UserInfo struct
# Line 701 | Line 583 | static struct ChannelConf *get_channel(c
583   *
584   * Return:
585   *    pointer to new UserInfo struct, or NULL if parsing failed
704 *
586   */
587 <
588 < static struct UserInfo *userinfo_create(char *source)
587 > static struct UserInfo *
588 > userinfo_create(char *source)
589   {
590 <   struct UserInfo *ret;
591 <
592 <   char *nick;
593 <   char *username;
594 <   char *hostname;
595 <   char *tmp;
596 <
597 <   int i, len;
598 <
599 <   nick = username = hostname = NULL;
600 <   tmp = DupString(source);
601 <   len = strlen(tmp);
602 <
603 <   nick = tmp;
604 <
605 <   for(i = 0; i < len; i++)
606 <   {
607 <      if(tmp[i] == '!')
608 <      {
609 <         tmp[i] = '\0';
610 <         username = tmp + i + 1;
611 <      }
612 <      if(tmp[i] == '@')
613 <      {
614 <         tmp[i] = '\0';
615 <         hostname = tmp + i + 1;
735 <      }
736 <   }
737 <
738 <   if(nick == NULL || username == NULL || hostname == NULL)
739 <   {
740 <      MyFree(tmp);
741 <      return NULL;
742 <   }
743 <
744 <   ret = MyMalloc(sizeof *ret);
745 <
746 <   ret->irc_nick     = DupString(nick);
747 <   ret->irc_username = DupString(username);
748 <   ret->irc_hostname = DupString(hostname);
590 >  struct UserInfo *ret;
591 >  char *nick;
592 >  char *username;
593 >  char *hostname;
594 >  char *tmp;
595 >  int i, len;
596 >
597 >  nick = username = hostname = NULL;
598 >  tmp = xstrdup(source);
599 >  len = strlen(tmp);
600 >  nick = tmp;
601 >
602 >  for (i = 0; i < len; ++i)
603 >  {
604 >    if (tmp[i] == '!')
605 >    {
606 >      tmp[i] = '\0';
607 >      username = tmp + i + 1;
608 >    }
609 >
610 >    if (tmp[i] == '@')
611 >    {
612 >      tmp[i] = '\0';
613 >      hostname = tmp + i + 1;
614 >    }
615 >  }
616  
617 <   MyFree(tmp);
617 >  if (nick == NULL || username == NULL || hostname == NULL)
618 >  {
619 >    MyFree(tmp);
620 >    return NULL;
621 >  }
622  
623 <   return ret;
624 < };
623 >  ret = xcalloc(sizeof *ret);
624 >  ret->irc_nick     = xstrdup(nick);
625 >  ret->irc_username = xstrdup(username);
626 >  ret->irc_hostname = xstrdup(hostname);
627  
628 +  MyFree(tmp);
629  
630 +  return ret;
631 + };
632  
633   /* userinfo_free
634   *
# Line 760 | Line 636 | static struct UserInfo *userinfo_create(
636   *
637   * Parameters:
638   *    source: struct to free
763 *
764 * Return: None
639   *
640 + * Return: None
641   */
642 <
643 < static void userinfo_free(struct UserInfo *source_p)
642 > static void
643 > userinfo_free(struct UserInfo *source_p)
644   {
645 <   if(source_p == NULL)
646 <      return;
645 >  if (source_p == NULL)
646 >    return;
647  
648 <   MyFree(source_p->irc_nick);
649 <   MyFree(source_p->irc_username);
650 <   MyFree(source_p->irc_hostname);
651 <   MyFree(source_p);
648 >  MyFree(source_p->irc_nick);
649 >  MyFree(source_p->irc_username);
650 >  MyFree(source_p->irc_hostname);
651 >  MyFree(source_p);
652   }
653  
779
780
654   /* m_perform
655   *
656   *    actions to perform on IRC connection
# Line 790 | Line 663 | static void userinfo_free(struct UserInf
663   * source_p: UserInfo struct of the source user, or NULL if
664   * the source (parv[0]) is a server.
665   */
666 <
667 < static void m_perform(char **parv, unsigned int parc, char *msg, struct UserInfo *notused)
666 > static void
667 > m_perform(char *parv[], unsigned int parc, char *msg, const struct UserInfo *notused)
668   {
669 <   node_t *node;
797 <   struct ChannelConf *channel;
798 <
799 <   USE_VAR(parv);
800 <   USE_VAR(parc);
801 <   USE_VAR(msg);
802 <   USE_VAR(notused);
669 >  node_t *node;
670  
671 <   log_printf("IRC -> Connected to %s:%d", IRCItem->server, IRCItem->port);
671 >  log_printf("IRC -> Connected to %s/%d", IRCItem->server, IRCItem->port);
672  
673 <   /* Identify to nickserv if needed */
674 <   if (!EmptyString(IRCItem->nickserv))
675 <      irc_send("%s", IRCItem->nickserv);
673 >  /* Identify to nickserv if needed */
674 >  if (!EmptyString(IRCItem->nickserv))
675 >    irc_send("%s", IRCItem->nickserv);
676  
677 <   /* Oper */
678 <   irc_send("OPER %s", IRCItem->oper);
677 >  /* Oper */
678 >  irc_send("OPER %s", IRCItem->oper);
679  
680 <   /* Set modes */
681 <   irc_send("MODE %s %s", IRCItem->nick, IRCItem->mode);
680 >  /* Set modes */
681 >  irc_send("MODE %s %s", IRCItem->nick, IRCItem->mode);
682  
683 <   /* Set Away */
684 <   irc_send("AWAY :%s", IRCItem->away);
683 >  /* Set Away */
684 >  if (!EmptyString(IRCItem->away))
685 >    irc_send("AWAY :%s", IRCItem->away);
686  
687 <   /* Perform */
688 <   LIST_FOREACH(node, IRCItem->performs->head)
689 <      irc_send("%s", (char *) node->data);
687 >  /* Perform */
688 >  LIST_FOREACH(node, IRCItem->performs->head)
689 >    irc_send("%s", node->data);
690  
691 <   /* Join all listed channels. */
692 <   LIST_FOREACH(node, IRCItem->channels->head)
693 <   {
694 <      channel = (struct ChannelConf *) node->data;
691 >  /* Join all listed channels. */
692 >  LIST_FOREACH(node, IRCItem->channels->head)
693 >  {
694 >    const struct ChannelConf *channel = node->data;
695  
696 <      if (EmptyString(channel->name))
697 <         continue;
696 >    if (EmptyString(channel->name))
697 >      continue;
698  
699 <      if (!EmptyString(channel->key))
700 <         irc_send("JOIN %s %s", channel->name, channel->key);
701 <      else
702 <         irc_send("JOIN %s", channel->name);
703 <   }
699 >    if (!EmptyString(channel->key))
700 >      irc_send("JOIN %s %s", channel->name, channel->key);
701 >    else
702 >      irc_send("JOIN %s", channel->name);
703 >  }
704   }
705  
838
706   /* m_ping
707   *
708   * parv[0]  = source
# Line 845 | Line 712 | static void m_perform(char **parv, unsig
712   * source_p: UserInfo struct of the source user, or NULL if
713   * the source (parv[0]) is a server.
714   */
715 < static void m_ping(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
715 > static void
716 > m_ping(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
717   {
718 <   USE_VAR(msg);
719 <   USE_VAR(source_p);
852 <
853 <   if(parc < 3)
854 <      return;
718 >  if (parc < 3)
719 >    return;
720  
721 <   if(OPT_DEBUG >= 2)
722 <      log_printf("IRC -> PING? PONG!");
721 >  if (OPT_DEBUG >= 2)
722 >    log_printf("IRC -> PING? PONG!");
723  
724 <   irc_send("PONG %s", parv[2]);
724 >  irc_send("PONG %s", parv[2]);
725   }
726  
862
863
727   /* m_invite
728   *
729   * parv[0]  = source
# Line 870 | Line 733 | static void m_ping(char **parv, unsigned
733   *
734   * source_p: UserInfo struct of the source user, or NULL if
735   * the source (parv[0]) is a server.
873 *
736   */
737 <
738 < static void m_invite(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
737 > static void
738 > m_invite(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
739   {
740 <   struct ChannelConf *channel;
879 <  
880 <   USE_VAR(msg);
881 <   USE_VAR(source_p);
740 >  struct ChannelConf *channel = NULL;
741  
742 <   if(parc < 4)
743 <      return;
742 >  if (parc < 4)
743 >    return;
744  
745 <   log_printf("IRC -> Invited to %s by %s", parv[3], parv[0]);
745 >  log_printf("IRC -> Invited to %s by %s", parv[3], parv[0]);
746  
747 <   if((channel = get_channel(parv[3])) == NULL)
748 <      return;
747 >  if ((channel = get_channel(parv[3])) == NULL)
748 >    return;
749  
750 <   irc_send("JOIN %s %s", channel->name, channel->key);
750 >  irc_send("JOIN %s %s", channel->name, channel->key);
751   }
752  
894
895
896
753   /* m_privmsg
754   *
755   * parv[0]  = source
# Line 903 | Line 759 | static void m_invite(char **parv, unsign
759   *
760   * source_p: UserInfo struct of the source user, or NULL if
761   * the source (parv[0]) is a server.
906 *
762   */
763 <
764 < static void m_privmsg(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
763 > static void
764 > m_privmsg(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
765   {
766 <   struct ChannelConf *channel;
767 <   size_t nick_len;
913 <
914 <   if(source_p == NULL)
915 <      return;
916 <
917 <   if(parc < 4)
918 <      return;
766 >  struct ChannelConf *channel = NULL;
767 >  size_t nick_len;
768  
769 <   /* CTCP */
770 <   if(parv[3][0] == '\001')
922 <      m_ctcp(parv, parc, msg, source_p);
769 >  if (source_p == NULL)
770 >    return;
771  
772 <   /* Only interested in privmsg to channels */
773 <   if(parv[2][0] != '#' && parv[2][0] != '&')
774 <      return;
775 <
776 <   /* Get a target */
777 <   if((channel = get_channel(parv[2])) == NULL)
778 <      return;
779 <
780 <   /* Find a suitable length to compare with */
781 <   nick_len = strcspn(parv[3], " :,");
782 <   if(nick_len < 3 && strlen(IRCItem->nick) >= 3)
783 <      nick_len = 3;
784 <  
785 <   /* message is a command */
786 <   if(strncasecmp(parv[3], IRCItem->nick, nick_len) == 0  ||
787 <         strncasecmp(parv[3], "!all", 4) == 0)
788 <   {
789 <      /* XXX command_parse will alter parv[3]. */
790 <      command_parse(parv[3], msg, channel, source_p);
791 <   }
772 >  if (parc < 4)
773 >    return;
774 >
775 >  /* CTCP */
776 >  if (parv[3][0] == '\001')
777 >    m_ctcp(parv, parc, msg, source_p);
778 >
779 >  /* Only interested in privmsg to channels */
780 >  if (parv[2][0] != '#' && parv[2][0] != '&')
781 >    return;
782 >
783 >  /* Get a target */
784 >  if ((channel = get_channel(parv[2])) == NULL)
785 >    return;
786 >
787 >  /* Find a suitable length to compare with */
788 >  nick_len = strcspn(parv[3], " :,");
789 >
790 >  if (nick_len < 3 && strlen(IRCItem->nick) >= 3)
791 >    nick_len = 3;
792 >
793 >  /* message is a command */
794 >  if (strncasecmp(parv[3], IRCItem->nick, nick_len) == 0  ||
795 >      strncasecmp(parv[3], "!all", 4) == 0)
796 >  {
797 >    /* XXX command_parse will alter parv[3]. */
798 >    command_parse(parv[3], channel, source_p);
799 >  }
800   }
801  
946
947
948
949
802   /* m_ctcp
803   * parv[0]  = source
804   * parv[1]  = PRIVMSG
# Line 957 | Line 809 | static void m_privmsg(char **parv, unsig
809   * the source (parv[0]) is a server.
810   *
811   */
812 <
813 < static void m_ctcp(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
812 > static void
813 > m_ctcp(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
814   {
815 <   USE_VAR(parc);
816 <   USE_VAR(msg);
817 <
966 <   if(strncasecmp(parv[3], "\001VERSION\001", 9) == 0)
967 <   {
968 <      irc_send("NOTICE %s :\001VERSION Hybrid Open Proxy Monitor %s\001",
969 <            source_p->irc_nick, VERSION);
970 <   }
815 >  if (strncasecmp(parv[3], "\001VERSION\001", 9) == 0)
816 >    irc_send("NOTICE %s :\001VERSION Hybrid Open Proxy Monitor %s\001",
817 >             source_p->irc_nick, VERSION);
818   }
819  
973
974
975
976
820   /* m_notice
821   *
822   * parv[0]  = source
# Line 986 | Line 829 | static void m_ctcp(char **parv, unsigned
829   * the source (parv[0]) is a server.
830   *
831   */
832 <
833 < static void m_notice(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
832 > static void
833 > m_notice(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
834   {
835 +  static regex_t *preg = NULL;
836 +  regmatch_t pmatch[5];
837 +  int errnum;
838 +  const char *user[4];
839 +
840 +  /* Not interested in notices from users */
841 +  if (source_p)
842 +    return;
843 +
844 +  if (parc < 4)
845 +    return;
846 +
847 +  /* Compile the regular expression if it has not been already */
848 +  if (preg == NULL)
849 +  {
850 +    preg = xcalloc(sizeof *preg);
851 +
852 +    if ((errnum = regcomp(preg, IRCItem->connregex, REG_ICASE | REG_EXTENDED)))
853 +    {
854 +      char errmsg[256];
855 +
856 +      regerror(errnum, preg, errmsg, sizeof(errmsg));
857 +      log_printf("IRC REGEX -> Error when compiling regular expression");
858 +      log_printf("IRC REGEX -> %s", errmsg);
859  
860 <
861 <   static regex_t *preg = NULL;
995 <   regmatch_t pmatch[5];
996 <
997 <   static char errmsg[256];
998 <   int errnum, i;
999 <
1000 <   char *user[4];
1001 <
1002 <   if(parc < 4)
1003 <      return;
1004 <
1005 <   /* Not interested in notices from users */
1006 <   if(source_p != NULL)
860 >      MyFree(preg);
861 >      preg = NULL;
862        return;
863 +    }
864 +  }
865  
866 <   /* Compile the regular expression if it has not been already */
867 <   if(preg == NULL)
868 <   {
869 <      preg = MyMalloc(sizeof *preg);
870 <
871 <      if((errnum = regcomp(preg, IRCItem->connregex, REG_ICASE | REG_EXTENDED)) != 0)
872 <      {
873 <
874 <         regerror(errnum, preg, errmsg, 256);
875 <         log_printf("IRC REGEX -> Error when compiling regular expression");
876 <         log_printf("IRC REGEX -> %s", errmsg);
877 <
1021 <         MyFree(preg);
1022 <         preg = NULL;
1023 <         return;
1024 <      }
1025 <   }
1026 <
1027 <   /* Match the expression against the possible connection notice */
1028 <   if(regexec(preg, parv[3], 5, pmatch, 0) != 0)
1029 <      return;
1030 <
1031 <   if(OPT_DEBUG > 0)
1032 <      log_printf("IRC REGEX -> Regular expression caught connection notice. Parsing.");
1033 <
1034 <   if(pmatch[4].rm_so == -1)
1035 <   {
1036 <      log_printf("IRC REGEX -> pmatch[4].rm_so is -1 while parsing??? Aborting.");
1037 <      return;
1038 <   }
866 >  /* Match the expression against the possible connection notice */
867 >  if (regexec(preg, parv[3], 5, pmatch, 0))
868 >    return;
869 >
870 >  if (OPT_DEBUG > 0)
871 >    log_printf("IRC REGEX -> Regular expression caught connection notice. Parsing.");
872 >
873 >  if (pmatch[4].rm_so == -1)
874 >  {
875 >    log_printf("IRC REGEX -> pmatch[4].rm_so is -1 while parsing??? Aborting.");
876 >    return;
877 >  }
878  
879 <   /*
880 <       Offsets for data in the connection notice:
879 >  /*
880 >   *   Offsets for data in the connection notice:
881 >   *
882 >   *   NICKNAME: pmatch[1].rm_so  TO  pmatch[1].rm_eo
883 >   *   USERNAME: pmatch[2].rm_so  TO  pmatch[2].rm_eo
884 >   *   HOSTNAME: pmatch[3].rm_so  TO  pmatch[3].rm_eo
885 >   *   IP      : pmatch[4].rm_so  TO  pmatch[4].rm_eo
886 >   */
887 >  for (unsigned int i = 0; i < 4; ++i)
888 >  {
889 >    user[i] = (parv[3] + pmatch[i + 1].rm_so);
890 >    *(parv[3] + pmatch[i + 1].rm_eo) = '\0';
891 >  }
892  
893 <       NICKNAME: pmatch[1].rm_so  TO  pmatch[1].rm_eo
894 <       USERNAME: pmatch[2].rm_so  TO  pmatch[2].rm_eo
895 <       HOSTNAME: pmatch[3].rm_so  TO  pmatch[3].rm_eo
1046 <       IP      : pmatch[4].rm_so  TO  pmatch[4].rm_eo
1047 <
1048 <    */
1049 <
1050 <   for(i = 0; i < 4; i++)
1051 <   {
1052 <      user[i] = (parv[3] + pmatch[i + 1].rm_so);
1053 <      *(parv[3] + pmatch[i + 1].rm_eo) = '\0';
1054 <   }
1055 <
1056 <   if(OPT_DEBUG > 0)
1057 <      log_printf("IRC REGEX -> Parsed %s!%s@%s [%s] from connection notice.",
1058 <          user[0], user[1], user[2], user[3]);
893 >  if (OPT_DEBUG > 0)
894 >    log_printf("IRC REGEX -> Parsed %s!%s@%s [%s] from connection notice.",
895 >               user[0], user[1], user[2], user[3]);
896  
897 <   /*FIXME (reminder) In the case of any rehash to the regex, preg MUST be freed first.
898 <       regfree(preg);
897 >  /*FIXME (reminder) In the case of any rehash to the regex, preg MUST be freed first.
898 >      regfree(preg);
899     */
900  
901 <   /* Pass this information off to scan.c */
902 <   scan_connect(user, msg);
903 <   /* Record the connect for stats purposes */
904 <   stats_connect();
901 >  /* Pass this information off to scan.c */
902 >  scan_connect(user, msg);
903 >
904 >  /* Record the connect for stats purposes */
905 >  stats_connect();
906   }
907  
908   /* m_userhost
# Line 1079 | Line 917 | static void m_notice(char **parv, unsign
917   * the source (parv[0]) is a server.
918   *
919   */
920 <
921 < static void m_userhost(char **parv, unsigned int parc, char *msg,
1084 <      struct UserInfo *source_p)
920 > static void
921 > m_userhost(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
922   {
923 <   USE_VAR(msg);
924 <   USE_VAR(source_p);
923 >  if (parc < 4)
924 >    return;
925  
926 <   if(parc < 4)
1090 <      return;
1091 <
1092 <   command_userhost(parv[3]);
926 >  command_userhost(parv[3]);
927   }
928  
929   /* m_cannot_join
# Line 1101 | Line 935 | static void m_userhost(char **parv, unsi
935   * parv[4]  = error text
936   *
937   */
938 <
939 < static void m_cannot_join(char **parv, unsigned int parc, char *msg,
1106 <      struct UserInfo *source_p)
938 > static void
939 > m_cannot_join(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
940   {
941 <   struct ChannelConf *channel;
941 >  const struct ChannelConf *channel = NULL;
942  
943 <   USE_VAR(msg);
944 <   USE_VAR(source_p);
1112 <
1113 <   if(parc < 5)
1114 <      return;
943 >  if (parc < 5)
944 >    return;
945  
946 <   /* Is it one of our channels? */
947 <   if((channel = get_channel(parv[3])) == NULL)
948 <      return;
946 >  /* Is it one of our channels? */
947 >  if ((channel = get_channel(parv[3])) == NULL)
948 >    return;
949  
950 <   if (EmptyString(channel->invite))
951 <      return;
950 >  if (EmptyString(channel->invite))
951 >    return;
952  
953 <   irc_send("%s", channel->invite);
953 >  irc_send("%s", channel->invite);
954   }
955  
1126
956   /* m_kill
957   *
958   * parv[0]  = source
# Line 1133 | Line 962 | static void m_cannot_join(char **parv, u
962   * parv[4]  = error text
963   *
964   */
965 <
966 < static void m_kill(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
965 > static void
966 > m_kill(char *parv[], unsigned int parc, char *msg, const struct UserInfo *source_p)
967   {
968 <   USE_VAR(parv);
969 <   USE_VAR(parc);
1141 <   USE_VAR(msg);
1142 <   USE_VAR(source_p);
1143 <
1144 <   /* Restart hopm to rehash */
1145 <   main_restart();
968 >  /* Restart hopm to rehash */
969 >  main_restart();
970   }

Comparing hopm/trunk/src/irc.c (property svn:eol-style):
Revision 5077 by michael, Mon Dec 22 18:34:34 2014 UTC vs.
Revision 5367 by michael, Mon Jan 12 20:13:22 2015 UTC

# Line 0 | Line 1
1 + native

Comparing hopm/trunk/src/irc.c (property svn:keywords):
Revision 5077 by michael, Mon Dec 22 18:34:34 2014 UTC vs.
Revision 5367 by michael, Mon Jan 12 20:13:22 2015 UTC

# Line 0 | Line 1
1 + Id

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)