process.c

Go to the documentation of this file.
00001 /* Main processing code for Services.
00002  *
00003  * (C) 2003-2007 Anope Team
00004  * Contact us at info@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  * $Id: process.c 1265 2007-08-26 15:33:06Z geniusdex $
00012  *
00013  */
00014 
00015 #include "services.h"
00016 #include "messages.h"
00017 #include "modules.h"
00018 
00019 /*************************************************************************/
00020 
00021 /* Use ignore code? */
00022 int allow_ignore = 1;
00023 
00024 /* People to ignore (hashed by first character of nick). */
00025 IgnoreData *ignore[256];
00026 
00027 /*************************************************************************/
00028 
00029 /* add_ignore: Add someone to the ignorance list for the next `delta'
00030  *             seconds.
00031  */
00032 
00033 void add_ignore(const char *nick, time_t delta)
00034 {
00035     IgnoreData *ign;
00036     char who[NICKMAX];
00037     time_t now = time(NULL);
00038     IgnoreData **whichlist = &ignore[tolower(nick[0])];
00039 
00040     strscpy(who, nick, NICKMAX);
00041     for (ign = *whichlist; ign; ign = ign->next) {
00042         if (stricmp(ign->who, who) == 0)
00043             break;
00044     }
00045     if (ign) {
00046         if (ign->time > now)
00047             ign->time += delta;
00048         else
00049             ign->time = now + delta;
00050     } else {
00051         ign = scalloc(sizeof(*ign), 1);
00052         strscpy(ign->who, who, sizeof(ign->who));
00053         ign->time = now + delta;
00054         ign->next = *whichlist;
00055         *whichlist = ign;
00056     }
00057 }
00058 
00059 /*************************************************************************/
00060 
00061 /* get_ignore: Retrieve an ignorance record for a nick.  If the nick isn't
00062  *             being ignored, return NULL and flush the record from the
00063  *             in-core list if it exists (i.e. ignore timed out).
00064  */
00065 
00066 IgnoreData *get_ignore(const char *nick)
00067 {
00068     IgnoreData *ign, *prev;
00069     time_t now = time(NULL);
00070     IgnoreData **whichlist = &ignore[tolower(nick[0])];
00071     User *u = finduser(nick);
00072     IgnoreData **whichlist2 = NULL;
00073     /* Bleah, this doesn't work. I need a way to get the first char of u->username.
00074        /if (u) whichlist2 = &ignore[tolower(u->username[0])]; */
00075     IgnoreData **whichlistast = &ignore[42];    /* * */
00076     IgnoreData **whichlistqst = &ignore[63];    /* ? */
00077     int finished = 0;
00078 
00079 
00080     /* User has disabled the IGNORE system */
00081     if (!allow_ignore) {
00082         return NULL;
00083     }
00084 
00085     /* if an oper gets on the ignore list we let them privmsg, this will allow
00086        them in places we call get_ignore to get by */
00087     if (u && is_oper(u)) {
00088         return NULL;
00089     }
00090 
00091     for (ign = *whichlist, prev = NULL; ign; prev = ign, ign = ign->next) {
00092         if (stricmp(ign->who, nick) == 0) {
00093             finished = 1;
00094             break;
00095         }
00096     }
00097     /* We can only do the next checks if we have an actual user -GD */
00098     if (u) {
00099         if (!finished && whichlist2) {
00100             for (ign = *whichlist2, prev = NULL; ign;
00101                  prev = ign, ign = ign->next) {
00102                 if (match_usermask(ign->who, u)) {
00103                     finished = 1;
00104                     break;
00105                 }
00106             }
00107         }
00108         if (!finished) {
00109             for (ign = *whichlistast, prev = NULL; ign;
00110                  prev = ign, ign = ign->next) {
00111                 if (match_usermask(ign->who, u)) {
00112                     finished = 1;
00113                     break;
00114                 }
00115             }
00116         }
00117         if (!finished) {
00118             for (ign = *whichlistqst, prev = NULL; ign;
00119                  prev = ign, ign = ign->next) {
00120                 if (match_usermask(ign->who, u)) {
00121                     finished = 1;
00122                     break;
00123                 }
00124             }
00125         }
00126     }
00127     if (ign && ign->time <= now) {
00128         if (prev)
00129             prev->next = ign->next;
00130         else
00131             *whichlist = ign->next;
00132         free(ign);
00133         ign = NULL;
00134     }
00135     return ign;
00136 }
00137 
00138 /*************************************************************************/
00139 
00140 /* split_buf:  Split a buffer into arguments and store the arguments in an
00141  *             argument vector pointed to by argv (which will be malloc'd
00142  *             as necessary); return the argument count.  If colon_special
00143  *             is non-zero, then treat a parameter with a leading ':' as
00144  *             the last parameter of the line, per the IRC RFC.  Destroys
00145  *             the buffer by side effect.
00146  */
00147 
00148 int split_buf(char *buf, char ***argv, int colon_special)
00149 {
00150     int argvsize = 8;
00151     int argc;
00152     char *s;
00153 
00154     *argv = scalloc(sizeof(char *) * argvsize, 1);
00155     argc = 0;
00156     while (*buf) {
00157         if (argc == argvsize) {
00158             argvsize += 8;
00159             *argv = srealloc(*argv, sizeof(char *) * argvsize);
00160         }
00161         if (*buf == ':') {
00162             (*argv)[argc++] = buf + 1;
00163             buf = "";
00164         } else {
00165             s = strpbrk(buf, " ");
00166             if (s) {
00167                 *s++ = 0;
00168                 while (*s == ' ')
00169                     s++;
00170             } else {
00171                 s = buf + strlen(buf);
00172             }
00173             (*argv)[argc++] = buf;
00174             buf = s;
00175         }
00176     }
00177     return argc;
00178 }
00179 
00180 /*************************************************************************/
00181 
00182 /* process:  Main processing routine.  Takes the string in inbuf (global
00183  *           variable) and does something appropriate with it. */
00184 
00185 void process()
00186 {
00187     int retVal = 0;
00188     Message *current = NULL;
00189     char source[64];
00190     char cmd[64];
00191     char buf[512];              /* Longest legal IRC command line */
00192     char *s;
00193     int ac;                     /* Parameters for the command */
00194     char **av;
00195     Message *m;
00196 
00197     /* zero out the buffers before we do much else */
00198     *buf = '\0';
00199     *source = '\0';
00200     *cmd = '\0';
00201 
00202     /* If debugging, log the buffer */
00203     if (debug) {
00204         alog("debug: Received: %s", inbuf);
00205     }
00206 
00207     /* First make a copy of the buffer so we have the original in case we
00208      * crash - in that case, we want to know what we crashed on. */
00209     strscpy(buf, inbuf, sizeof(buf));
00210 
00211     doCleanBuffer((char *) buf);
00212 
00213     /* Split the buffer into pieces. */
00214     if (*buf == ':') {
00215         s = strpbrk(buf, " ");
00216         if (!s)
00217             return;
00218         *s = 0;
00219         while (isspace(*++s));
00220         strscpy(source, buf + 1, sizeof(source));
00221         memmove(buf, s, strlen(s) + 1);
00222     } else {
00223         *source = 0;
00224     }
00225     if (!*buf)
00226         return;
00227     s = strpbrk(buf, " ");
00228     if (s) {
00229         *s = 0;
00230         while (isspace(*++s));
00231     } else
00232         s = buf + strlen(buf);
00233     strscpy(cmd, buf, sizeof(cmd));
00234     ac = split_buf(s, &av, 1);
00235     if (protocoldebug) {
00236         protocol_debug(source, cmd, ac, av);
00237     }
00238     if (mod_current_buffer) {
00239         free(mod_current_buffer);
00240     }
00241     /* fix to moduleGetLastBuffer() bug 296 */
00242     /* old logic was that since its meant for PRIVMSG that we would get
00243        the NICK as AV[0] and the rest would be in av[1], however on Bahamut
00244        based systems when you do /cs it assumes we will translate the command
00245        to the NICK and thus AV[0] is the message. The new logic is to check
00246        av[0] to see if its a service nick if so assign mod_current_buffer the
00247        value from AV[1] else just assign av[0] - TSL */
00248     /* First check if the ircd proto module overrides this -GD */
00249     /* fix to moduleGetLastBuffer() bug 476:
00250        fixed in part by adding {} to nickIsServices()
00251        however if you have a pseudo they could not use moduleGetLastBuffer()
00252        cause they are not part of nickIsServices, even those the ac count is 2
00253        that was ignored and only the first param was passed on which is fine for
00254        Bahmut ircd aliases but not for pseudo clients on. So additional logic is
00255        that if the ac is greater then 1 copy av[1] else copy av[0] 
00256        I also changed from if statments, cause attempting to access a array member
00257        that is not set can lead to odd things - TSL (3/12/06) */
00258     if (!anope_set_mod_current_buffer(ac, av)) {
00259         if (ac >= 1) {
00260             if (nickIsServices(av[0], 1)) {
00261                 mod_current_buffer =
00262                     (ac > 1 ? sstrdup(av[1]) : sstrdup(av[0]));
00263             } else {
00264                 mod_current_buffer =
00265                     (ac > 1 ? sstrdup(av[1]) : sstrdup(av[0]));
00266             }
00267         } else {
00268             mod_current_buffer = NULL;
00269         }
00270     }
00271     /* Do something with the message. */
00272     m = find_message(cmd);
00273     if (m) {
00274         if (m->func) {
00275             mod_current_module_name = m->mod_name;
00276             retVal = m->func(source, ac, av);
00277             mod_current_module_name = NULL;
00278             if (retVal == MOD_CONT) {
00279                 current = m->next;
00280                 while (current && current->func && retVal == MOD_CONT) {
00281                     mod_current_module_name = current->mod_name;
00282                     retVal = current->func(source, ac, av);
00283                     mod_current_module_name = NULL;
00284                     current = current->next;
00285                 }
00286             }
00287         }
00288     } else {
00289         if (debug)
00290             alog("debug: unknown message from server (%s)", inbuf);
00291     }
00292 
00293     /* Load/unload modules if needed */
00294     handleModuleOperationQueue();
00295 
00296     /* Free argument list we created */
00297     free(av);
00298 }
00299 
00300 /*************************************************************************/

Generated on Sun Dec 30 09:26:50 2007 for Anope by  doxygen 1.5.1-20070107