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 5083 by michael, Mon Dec 22 19:42:14 2014 UTC vs.
Revision 5274 by michael, Thu Jan 1 20:00:33 2015 UTC

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

Comparing hopm/trunk/src/irc.c (property svn:eol-style):
Revision 5083 by michael, Mon Dec 22 19:42:14 2014 UTC vs.
Revision 5274 by michael, Thu Jan 1 20:00:33 2015 UTC

# Line 0 | Line 1
1 + native

Comparing hopm/trunk/src/irc.c (property svn:keywords):
Revision 5083 by michael, Mon Dec 22 19:42:14 2014 UTC vs.
Revision 5274 by michael, Thu Jan 1 20:00:33 2015 UTC

# Line 0 | Line 1
1 + Id

Diff Legend

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