/* Main processing code for Services. * * IRC Services is copyright (c) 1996-2007 Andrew Church. * E-mail: * Parts written by Andrew Kempe and others. * This program is free but copyrighted software; see the file COPYING for * details. */ #include "services.h" #include "modules.h" #include "messages.h" #include "ignore.h" static int cb_recvmsg = -1; /*************************************************************************/ /*************************************************************************/ /* split_buf: Split a buffer into arguments and store a pointer to the * argument vector in argv_ptr; return the argument count. * The argument vector will point to a static buffer; * subsequent calls will overwrite this buffer. * If colon_special is non-zero, then treat a parameter with a * leading ':' as the last parameter of the line, per the IRC * RFC. Destroys the buffer by side effect. */ static char **sbargv = NULL; int split_buf(char *buf, char ***argv_ptr, int colon_special) { static int argvsize = 8; int argc; char *s; if (!sbargv) sbargv = smalloc(sizeof(char *) * argvsize); argc = 0; while (*buf) { if (argc == argvsize) { argvsize += 8; sbargv = srealloc(sbargv, sizeof(char *) * argvsize); } if (*buf == ':' && colon_special) { sbargv[argc++] = buf+1; *buf = 0; } else { s = strpbrk(buf, " "); if (s) { *s++ = 0; while (*s == ' ') s++; } else { s = buf + strlen(buf); } sbargv[argc++] = buf; buf = s; } } *argv_ptr = sbargv; return argc; } /*************************************************************************/ /*************************************************************************/ int process_init(int ac, char **av) { cb_recvmsg = register_callback(NULL, "receive message"); if (cb_recvmsg < 0) { log("process_init: register_callback() failed\n"); return 0; } return 1; } /*************************************************************************/ void process_cleanup(void) { unregister_callback(NULL, cb_recvmsg); free(sbargv); sbargv = NULL; } /*************************************************************************/ /* process: Main processing routine. Takes the string in inbuf (global * variable) and does something appropriate with it. */ void process() { char source[64]; char cmd[64]; char buf[512]; /* Longest legal IRC command line */ char *s; int ac; /* Parameters for the command */ char **av; /* If debugging, log the buffer. */ if (debug) log("debug: Received: %s", inbuf); /* First make a copy of the buffer so we have the original in case we * crash - in that case, we want to know what we crashed on. */ strscpy(buf, inbuf, sizeof(buf)); /* Split the buffer into pieces. */ if (*buf == ':') { s = strpbrk(buf, " "); if (!s) return; *s = 0; while (isspace(*++s)) ; strscpy(source, buf+1, sizeof(source)); strmove(buf, s); } else { *source = 0; } if (!*buf) return; s = strpbrk(buf, " "); if (s) { *s = 0; while (isspace(*++s)) ; } else s = buf + strlen(buf); strscpy(cmd, buf, sizeof(cmd)); ac = split_buf(s, &av, 1); /* Do something with the message. */ if (call_callback_4(NULL, cb_recvmsg, source, cmd, ac, av) <= 0) { if (!source && stricmp(cmd, "NICK") != 0) { log("Source missing for `%s' message from server (%s)",cmd,inbuf); } else { Message *m = find_message(cmd); if (m) { if (m->func) m->func(source, ac, av); } else { log("unknown message from server (%s)", inbuf); } } } /* Finally, clear the first byte of `inbuf' to signal that we're * finished processing. */ *inbuf = 0; } /*************************************************************************/