Anope IRC Services  Version 1.8
modules.c
Go to the documentation of this file.
1 
2 /* Modular support
3  *
4  * (C) 2003-2014 Anope Team
5  * Contact us at team@anope.org
6  *
7  * Please read COPYING and README for further details.
8  *
9  * Based on the original code of Epona by Lara.
10  * Based on the original code of Services by Andy Church.
11  *
12  *
13  */
14 #include "modules.h"
15 #include "language.h"
16 #include "version.h"
17 
18 #if defined(USE_MODULES) && !defined(_WIN32)
19 #include <dlfcn.h>
20 /* Define these for systems without them */
21 #ifndef RTLD_NOW
22 #define RTLD_NOW 0
23 #endif
24 #ifndef RTLD_LAZY
25 #define RTLD_LAZY RTLD_NOW
26 #endif
27 #ifndef RTLD_GLOBAL
28 #define RTLD_GLOBAL 0
29 #endif
30 #ifndef RTLD_LOCAL
31 #define RTLD_LOCAL 0
32 #endif
33 #endif
34 
35 #ifdef _WIN32
36 const char *ano_moderr(void);
37 #endif
38 
51 
54 char *mod_current_buffer = NULL;
58 
59 int displayCommand(Command * c);
60 int displayCommandFromHash(CommandHash * cmdTable[], char *name);
61 int displayMessageFromHash(char *name);
62 int displayMessage(Message * m);
63 char *ModuleGetErrStr(int status);
64 
65 char *ModuleGetErrStr(int status)
66 {
67  const char *module_err_str[] = {
68  "Module, Okay - No Error", /* MOD_ERR_OK */
69  "Module Error, Allocating memory", /* MOD_ERR_MEMORY */
70  "Module Error, Not enough parameters", /* MOD_ERR_PARAMS */
71  "Module Error, Already loaded", /* MOD_ERR_EXISTS */
72  "Module Error, File does not exist", /* MOD_ERR_NOEXIST */
73  "Module Error, No User", /* MOD_ERR_NOUSER */
74  "Module Error, Error during load time or module returned MOD_STOP", /* MOD_ERR_NOLOAD */
75  "Module Error, Unable to unload", /* MOD_ERR_NOUNLOAD */
76  "Module Error, Incorrect syntax", /* MOD_ERR_SYNTAX */
77  "Module Error, Unable to delete", /* MOD_ERR_NODELETE */
78  "Module Error, Unknown Error occuried", /* MOD_ERR_UNKOWN */
79  "Module Error, File I/O Error", /* MOD_ERR_FILE_IO */
80  "Module Error, No Service found for request", /* MOD_ERR_NOSERVICE */
81  "Module Error, No module name for request" /* MOD_ERR_NO_MOD_NAME */
82  };
83  return (char *) module_err_str[status];
84 }
85 
91 void modules_init(void)
92 {
93 #ifdef USE_MODULES
94  int idx;
95  int ret;
96  Module *m;
97 
98  if(nothird) {
99  return;
100  }
101 
102  for (idx = 0; idx < ModulesNumber; idx++) {
103  m = findModule(ModulesAutoload[idx]);
104  if (!m) {
105  m = createModule(ModulesAutoload[idx]);
106  mod_current_module = m;
108  mod_current_user = NULL;
109  alog("trying to load [%s]", mod_current_module->name);
110  ret = loadModule(mod_current_module, NULL);
111  alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
112  if (ret != MOD_ERR_OK)
113  destroyModule(m);
114  mod_current_module = NULL;
116  mod_current_user = NULL;
117  }
118  }
119 #endif
120 }
121 
127 void modules_core_init(int number, char **list)
128 {
129  int idx;
130  Module *m;
131  int status = 0;
132  for (idx = 0; idx < number; idx++) {
133  m = findModule(list[idx]);
134  if (!m) {
135  m = createModule(list[idx]);
136  mod_current_module = m;
138  mod_current_user = NULL;
139  status = loadModule(mod_current_module, NULL);
140  mod_current_module = m;
142  if (debug || status) {
143  alog("debug: trying to load core module [%s]",
144  mod_current_module->name);
145  alog("debug: status: [%d][%s]", status, ModuleGetErrStr(status));
146  if (status != MOD_ERR_OK)
147  destroyModule(mod_current_module);
148  }
149  mod_current_module = NULL;
151  mod_current_user = NULL;
152  }
153  }
154 }
159  int ret = 0;
160  Module *m;
161 
162  m = createModule(EncModule);
163  mod_current_module = m;
165  mod_current_user = NULL;
166  alog("Loading Encryption Module: [%s]", mod_current_module->name);
167  ret = loadModule(mod_current_module, NULL);
168  mod_current_module = m;
171  alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
172  mod_current_module = NULL;
174  if (ret != MOD_ERR_OK) {
175  destroyModule(m);
176  }
177  return ret;
178 }
179 
184 {
185  int ret = 0, noforksave = nofork;
186  Module *m;
187 
189  mod_current_module = m;
191  mod_current_user = NULL;
192  alog("Loading IRCD Protocol Module: [%s]", mod_current_module->name);
193  ret = loadModule(mod_current_module, NULL);
194  mod_current_module = m;
197  alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
198  mod_current_module = NULL;
200 
201  if (ret == MOD_ERR_OK) {
202  /* This is really NOT the correct place to do config checks, but
203  * as we only have the ircd struct filled here, we have to over
204  * here. -GD
205  */
206  if (UseTokens && !ircd->token) {
207  alog("Anope does not support TOKENS for this ircd setting; unsetting UseToken");
208  UseTokens = 0;
209  }
210 
211  if (UseTS6 && !ircd->ts6) {
212  alog("Chosen IRCd does not support TS6, unsetting UseTS6");
213  UseTS6 = 0;
214  }
215 
216  /* We can assume the ircd supports TS6 here */
217  if (UseTS6 && !Numeric) {
218  nofork = 1; /* We're going down, set nofork so this error is printed */
219  alog("UseTS6 requires the setting of Numeric to be enabled.");
220  nofork = noforksave;
221  ret = -1;
222  }
223  } else {
224  destroyModule(m);
225  }
226 
227  return ret;
228 }
229 
236 {
237 #ifdef USE_MODULES
238  int idx;
239  int ret;
240  Module *m;
241 
242  if(nothird) {
243  return;
244  }
245 
246  for (idx = 0; idx < ModulesDelayedNumber; idx++) {
248  if (!m) {
250  mod_current_module = m;
252  mod_current_user = NULL;
253  alog("trying to load [%s]", mod_current_module->name);
254  ret = loadModule(mod_current_module, NULL);
255  alog("status: [%d][%s]", ret, ModuleGetErrStr(ret));
256  mod_current_module = NULL;
258  mod_current_user = NULL;
259  if (ret != MOD_ERR_OK)
260  destroyModule(m);
261  }
262  }
263 #endif
264 }
265 
276 void modules_unload_all(boolean fini, boolean unload_proto)
277 {
278 #ifdef USE_MODULES
279  int idx;
280  ModuleHash *mh, *next;
281 
282  for (idx = 0; idx < MAX_CMD_HASH; idx++) {
283  mh = MODULE_HASH[idx];
284  while (mh) {
285  next = mh->next;
286  if (unload_proto || (mh->m->type != PROTOCOL)) {
287  mod_current_module = mh->m;
289  if(fini) {
290  union fini_union
291  {
292  void *ptr;
293  void (*func)(void);
294  } u;
295  u.ptr = ano_modsym(mh->m->handle, "AnopeFini");
296  if (u.ptr)
297  u.func(); /* exec AnopeFini */
298 
299  if (prepForUnload(mh->m) != MOD_ERR_OK) {
300  mh = next;
301  continue;
302  }
303 
304  if ((ano_modclose(mh->m->handle)) != 0)
305  alog("%s", ano_moderr());
306  else
307  delModule(mh->m);
308  } else
309  delModule(mh->m);
310 
311  mod_current_module = NULL;
313  }
314  mh = next;
315  }
316  }
317 #endif
318 }
319 
325 Module *createModule(char *filename)
326 {
327  Module *m;
328  int i = 0;
329  if (!filename) {
330  return NULL;
331  }
332  if ((m = malloc(sizeof(Module))) == NULL) {
333  fatal("Out of memory!");
334  }
335 
336  m->name = sstrdup(filename); /* Our Name */
337  m->handle = NULL; /* Handle */
338  m->version = NULL;
339  m->author = NULL;
340  m->nickHelp = NULL;
341  m->chanHelp = NULL;
342  m->memoHelp = NULL;
343  m->botHelp = NULL;
344  m->operHelp = NULL;
345  m->hostHelp = NULL;
346  m->helpHelp = NULL;
347 
348  m->type = THIRD;
349  for (i = 0; i < NUM_LANGS; i++) {
350  m->lang[i].argv = NULL;
351  m->lang[i].argc = 0;
352  }
353  return m; /* return a nice new module */
354 }
355 
363 {
364  int i = 0;
365  if (!m) {
366  return MOD_ERR_PARAMS;
367  }
368 
369  mod_current_module = m;
371  for (i = 0; i < NUM_LANGS; i++) {
373  }
374 
375  if (m->name) {
376  free(m->name);
377  }
378  if (m->filename) {
379  remove(m->filename);
380  free(m->filename);
381  }
382  m->handle = NULL;
383  if (m->author) {
384  free(m->author);
385  }
386  if (m->version) {
387  free(m->version);
388  }
389 
390  /* No need to free our cmd/msg list, as they will always be empty by the module is destroyed */
391  free(m);
392 
393  mod_current_module = NULL;
395 
396  return MOD_ERR_OK;
397 }
398 
405 {
406  int index = 0;
407  ModuleHash *current = NULL;
408  ModuleHash *newHash = NULL;
409  ModuleHash *lastHash = NULL;
410 
411  index = CMD_HASH(m->name);
412 
413  for (current = MODULE_HASH[index]; current; current = current->next) {
414  if (stricmp(m->name, current->name) == 0)
415  return MOD_ERR_EXISTS;
416  lastHash = current;
417  }
418 
419  if ((newHash = malloc(sizeof(ModuleHash))) == NULL) {
420  fatal("Out of memory");
421  }
422  m->time = time(NULL);
423  newHash->next = NULL;
424  newHash->name = sstrdup(m->name);
425  newHash->m = m;
426 
427  if (lastHash == NULL)
428  MODULE_HASH[index] = newHash;
429  else
430  lastHash->next = newHash;
431  return MOD_ERR_OK;
432 }
433 
440 {
441  int index = 0;
442  ModuleHash *current = NULL;
443  ModuleHash *lastHash = NULL;
444 
445  if (!m) {
446  return MOD_ERR_PARAMS;
447  }
448 
449  index = CMD_HASH(m->name);
450 
451  for (current = MODULE_HASH[index]; current; current = current->next) {
452  if (stricmp(m->name, current->name) == 0) {
453  if (!lastHash) {
454  MODULE_HASH[index] = current->next;
455  } else {
456  lastHash->next = current->next;
457  }
458  destroyModule(current->m);
459  free(current->name);
460  free(current);
461  return MOD_ERR_OK;
462  }
463  lastHash = current;
464  }
465  return MOD_ERR_NOEXIST;
466 }
467 
473 Module *findModule(char *name)
474 {
475  int idx;
476  ModuleHash *current = NULL;
477  if (!name) {
478  return NULL;
479  }
480  idx = CMD_HASH(name);
481 
482  for (current = MODULE_HASH[idx]; current; current = current->next) {
483  if (stricmp(name, current->name) == 0) {
484  return current->m;
485  }
486  }
487  return NULL;
488 
489 }
490 
496 {
497  int idx = 0;
498  ModuleHash *current = NULL;
499 
500  for (idx = 0; idx != MAX_CMD_HASH; idx++) {
501  for (current = MODULE_HASH[idx]; current; current = current->next) {
502  if (current->m->type == PROTOCOL) {
503  return 1;
504  }
505  }
506  }
507  return 0;
508 }
509 
515 {
516  int idx = 0;
517  ModuleHash *current = NULL;
518 
519  for (idx = 0; idx != MAX_CMD_HASH; idx++) {
520  for (current = MODULE_HASH[idx]; current; current = current->next) {
521  if (current->m->type == ENCRYPTION) {
522  return 1;
523  }
524  }
525  }
526  return 0;
527 }
528 
538 int moduleCopyFile(char *name, char *output)
539 {
540 #ifdef USE_MODULES
541  int ch;
542  FILE *source, *target;
543  int srcfp;
544  char input[4096] = "";
545  int len;
546 
547  strncpy(input, MODULE_PATH, 4095); /* Get full path with module extension */
548  len = strlen(input);
549  strncat(input, name, 4095 - len);
550  len = strlen(output);
551  strncat(input, MODULE_EXT, 4095 - len);
552 
553 #ifndef _WIN32
554  if ((srcfp = mkstemp(output)) == -1)
555  return MOD_ERR_FILE_IO;
556 #else
557  if (!mktemp(output))
558  return MOD_ERR_FILE_IO;
559 #endif
560  if (debug)
561  alog("Runtime module location: %s", output);
562 
563  /* Linux/UNIX should ignore the b param, why do we still have seperate
564  * calls for it here? -GD
565  */
566 #ifndef _WIN32
567  if ((source = fopen(input, "r")) == NULL) {
568  close(srcfp);
569 #else
570  if ((source = fopen(input, "rb")) == NULL) {
571 #endif
572  return MOD_ERR_NOEXIST;
573  }
574 #ifndef _WIN32
575  if ((target = fdopen(srcfp, "w")) == NULL) {
576 #else
577  if ((target = fopen(output, "wb")) == NULL) {
578 #endif
579  fclose(source);
580  return MOD_ERR_FILE_IO;
581  }
582  while ((ch = fgetc(source)) != EOF) {
583  fputc(ch, target);
584  }
585  fclose(source);
586  if (fclose(target) != 0) {
587  return MOD_ERR_FILE_IO;
588  }
589 #endif
590  return MOD_ERR_OK;
591 }
592 
599 int loadModule(Module * m, User * u)
600 {
601 #ifdef USE_MODULES
602  char buf[4096];
603  int len;
604  const char *err;
605  int ret = 0;
606  char *argv[1];
607  int argc = 0;
608 
609  union init_func_union
610  {
611  void *ptr;
612  int (*func)(int, char **);
613  } init_union;
614 
615  union version_func_union
616  {
617  void *ptr;
618  int (*func)();
619  } version_union;
620 
621  Module *m2;
622  if (!m || !m->name) {
623  return MOD_ERR_PARAMS;
624  }
625  if (m->handle) {
626  return MOD_ERR_EXISTS;
627  }
628  if ((m2 = findModule(m->name)) != NULL) {
629  return MOD_ERR_EXISTS;
630  }
631 
632  /* Generate the filename for the temporary copy of the module */
633  strncpy(buf, MODULE_PATH, 4095); /* Get full path with module extension */
634  len = strlen(buf);
635 #ifndef _WIN32
636  strncat(buf, "runtime/", 4095 - len);
637 #else
638  strncat(buf, "runtime\\", 4095 - len);
639 #endif
640  len = strlen(buf);
641  strncat(buf, m->name, 4095 - len);
642  len = strlen(buf);
643  strncat(buf, MODULE_EXT, 4095 - len);
644  len = strlen(buf);
645  strncat(buf, ".", 4095 - len);
646  len = strlen(buf);
647  strncat(buf, "XXXXXX", 4095 - len);
648  buf[4095] = '\0';
649  /* Don't skip return value checking! -GD */
650  if ((ret = moduleCopyFile(m->name, buf)) != MOD_ERR_OK) {
651  m->filename = sstrdup(buf);
652  return ret;
653  }
654 
655  m->filename = sstrdup(buf);
656  ano_modclearerr();
657  m->handle = ano_modopen(m->filename);
658  if ( m->handle == NULL && (err = ano_moderr()) != NULL) {
659  alog("%s", err);
660  return MOD_ERR_NOLOAD;
661  }
662  ano_modclearerr();
663 
664  init_union.ptr = ano_modsym(m->handle, "AnopeInit");
665 
666  if ( init_union.ptr == NULL && (err = ano_moderr()) != NULL) {
667  ano_modclose(m->handle); /* If no AnopeInit - it isnt an Anope Module, close it */
668  return MOD_ERR_NOLOAD;
669  }
670  if (init_union.ptr) {
671  version_union.ptr = ano_modsym(m->handle,"getAnopeBuildVersion");
672  if (version_union.ptr) {
673  if (version_union.func() >= VERSION_BUILD ) {
674  if(debug)
675  alog("Module %s compiled against current or newer anope revision %d, this is %d",m->name,version_union.func(),VERSION_BUILD);
676  } else {
677  alog("Module %s is compiled against an old version of anope (%d) current is %d", m->name, version_union.func(), VERSION_BUILD);
678  alog("Rebuild module %s against the current version to resolve this error", m->name);
679  ano_modclose(m->handle);
680  ano_modclearerr();
681  return MOD_ERR_NOLOAD;
682  }
683  } else {
684  ano_modclose(m->handle);
685  ano_modclearerr();
686  alog("Module %s is compiled against an older version of anope (unknown)", m->name);
687  alog("Rebuild module %s against the current version to resolve this error", m->name);
688  return MOD_ERR_NOLOAD;
689  }
690 
691  mod_current_module = m;
693  /* argv[0] is the user if there was one, or NULL if not */
694  if (u) {
695  argv[0] = sstrdup(u->nick);
696  } else {
697  argv[0] = NULL;
698  }
699  argc++;
700 
701  ret = init_union.func(argc, argv); /* exec AnopeInit */
702  if (u) {
703  free(argv[0]);
704  }
705  if (m->type == PROTOCOL && protocolModuleLoaded()) {
706  alog("You cannot load two protocol modules");
707  ret = MOD_STOP;
708  } else if (m->type == ENCRYPTION && encryptionModuleLoaded()) {
709  alog("You cannot load two encryption modules");
710  ret = MOD_STOP;
711  }
712  if (ret == MOD_STOP) {
713  alog("%s requested unload...", m->name);
714  unloadModule(m, NULL);
715  mod_current_module = NULL;
717  return MOD_ERR_NOLOAD;
718  }
719 
720  mod_current_module = NULL;
722  }
723 
724  if (u) {
725  anope_cmd_global(s_OperServ, "%s loaded module %s", u->nick,
726  m->name);
727  notice_lang(s_OperServ, u, OPER_MODULE_LOADED, m->name);
728  }
729  addModule(m);
730 
731  /* Loading is complete.. send out an event in case anyone s interested.. ~ Viper */
732  send_event(EVENT_MODLOAD, 1, m->name);
733 
734  return MOD_ERR_OK;
735 
736 #else
737  return MOD_ERR_NOLOAD;
738 #endif
739 }
740 
747 int unloadModule(Module * m, User * u)
748 {
749 #ifdef USE_MODULES
750  union fini_union
751  {
752  void *ptr;
753  void (*func)(void);
754  } un;
755 
756  if (!m || !m->handle) {
757  if (u) {
758  notice_lang(s_OperServ, u, OPER_MODULE_REMOVE_FAIL, m->name);
759  }
760  return MOD_ERR_PARAMS;
761  }
762 
763  if (m->type == PROTOCOL) {
764  if (u) {
765  notice_lang(s_OperServ, u, OPER_MODULE_NO_UNLOAD);
766  }
767  return MOD_ERR_NOUNLOAD;
768  } else if(m->type == ENCRYPTION) {
769  if (u) {
770  notice_lang(s_OperServ, u, OPER_MODULE_NO_UNLOAD);
771  }
772  return MOD_ERR_NOUNLOAD;
773  }
774 
775  un.ptr = ano_modsym(m->handle, "AnopeFini");
776  if (un.ptr) {
777  mod_current_module = m;
779  un.func(); /* exec AnopeFini */
780  }
781 
782  if (prepForUnload(m) != MOD_ERR_OK) {
783  return MOD_ERR_UNKNOWN;
784  }
785 
786  /* Unloading is complete: AnopeFini has been called and all commands, hooks and callbacks
787  * have been removed.. send out an event in case anyone s interested.. ~ Viper */
789 
790  if ((ano_modclose(m->handle)) != 0) {
791  alog("%s", ano_moderr());
792  if (u) {
793  notice_lang(s_OperServ, u, OPER_MODULE_REMOVE_FAIL, m->name);
794  }
795  mod_current_module = NULL;
797  return MOD_ERR_NOUNLOAD;
798  } else {
799  if (u) {
800  anope_cmd_global(s_OperServ, "%s unloaded module %s", u->nick,
801  m->name);
802  notice_lang(s_OperServ, u, OPER_MODULE_UNLOADED, m->name);
803  }
804  delModule(m);
805  mod_current_module = NULL;
807  return MOD_ERR_OK;
808  }
809 #else
810  return MOD_ERR_NOUNLOAD;
811 #endif
812 }
813 
819 {
820  mod_current_module->type = type;
821 }
822 
831 {
832  int idx;
833  CommandHash *current = NULL, *current_next = NULL;
834  MessageHash *mcurrent = NULL, *mcurrent_next = NULL;
835  EvtMessageHash *ecurrent = NULL, *ecurrent_next = NULL;
836  EvtHookHash *ehcurrent = NULL, *ehcurrent_next = NULL;
837 
838  Command *c, *c_next;
839  Message *msg, *msg_next;
840  EvtMessage *eMsg, *eMsg_next;
841  EvtHook *eHook, *eHook_next;
842 
843  if (!m) {
844  return MOD_ERR_PARAMS;
845  }
846 
847  /* Kill any active callbacks this module has */
849 
850  /* Remove any stored data this module has */
852 
856  for (idx = 0; idx < MAX_CMD_HASH; idx++) {
857  for (current = HS_cmdTable[idx]; current; current = current_next) {
858  current_next = current->next;
859  for (c = current->c; c; c = c_next) {
860  c_next = c->next;
861  if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
862  delCommand(HOSTSERV, c, m->name);
863  destroyCommand(c);
864  }
865  }
866  }
867 
868  for (current = BS_cmdTable[idx]; current; current = current_next) {
869  current_next = current->next;
870  for (c = current->c; c; c = c_next) {
871  c_next = c->next;
872  if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
873  delCommand(BOTSERV, c, m->name);
874  destroyCommand(c);
875  }
876  }
877  }
878 
879  for (current = MS_cmdTable[idx]; current; current = current_next) {
880  current_next = current->next;
881  for (c = current->c; c; c = c_next) {
882  c_next = c->next;
883  if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
884  delCommand(MEMOSERV, c, m->name);
885  destroyCommand(c);
886  }
887  }
888  }
889 
890  for (current = NS_cmdTable[idx]; current; current = current_next) {
891  current_next = current->next;
892  for (c = current->c; c; c = c_next) {
893  c_next = c->next;
894  if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
895  delCommand(NICKSERV, c, m->name);
896  destroyCommand(c);
897  }
898  }
899  }
900 
901  for (current = CS_cmdTable[idx]; current; current = current_next) {
902  current_next = current->next;
903  for (c = current->c; c; c = c_next) {
904  c_next = c->next;
905  if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
906  delCommand(CHANSERV, c, m->name);
907  destroyCommand(c);
908  }
909  }
910  }
911 
912  for (current = HE_cmdTable[idx]; current; current = current_next) {
913  current_next = current->next;
914  for (c = current->c; c; c = c_next) {
915  c_next = c->next;
916  if ((c->mod_name) && (strcmp(c->mod_name, m->name) == 0)) {
917  delCommand(HELPSERV, c, m->name);
918  destroyCommand(c);
919  }
920  }
921  }
922 
923  for (current = OS_cmdTable[idx]; current; current = current_next) {
924  current_next = current->next;
925  for (c = current->c; c; c = c_next) {
926  c_next = c->next;
927  if ((c->mod_name) && (stricmp(c->mod_name, m->name) == 0)) {
928  delCommand(OPERSERV, c, m->name);
929  destroyCommand(c);
930  }
931  }
932  }
933 
934  for (mcurrent = IRCD[idx]; mcurrent; mcurrent = mcurrent_next) {
935  mcurrent_next = mcurrent->next;
936  for (msg = mcurrent->m; msg; msg = msg_next) {
937  msg_next = msg->next;
938  if (msg->mod_name && (stricmp(msg->mod_name, m->name) == 0)) {
939  delMessage(IRCD, msg, m->name);
940  destroyMessage(msg);
941  }
942  }
943  }
944 
945  for (ecurrent = EVENT[idx]; ecurrent; ecurrent = ecurrent_next) {
946  ecurrent_next = ecurrent->next;
947  for (eMsg = ecurrent->evm; eMsg; eMsg = eMsg_next) {
948  eMsg_next = eMsg->next;
949  if ((eMsg->mod_name)
950  && (stricmp(eMsg->mod_name, m->name) == 0)) {
951  delEventHandler(EVENT, eMsg, m->name);
952  destroyEventHandler(eMsg);
953  }
954  }
955  }
956  for (ehcurrent = EVENTHOOKS[idx]; ehcurrent; ehcurrent = ehcurrent_next) {
957  ehcurrent_next = ehcurrent->next;
958  for (eHook = ehcurrent->evh; eHook; eHook = eHook_next) {
959  eHook_next = eHook->next;
960  if ((eHook->mod_name)
961  && (stricmp(eHook->mod_name, m->name) == 0)) {
962  delEventHook(EVENTHOOKS, eHook, m->name);
963  destroyEventHook(eHook);
964  }
965  }
966  }
967 
968  }
969  return MOD_ERR_OK;
970 }
971 
972 /*******************************************************************************
973  * Command Functions
974  *******************************************************************************/
987 Command *createCommand(const char *name, int (*func) (User * u),
988  int (*has_priv) (User * u), int help_all,
989  int help_reg, int help_oper, int help_admin,
990  int help_root)
991 {
992  Command *c;
993  if (!name || !*name) {
994  return NULL;
995  }
996 
997  if ((c = malloc(sizeof(Command))) == NULL) {
998  fatal("Out of memory!");
999  }
1000  c->name = sstrdup(name);
1001  c->routine = func;
1002  c->has_priv = has_priv;
1003  c->helpmsg_all = help_all;
1004  c->helpmsg_reg = help_reg;
1005  c->helpmsg_oper = help_oper;
1006  c->helpmsg_admin = help_admin;
1007  c->helpmsg_root = help_root;
1008  c->help_param1 = NULL;
1009  c->help_param2 = NULL;
1010  c->help_param3 = NULL;
1011  c->help_param4 = NULL;
1012  c->next = NULL;
1013  c->mod_name = NULL;
1014  c->service = NULL;
1015  c->all_help = NULL;
1016  c->regular_help = NULL;
1017  c->oper_help = NULL;
1018  c->admin_help = NULL;
1019  c->root_help = NULL;
1020  return c;
1021 }
1022 
1029 {
1030  if (!c) {
1031  return MOD_ERR_PARAMS;
1032  }
1033  if (c->core == 1) {
1034  return MOD_ERR_UNKNOWN;
1035  }
1036  if (c->name) {
1037  free(c->name);
1038  }
1039  c->routine = NULL;
1040  c->has_priv = NULL;
1041  c->helpmsg_all = -1;
1042  c->helpmsg_reg = -1;
1043  c->helpmsg_oper = -1;
1044  c->helpmsg_admin = -1;
1045  c->helpmsg_root = -1;
1046  if (c->mod_name) {
1047  free(c->mod_name);
1048  }
1049  if (c->service) {
1050  free(c->service);
1051  }
1052  c->next = NULL;
1053  free(c);
1054  return MOD_ERR_OK;
1055 }
1056 
1063 int addCoreCommand(CommandHash * cmdTable[], Command * c)
1064 {
1065  if (!cmdTable || !c) {
1066  return MOD_ERR_PARAMS;
1067  }
1068  c->core = 1;
1069  c->next = NULL;
1070  return addCommand(cmdTable, c, 0);
1071 }
1072 
1082 int moduleAddCommand(CommandHash * cmdTable[], Command * c, int pos)
1083 {
1084  int status;
1085 
1086  if (!cmdTable || !c) {
1087  return MOD_ERR_PARAMS;
1088  }
1089 
1090  if (!mod_current_module) {
1091  return MOD_ERR_UNKNOWN;
1092  } /* shouldnt happen */
1093  c->core = 0;
1094  if (!c->mod_name) {
1095  c->mod_name = sstrdup(mod_current_module->name);
1096  }
1097 
1098 
1099  if (cmdTable == HOSTSERV) {
1100  if (s_HostServ) {
1101  c->service = sstrdup(s_HostServ);
1102  } else {
1103  return MOD_ERR_NOSERVICE;
1104  }
1105  } else if (cmdTable == BOTSERV) {
1106  if (s_BotServ) {
1107  c->service = sstrdup(s_BotServ);
1108  } else {
1109  return MOD_ERR_NOSERVICE;
1110  }
1111  } else if (cmdTable == MEMOSERV) {
1112  if (s_MemoServ) {
1113  c->service = sstrdup(s_MemoServ);
1114  } else {
1115  return MOD_ERR_NOSERVICE;
1116  }
1117  } else if (cmdTable == CHANSERV) {
1118  if (s_ChanServ) {
1119  c->service = sstrdup(s_ChanServ);
1120  } else {
1121  return MOD_ERR_NOSERVICE;
1122  }
1123  } else if (cmdTable == NICKSERV) {
1124  if (s_NickServ) {
1125  c->service = sstrdup(s_NickServ);
1126  } else {
1127  return MOD_ERR_NOSERVICE;
1128  }
1129  } else if (cmdTable == HELPSERV) {
1130  if (s_HelpServ) {
1131  c->service = sstrdup(s_HelpServ);
1132  } else {
1133  return MOD_ERR_NOSERVICE;
1134  }
1135  } else if (cmdTable == OPERSERV) {
1136  if (s_OperServ) {
1137  c->service = sstrdup(s_OperServ);
1138  } else {
1139  return MOD_ERR_NOSERVICE;
1140  }
1141  } else
1142  c->service = sstrdup("Unknown");
1143 
1144  if (debug >= 2)
1145  displayCommandFromHash(cmdTable, c->name);
1146  status = addCommand(cmdTable, c, pos);
1147  if (debug >= 2)
1148  displayCommandFromHash(cmdTable, c->name);
1149  if (status != MOD_ERR_OK) {
1150  alog("ERROR! [%d]", status);
1151  }
1152  return status;
1153 }
1154 
1161 int moduleDelCommand(CommandHash * cmdTable[], char *name)
1162 {
1163  Command *c = NULL;
1164  Command *cmd = NULL, *cmd_next = NULL;
1165  int status = 0;
1166 
1167  if (!mod_current_module) {
1168  return MOD_ERR_UNKNOWN;
1169  }
1170 
1171  c = findCommand(cmdTable, name);
1172  if (!c) {
1173  return MOD_ERR_NOEXIST;
1174  }
1175 
1176 
1177  for (cmd = c; cmd; cmd = cmd_next) {
1178  cmd_next = cmd->next;
1179  if (cmd->mod_name
1180  && stricmp(cmd->mod_name, mod_current_module->name) == 0) {
1181  if (debug >= 2) {
1182  displayCommandFromHash(cmdTable, name);
1183  }
1184  status = delCommand(cmdTable, cmd, mod_current_module->name);
1185  if (debug >= 2) {
1186  displayCommandFromHash(cmdTable, name);
1187  }
1188  destroyCommand(cmd);
1189  }
1190  }
1191  return status;
1192 }
1193 
1201 int displayCommandFromHash(CommandHash * cmdTable[], char *name)
1202 {
1203  CommandHash *current = NULL;
1204  int index = 0;
1205  index = CMD_HASH(name);
1206  if (debug > 1) {
1207  alog("debug: trying to display command %s", name);
1208  }
1209  for (current = cmdTable[index]; current; current = current->next) {
1210  if (stricmp(name, current->name) == 0) {
1211  displayCommand(current->c);
1212  }
1213  }
1214  if (debug > 1) {
1215  alog("debug: done displaying command %s", name);
1216  }
1217  return 0;
1218 }
1219 
1228 {
1229  Command *cmd = NULL;
1230  int i = 0;
1231  alog("Displaying command list for %s", c->name);
1232  for (cmd = c; cmd; cmd = cmd->next) {
1233  alog("%d: 0x%p", ++i, (void *) cmd);
1234  }
1235  alog("end");
1236  return 0;
1237 }
1238 
1245 int displayMessageFromHash(char *name)
1246 {
1247  MessageHash *current = NULL;
1248  int index = 0;
1249  index = CMD_HASH(name);
1250  if (debug > 1) {
1251  alog("debug: trying to display message %s", name);
1252  }
1253  for (current = IRCD[index]; current; current = current->next) {
1254  if (stricmp(name, current->name) == 0) {
1255  displayMessage(current->m);
1256  }
1257  }
1258  if (debug > 1) {
1259  alog("debug: done displaying message %s", name);
1260  }
1261  return 0;
1262 }
1263 
1271 {
1272  Message *msg = NULL;
1273  int i = 0;
1274  alog("Displaying message list for %s", m->name);
1275  for (msg = m; msg; msg = msg->next) {
1276  alog("%d: 0x%p", ++i, (void *) msg);
1277  }
1278  alog("end");
1279  return 0;
1280 }
1281 
1282 
1293 int addCommand(CommandHash * cmdTable[], Command * c, int pos)
1294 {
1295  /* We can assume both param's have been checked by this point.. */
1296  int index = 0;
1297  CommandHash *current = NULL;
1298  CommandHash *newHash = NULL;
1299  CommandHash *lastHash = NULL;
1300  Command *tail = NULL;
1301 
1302  if (!cmdTable || !c || (pos < 0 || pos > 2)) {
1303  return MOD_ERR_PARAMS;
1304  }
1305 
1306  if (mod_current_module_name && !c->mod_name)
1307  return MOD_ERR_NO_MOD_NAME;
1308 
1309  index = CMD_HASH(c->name);
1310 
1311  for (current = cmdTable[index]; current; current = current->next) {
1312  if ((c->service) && (current->c) && (current->c->service)
1313  && (!strcmp(c->service, current->c->service) == 0)) {
1314  continue;
1315  }
1316  if ((stricmp(c->name, current->name) == 0)) { /* the cmd exist's we are a addHead */
1317  if (pos == 1) {
1318  c->next = current->c;
1319  current->c = c;
1320  if (debug)
1321  alog("debug: existing cmd: (0x%p), new cmd (0x%p)",
1322  (void *) c->next, (void *) c);
1324  return MOD_ERR_OK;
1325  } else if (pos == 2) {
1326 
1327  tail = current->c;
1328  while (tail->next)
1329  tail = tail->next;
1330  if (debug)
1331  alog("debug: existing cmd: (0x%p), new cmd (0x%p)",
1332  (void *) tail, (void *) c);
1333  tail->next = c;
1334  c->next = NULL;
1335 
1337  return MOD_ERR_OK;
1338  } else
1339  return MOD_ERR_EXISTS;
1340  }
1341  lastHash = current;
1342  }
1343 
1344  if ((newHash = malloc(sizeof(CommandHash))) == NULL) {
1345  fatal("Out of memory");
1346  }
1347  newHash->next = NULL;
1348  newHash->name = sstrdup(c->name);
1349  newHash->c = c;
1350 
1351  if (lastHash == NULL)
1352  cmdTable[index] = newHash;
1353  else
1354  lastHash->next = newHash;
1355 
1357  return MOD_ERR_OK;
1358 }
1359 
1367 int delCommand(CommandHash * cmdTable[], Command * c, char *mod_name)
1368 {
1369  int index = 0;
1370  CommandHash *current = NULL;
1371  CommandHash *lastHash = NULL;
1372  Command *tail = NULL, *last = NULL;
1373 
1374  if (!c || !cmdTable) {
1375  return MOD_ERR_PARAMS;
1376  }
1377 
1378  index = CMD_HASH(c->name);
1379  for (current = cmdTable[index]; current; current = current->next) {
1380  if (stricmp(c->name, current->name) == 0) {
1381  if (!lastHash) {
1382  tail = current->c;
1383  if (tail->next) {
1384  while (tail) {
1385  if (mod_name && tail->mod_name
1386  && (stricmp(mod_name, tail->mod_name) == 0)) {
1387  if (last) {
1388  last->next = tail->next;
1389  } else {
1390  current->c = tail->next;
1391  }
1393  return MOD_ERR_OK;
1394  }
1395  last = tail;
1396  tail = tail->next;
1397  }
1398  } else {
1399  cmdTable[index] = current->next;
1400  free(current->name);
1401  free(current);
1403  return MOD_ERR_OK;
1404  }
1405  } else {
1406  tail = current->c;
1407  if (tail->next) {
1408  while (tail) {
1409  if (mod_name && tail->mod_name
1410  && (stricmp(mod_name, tail->mod_name) == 0)) {
1411  if (last) {
1412  last->next = tail->next;
1413  } else {
1414  current->c = tail->next;
1415  }
1417  return MOD_ERR_OK;
1418  }
1419  last = tail;
1420  tail = tail->next;
1421  }
1422  } else {
1423  lastHash->next = current->next;
1424  free(current->name);
1425  free(current);
1427  return MOD_ERR_OK;
1428  }
1429  }
1430  }
1431  lastHash = current;
1432  }
1433  return MOD_ERR_NOEXIST;
1434 }
1435 
1442 Command *findCommand(CommandHash * cmdTable[], const char *name)
1443 {
1444  int idx;
1445  CommandHash *current = NULL;
1446  if (!cmdTable || !name) {
1447  return NULL;
1448  }
1449 
1450  idx = CMD_HASH(name);
1451 
1452  for (current = cmdTable[idx]; current; current = current->next) {
1453  if (stricmp(name, current->name) == 0) {
1454  return current->c;
1455  }
1456  }
1457  return NULL;
1458 }
1459 
1460 /*******************************************************************************
1461  * Message Functions
1462  *******************************************************************************/
1463 
1470 Message *createMessage(const char *name,
1471  int (*func) (char *source, int ac, char **av))
1472 {
1473  Message *m = NULL;
1474  if (!name || !func) {
1475  return NULL;
1476  }
1477  if ((m = malloc(sizeof(Message))) == NULL) {
1478  fatal("Out of memory!");
1479  }
1480  m->name = sstrdup(name);
1481  m->func = func;
1482  m->mod_name = NULL;
1483  m->next = NULL;
1484  return m;
1485 }
1486 
1494 Message *findMessage(MessageHash * msgTable[], const char *name)
1495 {
1496  int idx;
1497  MessageHash *current = NULL;
1498  if (!msgTable || !name) {
1499  return NULL;
1500  }
1501  idx = CMD_HASH(name);
1502 
1503  for (current = msgTable[idx]; current; current = current->next) {
1504  if (UseTokens) {
1505  if (ircd->tokencaseless) {
1506  if (stricmp(name, current->name) == 0) {
1507  return current->m;
1508  }
1509  } else {
1510  if (strcmp(name, current->name) == 0) {
1511  return current->m;
1512  }
1513  }
1514  } else {
1515  if (stricmp(name, current->name) == 0) {
1516  return current->m;
1517  }
1518  }
1519  }
1520  return NULL;
1521 }
1522 
1531 int addMessage(MessageHash * msgTable[], Message * m, int pos)
1532 {
1533  /* We can assume both param's have been checked by this point.. */
1534  int index = 0;
1535  MessageHash *current = NULL;
1536  MessageHash *newHash = NULL;
1537  MessageHash *lastHash = NULL;
1538  Message *tail = NULL;
1539  int match = 0;
1540 
1541  if (!msgTable || !m || (pos < 0 || pos > 2)) {
1542  return MOD_ERR_PARAMS;
1543  }
1544 
1545  index = CMD_HASH(m->name);
1546 
1547  for (current = msgTable[index]; current; current = current->next) {
1548  if ((UseTokens) && (!ircd->tokencaseless)) {
1549  match = strcmp(m->name, current->name);
1550  } else {
1551  match = stricmp(m->name, current->name);
1552  }
1553  if (match == 0) { /* the msg exist's we are a addHead */
1554  if (pos == 1) {
1555  m->next = current->m;
1556  current->m = m;
1557  if (debug)
1558  alog("debug: existing msg: (0x%p), new msg (0x%p)",
1559  (void *) m->next, (void *) m);
1560  return MOD_ERR_OK;
1561  } else if (pos == 2) {
1562  tail = current->m;
1563  while (tail->next)
1564  tail = tail->next;
1565  if (debug)
1566  alog("debug: existing msg: (0x%p), new msg (0x%p)",
1567  (void *) tail, (void *) m);
1568  tail->next = m;
1569  m->next = NULL;
1570  return MOD_ERR_OK;
1571  } else
1572  return MOD_ERR_EXISTS;
1573  }
1574  lastHash = current;
1575  }
1576 
1577  if ((newHash = malloc(sizeof(MessageHash))) == NULL) {
1578  fatal("Out of memory");
1579  }
1580  newHash->next = NULL;
1581  newHash->name = sstrdup(m->name);
1582  newHash->m = m;
1583 
1584  if (lastHash == NULL)
1585  msgTable[index] = newHash;
1586  else
1587  lastHash->next = newHash;
1588  return MOD_ERR_OK;
1589 }
1590 
1597 int addCoreMessage(MessageHash * msgTable[], Message * m)
1598 {
1599  if (!msgTable || !m) {
1600  return MOD_ERR_PARAMS;
1601  }
1602  m->core = 1;
1603  return addMessage(msgTable, m, 0);
1604 }
1605 
1612 int moduleAddMessage(Message * m, int pos)
1613 {
1614  int status;
1615 
1616  if (!m) {
1617  return MOD_ERR_PARAMS;
1618  }
1619 
1620  if (!mod_current_module) {
1621  return MOD_ERR_UNKNOWN;
1622  } /* shouldnt happen */
1623  m->core = 0;
1624  if (!m->mod_name) {
1625  m->mod_name = sstrdup(mod_current_module->name);
1626  }
1627 
1628  status = addMessage(IRCD, m, pos);
1629  if (debug) {
1631  }
1632  return status;
1633 }
1634 
1640 int moduleDelMessage(char *name)
1641 {
1642  Message *m;
1643  int status;
1644 
1645  if (!mod_current_module) {
1646  return MOD_ERR_UNKNOWN;
1647  }
1648  m = findMessage(IRCD, name);
1649  if (!m) {
1650  return MOD_ERR_NOEXIST;
1651  }
1652 
1653  status = delMessage(IRCD, m, mod_current_module->name);
1654  if (debug) {
1656  }
1657  destroyMessage(m);
1658  return status;
1659 }
1660 
1668 int delMessage(MessageHash * msgTable[], Message * m, char *mod_name)
1669 {
1670  int index = 0;
1671  MessageHash *current = NULL;
1672  MessageHash *lastHash = NULL;
1673  Message *tail = NULL, *last = NULL;
1674 
1675  if (!m || !msgTable) {
1676  return MOD_ERR_PARAMS;
1677  }
1678 
1679  index = CMD_HASH(m->name);
1680 
1681  for (current = msgTable[index]; current; current = current->next) {
1682  if (stricmp(m->name, current->name) == 0) {
1683  if (!lastHash) {
1684  tail = current->m;
1685  if (tail->next) {
1686  while (tail) {
1687  if (mod_name && tail->mod_name
1688  && (stricmp(mod_name, tail->mod_name) == 0)) {
1689  if (last) {
1690  last->next = tail->next;
1691  } else {
1692  current->m = tail->next;
1693  }
1694  return MOD_ERR_OK;
1695  }
1696  last = tail;
1697  tail = tail->next;
1698  }
1699  } else {
1700  msgTable[index] = current->next;
1701  free(current->name);
1702  free(current);
1703  return MOD_ERR_OK;
1704  }
1705  } else {
1706  tail = current->m;
1707  if (tail->next) {
1708  while (tail) {
1709  if (mod_name && tail->mod_name
1710  && (stricmp(mod_name, tail->mod_name) == 0)) {
1711  if (last) {
1712  last->next = tail->next;
1713  } else {
1714  current->m = tail->next;
1715  }
1716  return MOD_ERR_OK;
1717  }
1718  last = tail;
1719  tail = tail->next;
1720  }
1721  } else {
1722  lastHash->next = current->next;
1723  free(current->name);
1724  free(current);
1725  return MOD_ERR_OK;
1726  }
1727  }
1728  }
1729  lastHash = current;
1730  }
1731  return MOD_ERR_NOEXIST;
1732 }
1733 
1740 {
1741  if (!m) {
1742  return MOD_ERR_PARAMS;
1743  }
1744  if (m->name) {
1745  free(m->name);
1746  }
1747  m->func = NULL;
1748  if (m->mod_name) {
1749  free(m->mod_name);
1750  }
1751  m->next = NULL;
1752  free(m);
1753  return MOD_ERR_OK;
1754 }
1755 
1760 void moduleAddVersion(const char *version)
1761 {
1762  if (mod_current_module && version) {
1763  Anope_Free(mod_current_module->version);
1764  mod_current_module->version = sstrdup(version);
1765  }
1766 }
1767 
1772 void moduleAddAuthor(const char *author)
1773 {
1774  if (mod_current_module && author) {
1775  Anope_Free(mod_current_module->author);
1776  mod_current_module->author = sstrdup(author);
1777  }
1778 }
1779 
1780 /*******************************************************************************
1781  * Module Callback Functions
1782  *******************************************************************************/
1794 int moduleAddCallback(char *name, time_t when,
1795  int (*func) (int argc, char *argv[]), int argc,
1796  char **argv)
1797 {
1798  ModuleCallBack *new, *tmp, *prev;
1799  int i;
1800  new = malloc(sizeof(ModuleCallBack));
1801  if (!new)
1802  return MOD_ERR_MEMORY;
1803 
1804  if (name)
1805  new->name = sstrdup(name);
1806  else
1807  new->name = NULL;
1808  new->when = when;
1810  new->owner_name = sstrdup(mod_current_module_name);
1811  } else {
1812  new->owner_name = NULL;
1813  }
1814  new->func = func;
1815  new->argc = argc;
1816  new->argv = malloc(sizeof(char *) * argc);
1817  for (i = 0; i < argc; i++) {
1818  new->argv[i] = sstrdup(argv[i]);
1819  }
1820  new->next = NULL;
1821 
1822  if (moduleCallBackHead == NULL) {
1823  moduleCallBackHead = new;
1824  } else { /* find place in list */
1825  tmp = moduleCallBackHead;
1826  prev = tmp;
1827  if (new->when < tmp->when) {
1828  new->next = tmp;
1829  moduleCallBackHead = new;
1830  } else {
1831  while (tmp && new->when >= tmp->when) {
1832  prev = tmp;
1833  tmp = tmp->next;
1834  }
1835  prev->next = new;
1836  new->next = tmp;
1837  }
1838  }
1839  if (debug)
1840  alog("debug: added module CallBack: [%s] due to execute at %ld",
1841  new->name ? new->name : "?", (long int) new->when);
1842  return MOD_ERR_OK;
1843 }
1844 
1849 {
1850  ModuleCallBack *tmp;
1851 
1852  while ((tmp = moduleCallBackHead) && (tmp->when <= time(NULL))) {
1853  if (debug)
1854  alog("debug: executing callback: %s", tmp->name ? tmp->name : "<unknown>");
1855  if (tmp->func) {
1856  mod_current_module = findModule(tmp->owner_name);
1858  tmp->func(tmp->argc, tmp->argv);
1859  mod_current_module = NULL;
1860  mod_current_module_name = NULL;
1862  }
1863  }
1864 }
1865 
1871 {
1872  ModuleCallBack *tmp = NULL;
1873  int i;
1874  if (prev == NULL) {
1875  tmp = moduleCallBackHead;
1876  moduleCallBackHead = tmp->next;
1877  } else {
1878  tmp = prev->next;
1879  prev->next = tmp->next;
1880  }
1881  if (tmp->name)
1882  free(tmp->name);
1883  if (tmp->owner_name)
1884  free(tmp->owner_name);
1885  tmp->func = NULL;
1886  for (i = 0; i < tmp->argc; i++) {
1887  free(tmp->argv[i]);
1888  }
1889  free(tmp->argv);
1890  tmp->argc = 0;
1891  tmp->next = NULL;
1892  free(tmp);
1893 }
1894 
1901 ModuleCallBack *moduleCallBackFindEntry(char *mod_name, boolean * found)
1902 {
1903  ModuleCallBack *prev = NULL, *current = NULL;
1904  *found = false;
1905  current = moduleCallBackHead;
1906  while (current != NULL) {
1907  if (current->owner_name
1908  && (strcmp(mod_name, current->owner_name) == 0)) {
1909  *found = true;
1910  break;
1911  } else {
1912  prev = current;
1913  current = current->next;
1914  }
1915  }
1916  if (current == moduleCallBackHead) {
1917  return NULL;
1918  } else {
1919  return prev;
1920  }
1921 }
1922 
1927 void moduleDelCallback(char *name)
1928 {
1929  ModuleCallBack *current = NULL;
1930  ModuleCallBack *prev = NULL, *tmp = NULL;
1931  int del = 0;
1932  if (!mod_current_module_name) {
1933  return;
1934  }
1935  if (!name) {
1936  return;
1937  }
1938  current = moduleCallBackHead;
1939  while (current) {
1940  if ((current->owner_name) && (current->name)) {
1941  if ((strcmp(mod_current_module_name, current->owner_name) == 0)
1942  && (strcmp(current->name, name) == 0)) {
1943  if (debug) {
1944  alog("debug: removing CallBack %s for module %s", name,
1946  }
1947  tmp = current->next; /* get a pointer to the next record, as once we delete this record, we'll lose it :) */
1948  moduleCallBackDeleteEntry(prev); /* delete this record */
1949  del = 1; /* set the record deleted flag */
1950  }
1951  }
1952  if (del == 1) { /* if a record was deleted */
1953  current = tmp; /* use the value we stored in temp */
1954  tmp = NULL; /* clear it for next time */
1955  del = 0; /* reset the flag */
1956  } else {
1957  prev = current; /* just carry on as normal */
1958  current = current->next;
1959  }
1960  }
1961 }
1962 
1968 void moduleCallBackPrepForUnload(char *mod_name)
1969 {
1970  boolean found = false;
1971  ModuleCallBack *tmp = NULL;
1972 
1973  tmp = moduleCallBackFindEntry(mod_name, &found);
1974  while (found) {
1975  if (debug) {
1976  alog("debug: removing CallBack for module %s", mod_name);
1977  }
1979  tmp = moduleCallBackFindEntry(mod_name, &found);
1980  }
1981 }
1982 
1989 {
1990  char *tmp = NULL;
1991  if (mod_current_buffer) {
1992  tmp = strchr(mod_current_buffer, ' ');
1993  if (tmp) {
1994  tmp++;
1995  }
1996  }
1997  return tmp;
1998 }
1999 
2000 /*******************************************************************************
2001  * Module HELP Functions
2002  *******************************************************************************/
2008 int moduleAddRootHelp(Command * c, int (*func) (User * u))
2009 {
2010  if (c) {
2011  c->root_help = func;
2012  return MOD_STOP;
2013  }
2014  return MOD_CONT;
2015 }
2016 
2022 int moduleAddAdminHelp(Command * c, int (*func) (User * u))
2023 {
2024  if (c) {
2025  c->admin_help = func;
2026  return MOD_STOP;
2027  }
2028  return MOD_CONT;
2029 }
2030 
2036 int moduleAddOperHelp(Command * c, int (*func) (User * u))
2037 {
2038  if (c) {
2039  c->oper_help = func;
2040  return MOD_STOP;
2041  }
2042  return MOD_CONT;
2043 }
2044 
2050 int moduleAddRegHelp(Command * c, int (*func) (User * u))
2051 {
2052  if (c) {
2053  c->regular_help = func;
2054  return MOD_STOP;
2055  }
2056  return MOD_CONT;
2057 }
2058 
2064 int moduleAddHelp(Command * c, int (*func) (User * u))
2065 {
2066  if (c) {
2067  c->all_help = func;
2068  return MOD_STOP;
2069  }
2070  return MOD_CONT;
2071 }
2072 
2078 void moduleSetNickHelp(void (*func) (User * u))
2079 {
2080  if (mod_current_module) {
2081  mod_current_module->nickHelp = func;
2082  }
2083 }
2084 
2090 void moduleSetChanHelp(void (*func) (User * u))
2091 {
2092  if (mod_current_module) {
2093  mod_current_module->chanHelp = func;
2094  }
2095 }
2096 
2102 void moduleSetMemoHelp(void (*func) (User * u))
2103 {
2104  if (mod_current_module) {
2105  mod_current_module->memoHelp = func;
2106  }
2107 }
2108 
2114 void moduleSetBotHelp(void (*func) (User * u))
2115 {
2116  if (mod_current_module) {
2117  mod_current_module->botHelp = func;
2118  }
2119 }
2120 
2126 void moduleSetOperHelp(void (*func) (User * u))
2127 {
2128  if (mod_current_module) {
2129  mod_current_module->operHelp = func;
2130  }
2131 }
2132 
2138 void moduleSetHostHelp(void (*func) (User * u))
2139 {
2140  if (mod_current_module) {
2141  mod_current_module->hostHelp = func;
2142  }
2143 }
2144 
2150 void moduleSetHelpHelp(void (*func) (User * u))
2151 {
2152  if (mod_current_module) {
2153  mod_current_module->helpHelp = func;
2154  }
2155 }
2156 
2162 void moduleDisplayHelp(int service, User * u)
2163 {
2164 #ifdef USE_MODULES
2165  int idx;
2166  ModuleHash *current = NULL;
2167  Module *calling_module = mod_current_module;
2168  char *calling_module_name = mod_current_module_name;
2169 
2170  for (idx = 0; idx != MAX_CMD_HASH; idx++) {
2171  for (current = MODULE_HASH[idx]; current; current = current->next) {
2172  mod_current_module_name = current->name;
2173  mod_current_module = current->m;
2174 
2175  if ((service == 1) && current->m->nickHelp) {
2176  current->m->nickHelp(u);
2177  } else if ((service == 2) && current->m->chanHelp) {
2178  current->m->chanHelp(u);
2179  } else if ((service == 3) && current->m->memoHelp) {
2180  current->m->memoHelp(u);
2181  } else if ((service == 4) && current->m->botHelp) {
2182  current->m->botHelp(u);
2183  } else if ((service == 5) && current->m->operHelp) {
2184  current->m->operHelp(u);
2185  } else if ((service == 6) && current->m->hostHelp) {
2186  current->m->hostHelp(u);
2187  } else if ((service == 7) && current->m->helpHelp) {
2188  current->m->helpHelp(u);
2189  }
2190  }
2191  }
2192 
2193  mod_current_module = calling_module;
2194  mod_current_module_name = calling_module_name;
2195 #endif
2196 }
2197 
2206 {
2207  ModuleData *current = NULL;
2208  alog("Dumping module data....");
2209  for (current = *md; current; current = current->next) {
2210  alog("Module: [%s]", current->moduleName);
2211  alog(" Key [%s]\tValue [%s]", current->key, current->value);
2212  }
2213  alog("End of module data dump");
2214  return 0;
2215 }
2216 
2225 int moduleAddData(ModuleData ** md, char *key, char *value)
2226 {
2227  ModuleData *newData = NULL;
2228 
2229  if (mod_current_module_name == NULL) {
2230  alog("moduleAddData() called with mod_current_module_name being NULL");
2231  if (debug)
2232  do_backtrace(0);
2233  }
2234 
2235  if (!key || !value) {
2236  alog("A module (%s) tried to use ModuleAddData() with one or more NULL arguments... returning", mod_current_module_name);
2237  return MOD_ERR_PARAMS;
2238  }
2239 
2240  moduleDelData(md, key); /* Remove any existing module data for this module with the same key */
2241 
2242  newData = malloc(sizeof(ModuleData));
2243  if (!newData) {
2244  return MOD_ERR_MEMORY;
2245  }
2246 
2248  newData->key = sstrdup(key);
2249  newData->value = sstrdup(value);
2250  newData->next = *md;
2251  *md = newData;
2252 
2253  if (debug) {
2254  moduleDataDebug(md);
2255  }
2256  return MOD_ERR_OK;
2257 }
2258 
2266 char *moduleGetData(ModuleData ** md, char *key)
2267 {
2268  /* See comment in moduleAddData... -GD */
2269  char *mod_name = sstrdup(mod_current_module_name);
2270  ModuleData *current = *md;
2271 
2272  if (mod_current_module_name == NULL) {
2273  alog("moduleGetData() called with mod_current_module_name being NULL");
2274  if (debug)
2275  do_backtrace(0);
2276  }
2277 
2278  if (debug > 1) {
2279  alog("debug: moduleGetData %p : key %s", (void *) md, key);
2280  alog("debug: Current Module %s", mod_name);
2281  }
2282 
2283  while (current) {
2284  if ((stricmp(current->moduleName, mod_name) == 0)
2285  && (stricmp(current->key, key) == 0)) {
2286  free(mod_name);
2287  return sstrdup(current->value);
2288  }
2289  current = current->next;
2290  }
2291  free(mod_name);
2292  return NULL;
2293 }
2294 
2301 void moduleDelData(ModuleData ** md, char *key)
2302 {
2303  /* See comment in moduleAddData... -GD */
2304  char *mod_name = sstrdup(mod_current_module_name);
2305  ModuleData *current = *md;
2306  ModuleData *prev = NULL;
2307  ModuleData *next = NULL;
2308 
2309  if (mod_current_module_name == NULL) {
2310  alog("moduleDelData() called with mod_current_module_name being NULL");
2311  if (debug)
2312  do_backtrace(0);
2313  }
2314 
2315  if (key) {
2316  while (current) {
2317  next = current->next;
2318  if ((stricmp(current->moduleName, mod_name) == 0)
2319  && (stricmp(current->key, key) == 0)) {
2320  if (prev) {
2321  prev->next = current->next;
2322  } else {
2323  *md = current->next;
2324  }
2325  free(current->moduleName);
2326  free(current->key);
2327  free(current->value);
2328  current->next = NULL;
2329  free(current);
2330  } else {
2331  prev = current;
2332  }
2333  current = next;
2334  }
2335  }
2336  free(mod_name);
2337 }
2338 
2346 {
2347  /* See comment in moduleAddData... -GD */
2348  char *mod_name = sstrdup(mod_current_module_name);
2349  ModuleData *current = *md;
2350  ModuleData *prev = NULL;
2351  ModuleData *next = NULL;
2352 
2353  if (mod_current_module_name == NULL) {
2354  alog("moduleDelAllData() called with mod_current_module_name being NULL");
2355  if (debug)
2356  do_backtrace(0);
2357  }
2358 
2359  while (current) {
2360  next = current->next;
2361  if ((stricmp(current->moduleName, mod_name) == 0)) {
2362  if (prev) {
2363  prev->next = current->next;
2364  } else {
2365  *md = current->next;
2366  }
2367  free(current->moduleName);
2368  free(current->key);
2369  free(current->value);
2370  current->next = NULL;
2371  free(current);
2372  } else {
2373  prev = current;
2374  }
2375  current = next;
2376  }
2377  free(mod_name);
2378 }
2379 
2385 {
2386  boolean freeme = false;
2387  int i, j;
2388  User *user;
2389  NickAlias *na;
2390  NickCore *nc;
2391  ChannelInfo *ci;
2392 
2393  if (!mod_current_module_name) {
2395  freeme = true;
2396  }
2397 
2398  for (i = 0; i < 1024; i++) {
2399  /* Remove the users */
2400  for (user = userlist[i]; user; user = user->next) {
2401  moduleDelAllData(&user->moduleData);
2402  }
2403  /* Remove the nick Cores */
2404  for (nc = nclists[i]; nc; nc = nc->next) {
2406  /* Remove any memo data for this nick core */
2407  for (j = 0; j < nc->memos.memocount; j++) {
2409  }
2410  }
2411  /* Remove the nick Aliases */
2412  for (na = nalists[i]; na; na = na->next) {
2414  }
2415  }
2416 
2417  for (i = 0; i < 256; i++) {
2418  /* Remove any chan info data */
2419  for (ci = chanlists[i]; ci; ci = ci->next) {
2421  /* Remove any memo data for this nick core */
2422  for (j = 0; j < ci->memos.memocount; j++) {
2424  }
2425  }
2426  }
2427 
2428  if (freeme) {
2430  mod_current_module_name = NULL;
2431  }
2432 }
2433 
2439 void moduleCleanStruct(ModuleData ** moduleData)
2440 {
2441  ModuleData *current = *moduleData;
2442  ModuleData *next = NULL;
2443 
2444  while (current) {
2445  next = current->next;
2446  free(current->moduleName);
2447  free(current->key);
2448  free(current->value);
2449  current->next = NULL;
2450  free(current);
2451  current = next;
2452  }
2453  *moduleData = NULL;
2454 }
2455 
2465 boolean moduleMinVersion(int major, int minor, int patch, int build)
2466 {
2467  boolean ret = false;
2468  if (VERSION_MAJOR > major) { /* Def. new */
2469  ret = true;
2470  } else if (VERSION_MAJOR == major) { /* Might be newer */
2471  if (minor == -1) {
2472  return true;
2473  } /* They dont care about minor */
2474  if (VERSION_MINOR > minor) { /* Def. newer */
2475  ret = true;
2476  } else if (VERSION_MINOR == minor) { /* Might be newer */
2477  if (patch == -1) {
2478  return true;
2479  } /* They dont care about patch */
2480  if (VERSION_PATCH > patch) {
2481  ret = true;
2482  } else if (VERSION_PATCH == patch) {
2483  if (build == -1) {
2484  return true;
2485  } /* They dont care about build */
2486  if (VERSION_BUILD >= build) {
2487  ret = true;
2488  }
2489  }
2490  }
2491  }
2492  return ret;
2493 }
2494 
2495 #ifdef _WIN32
2496 const char *ano_moderr(void)
2497 {
2498  static char errbuf[513];
2499  DWORD err = GetLastError();
2500  if (err == 0)
2501  return NULL;
2502  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
2503  FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, errbuf, 512,
2504  NULL);
2505  return errbuf;
2506 }
2507 #endif
2508 
2512 void updateProtectDetails(char *level_info_protect_word,
2513  char *level_info_protectme_word,
2514  char *fant_protect_add, char *fant_protect_del,
2515  char *level_protect_word, char *protect_set_mode,
2516  char *protect_unset_mode)
2517 {
2518  int i = 0;
2519  CSModeUtil ptr;
2520  LevelInfo l_ptr;
2521 
2522  ptr = csmodeutils[i];
2523  while (ptr.name) {
2524  if (strcmp(ptr.name, "PROTECT") == 0) {
2525  csmodeutils[i].bsname = sstrdup(fant_protect_add);
2526  csmodeutils[i].mode = sstrdup(protect_set_mode);
2527  } else if (strcmp(ptr.name, "DEPROTECT") == 0) {
2528  csmodeutils[i].bsname = sstrdup(fant_protect_del);
2529  csmodeutils[i].mode = sstrdup(protect_unset_mode);
2530  }
2531  ptr = csmodeutils[++i];
2532  }
2533 
2534  i = 0;
2535  l_ptr = levelinfo[i];
2536  while (l_ptr.what != -1) {
2537  if (l_ptr.what == CA_PROTECT) {
2538  levelinfo[i].name = sstrdup(level_info_protect_word);
2539  } else if (l_ptr.what == CA_PROTECTME) {
2540  levelinfo[i].name = sstrdup(level_info_protectme_word);
2541  } else if (l_ptr.what == CA_AUTOPROTECT) {
2542  levelinfo[i].name = sstrdup(level_protect_word);
2543  }
2544  l_ptr = levelinfo[++i];
2545  }
2546 }
2547 
2554 {
2555  FILE *config;
2556  char *dir = NULL;
2557  char buf[1024];
2558  char *directive;
2559  int linenum = 0;
2560  int ac = 0;
2561  char *av[MAXPARAMS];
2562  char *str = NULL;
2563  char *s = NULL;
2564  char *t = NULL;
2565  int retval = 1;
2566  int i;
2567 
2568  /* Dumb modules pass uninitialized string pointers here. Dumb people will not add the proper configuration values to services.conf.
2569  * Combine the two and you end up with parse_directive never setting the char* pointers passed here. So, null them out now.
2570  */
2571  for (i = 0; i < MAXPARAMS && d->params[i].type != PARAM_NONE; i++)
2572  if (d->params[i].type == PARAM_STRING)
2573  *(char **) d->params[i].ptr = NULL;
2574 
2575  config = fopen(SERVICES_CONF, "r");
2576  if (!config) {
2577  alog("Can't open %s", SERVICES_CONF);
2578  return 0;
2579  }
2580  while (fgets(buf, sizeof(buf), config)) {
2581  linenum++;
2582  if (*buf == '#' || *buf == '\r' || *buf == '\n') {
2583  continue;
2584  }
2585  dir = myStrGetOnlyToken(buf, '\t', 0);
2586  if (dir) {
2587  str = myStrGetTokenRemainder(buf, '\t', 1);
2588  } else {
2589  dir = myStrGetOnlyToken(buf, ' ', 0);
2590  if (dir || (dir = myStrGetOnlyToken(buf, '\n', 0))) {
2591  str = myStrGetTokenRemainder(buf, ' ', 1);
2592  } else {
2593  continue;
2594  }
2595  }
2596  if (dir)
2597  directive = normalizeBuffer(dir);
2598  else
2599  continue;
2600 
2601  if (stricmp(directive, d->name) == 0) {
2602  if (str) {
2603  s = str;
2604  while (isspace(*s))
2605  s++;
2606  while (*s) {
2607  if (ac >= MAXPARAMS) {
2608  alog("module error: too many config. params");
2609  break;
2610  }
2611  t = s;
2612  if (*s == '"') {
2613  t++;
2614  s++;
2615  while (*s && *s != '"') {
2616  if (*s == '\\' && s[1] != 0)
2617  s++;
2618  s++;
2619  }
2620  if (!*s)
2621  alog("module error: Warning: unterminated double-quoted string");
2622  else
2623  *s++ = 0;
2624  } else {
2625  s += strcspn(s, " \t\r\n");
2626  if (*s)
2627  *s++ = 0;
2628  }
2629  av[ac++] = t;
2630  while (isspace(*s))
2631  s++;
2632  }
2633  }
2634  retval = parse_directive(d, directive, ac, av, linenum, 0, s);
2635  }
2636  Anope_Free(directive);
2637  Anope_Free(dir);
2638  Anope_Free(str);
2639  }
2640  fclose(config);
2641  return retval;
2642 }
2643 
2650 void moduleInsertLanguage(int langNumber, int ac, char **av)
2651 {
2652  int i;
2653 
2654  if ((mod_current_module_name) && (!mod_current_module || strcmp(mod_current_module_name, mod_current_module->name))) {
2655  mod_current_module = findModule(mod_current_module_name);
2656  }
2657 
2658  if (debug)
2659  alog("debug: %s Adding %d texts for language %d", mod_current_module->name, ac, langNumber);
2660 
2661  if (mod_current_module->lang[langNumber].argc > 0) {
2662  moduleDeleteLanguage(langNumber);
2663  }
2664 
2665  mod_current_module->lang[langNumber].argc = ac;
2666  mod_current_module->lang[langNumber].argv =
2667  malloc(sizeof(char *) * ac);
2668  for (i = 0; i < ac; i++) {
2669  mod_current_module->lang[langNumber].argv[i] = sstrdup(av[i]);
2670  }
2671 }
2672 
2680 void moduleNoticeLang(char *source, User * u, int number, ...)
2681 {
2682  va_list va;
2683  char buffer[4096], outbuf[4096];
2684  char *fmt = NULL;
2685  int lang = NSDefLanguage;
2686  char *s, *t, *buf;
2687 
2688  if ((mod_current_module_name) && (!mod_current_module || strcmp(mod_current_module_name, mod_current_module->name))) {
2689  mod_current_module = findModule(mod_current_module_name);
2690  }
2691 
2692  /* Find the users lang, and use it if we can */
2693  if (u && u->na && u->na->nc) {
2694  lang = u->na->nc->language;
2695  }
2696 
2697  /* If the users lang isnt supported, drop back to English */
2698  if (mod_current_module->lang[lang].argc == 0) {
2699  lang = LANG_EN_US;
2700  }
2701 
2702  /* If the requested lang string exists for the language */
2703  if (mod_current_module->lang[lang].argc > number) {
2704  fmt = mod_current_module->lang[lang].argv[number];
2705 
2706  buf = sstrdup(fmt);
2707  va_start(va, number);
2708  vsnprintf(buffer, 4095, buf, va);
2709  va_end(va);
2710  s = buffer;
2711  while (*s) {
2712  t = s;
2713  s += strcspn(s, "\n");
2714  if (*s)
2715  *s++ = '\0';
2716  strscpy(outbuf, t, sizeof(outbuf));
2717  notice_user(source, u, "%s", outbuf);
2718  }
2719  free(buf);
2720  } else {
2721  alog("%s: INVALID language string call, language: [%d], String [%d]", mod_current_module->name, lang, number);
2722  }
2723 }
2724 
2731 char *moduleGetLangString(User * u, int number)
2732 {
2733  int lang = NSDefLanguage;
2734 
2735  if ((mod_current_module_name) && (!mod_current_module || strcmp(mod_current_module_name, mod_current_module->name)))
2736  mod_current_module = findModule(mod_current_module_name);
2737 
2738  /* Find the users lang, and use it if we can */
2739  if (u && u->na && u->na->nc)
2740  lang = u->na->nc->language;
2741 
2742  /* If the users lang isnt supported, drop back to English */
2743  if (mod_current_module->lang[lang].argc == 0)
2744  lang = LANG_EN_US;
2745 
2746  /* If the requested lang string exists for the language */
2747  if (mod_current_module->lang[lang].argc > number) {
2748  return mod_current_module->lang[lang].argv[number];
2749  /* Return an empty string otherwise, because we might be used without
2750  * the return value being checked. If we would return NULL, bad things
2751  * would happen!
2752  */
2753  } else {
2754  alog("%s: INVALID language string call, language: [%d], String [%d]", mod_current_module->name, lang, number);
2755  return "";
2756  }
2757 }
2758 
2763 void moduleDeleteLanguage(int langNumber)
2764 {
2765  int idx = 0;
2766  if ((mod_current_module_name) && (!mod_current_module || strcmp(mod_current_module_name, mod_current_module->name))) {
2767  mod_current_module = findModule(mod_current_module_name);
2768  }
2769  for (idx = 0; idx < mod_current_module->lang[langNumber].argc; idx++) {
2770  free(mod_current_module->lang[langNumber].argv[idx]);
2771  }
2772  Anope_Free(mod_current_module->lang[langNumber].argv);
2773  mod_current_module->lang[langNumber].argv = NULL;
2774  mod_current_module->lang[langNumber].argc = 0;
2775 }
2776 
2784 {
2785  ModuleQueue *qm;
2786 
2787  qm = scalloc(1, sizeof(ModuleQueue));
2788  qm->m = m;
2789  qm->op = op;
2790  qm->u = u;
2791  qm->next = mod_operation_queue;
2792  mod_operation_queue = qm;
2793 }
2794 
2801 int queueModuleLoad(char *name, User *u)
2802 {
2803  Module *m;
2804 
2805  if (!name || !u)
2806  return 0;
2807 
2808  if (findModule(name))
2809  return 0;
2810  m = createModule(name);
2812 
2813  return 1;
2814 }
2815 
2822 int queueModuleUnload(char *name, User *u)
2823 {
2824  Module *m;
2825 
2826  if (!name || !u)
2827  return 0;
2828 
2829  m = findModule(name);
2830  if (!m)
2831  return 0;
2833 
2834  return 1;
2835 }
2836 
2841 {
2842  ModuleQueue *next;
2843  int status;
2844 
2845  if (!mod_operation_queue)
2846  return;
2847 
2848  while (mod_operation_queue) {
2849  next = mod_operation_queue->next;
2850 
2851  mod_current_module = mod_operation_queue->m;
2852  mod_current_user = mod_operation_queue->u;
2853 
2854  if (mod_operation_queue->op == MOD_OP_LOAD) {
2855  alog("Trying to load module [%s]", mod_operation_queue->m->name);
2856  status = loadModule(mod_operation_queue->m, mod_operation_queue->u);
2857  alog("Module loading status: %d (%s)", status, ModuleGetErrStr(status));
2858  if (status != MOD_ERR_OK) {
2859  if(mod_current_user) {
2860  notice_lang(s_OperServ, mod_current_user, OPER_MODULE_LOAD_FAIL,mod_operation_queue->m->name);
2861  }
2862  destroyModule(mod_operation_queue->m);
2863  }
2864  } else if (mod_operation_queue->op == MOD_OP_UNLOAD) {
2865  alog("Trying to unload module [%s]", mod_operation_queue->m->name);
2866  status = unloadModule(mod_operation_queue->m, mod_operation_queue->u);
2867  alog("Module unloading status: %d (%s)", status, ModuleGetErrStr(status));
2868  }
2869 
2870  /* Remove the ModuleQueue from memory */
2871  free(mod_operation_queue);
2872 
2873  mod_operation_queue = next;
2874  }
2875 
2876  mod_current_module = NULL;
2877  mod_current_user = NULL;
2878 }
2879 
2881 {
2882 #ifndef _WIN32
2883  DIR *dirp;
2884  struct dirent *dp;
2885 #else
2886  BOOL fFinished;
2887  HANDLE hList;
2888  TCHAR szDir[MAX_PATH + 1];
2889  TCHAR szSubDir[MAX_PATH + 1];
2890  WIN32_FIND_DATA FileData;
2891  char buffer[_MAX_PATH];
2892 #endif
2893  char dirbuf[BUFSIZE];
2894  char filebuf[BUFSIZE];
2895 
2896 
2897 #ifndef _WIN32
2898  snprintf(dirbuf, BUFSIZE, "%s/modules/runtime", services_dir);
2899 #else
2900  snprintf(dirbuf, BUFSIZE, "\\%s", "modules/runtime");
2901 #endif
2902 
2903  if (debug) {
2904  alog("debug: Cleaning out Module run time directory (%s) - this may take a moment please wait", dirbuf);
2905  }
2906 
2907 #ifndef _WIN32
2908  if ((dirp = opendir(dirbuf)) == NULL) {
2909  if (debug)
2910  alog("debug: cannot open directory (%s)", dirbuf);
2911  return;
2912  }
2913  while ((dp = readdir(dirp)) != NULL) {
2914  if (dp->d_ino == 0) {
2915  continue;
2916  }
2917  if (!stricmp(dp->d_name, ".") || !stricmp(dp->d_name, "..")) {
2918  continue;
2919  }
2920  snprintf(filebuf, BUFSIZE, "%s/%s", dirbuf, dp->d_name);
2921  unlink(filebuf);
2922  }
2923  closedir(dirp);
2924 #else
2925  /* Get the current working directory: */
2926  if (_getcwd(buffer, _MAX_PATH) == NULL) {
2927  if (debug)
2928  alog("debug: Unable to set Current working directory");
2929  }
2930  snprintf(szDir, sizeof(szDir), "%s\\%s\\*", buffer, dirbuf);
2931 
2932  hList = FindFirstFile(szDir, &FileData);
2933  if (hList != INVALID_HANDLE_VALUE) {
2934  fFinished = FALSE;
2935  while (!fFinished) {
2936  if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2937  snprintf(filebuf, BUFSIZE, "%s/%s", dirbuf, FileData.cFileName);
2938  DeleteFile(filebuf);
2939  }
2940  if (!FindNextFile(hList, &FileData)) {
2941  if (GetLastError() == ERROR_NO_MORE_FILES) {
2942  fFinished = TRUE;
2943  }
2944  }
2945  }
2946  } else {
2947  if (debug)
2948  alog("debug: Invalid File Handle. GetLastError reports %d\n", GetLastError());
2949  }
2950  FindClose(hList);
2951 #endif
2952  if (debug)
2953  alog("debug: Module run time directory has been cleaned out");
2954 }
2955 
2956 /* EOF */
void * handle
Definition: modules.h:139
void moduleSetOperHelp(void(*func)(User *u))
Definition: modules.c:2126
ModuleData * moduleData
Definition: services.h:695
int addModule(Module *m)
Definition: modules.c:404
void moduleNoticeLang(char *source, User *u, int number,...)
Definition: modules.c:2680
ModuleData * next
Definition: services.h:482
int moduleCopyFile(char *name, char *output)
Definition: modules.c:538
char * ModuleGetErrStr(int status)
Definition: modules.c:65
Command * next
Definition: modules.h:202
#define Anope_Free(x)
Definition: extern.h:1391
CommandHash * next
Definition: modules.h:208
int moduleDelMessage(char *name)
Definition: modules.c:1640
void moduleAddVersion(const char *version)
Definition: modules.c:1760
void moduleCleanStruct(ModuleData **moduleData)
Definition: modules.c:2439
char * mod_name
Definition: modules.h:215
ModuleHash * next
Definition: modules.h:162
ModuleCallBack * moduleCallBackFindEntry(char *mod_name, boolean *found)
Definition: modules.c:1901
int destroyModule(Module *m)
Definition: modules.c:362
char ** argv
Definition: modules.h:133
char nick[NICKMAX]
Definition: services.h:875
int(* root_help)(User *u)
Definition: modules.h:200
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
static Channel * current
Definition: channels.c:427
void moduleSetHelpHelp(void(*func)(User *u))
Definition: modules.c:2150
E int ModulesNumber
Definition: extern.h:478
int moduleAddCallback(char *name, time_t when, int(*func)(int argc, char *argv[]), int argc, char **argv)
Definition: modules.c:1794
void moduleSetType(MODType type)
Definition: modules.c:818
#define MOD_ERR_NO_MOD_NAME
Definition: modules.h:84
ModuleHash * MODULE_HASH[MAX_CMD_HASH]
Definition: modules.c:50
CommandHash * BOTSERV[MAX_CMD_HASH]
Definition: modules.c:43
#define PARAM_NONE
Definition: services.h:439
void modules_core_init(int number, char **list)
Definition: modules.c:127
E int parse_directive(Directive *d, char *dir, int ac, char *av[MAXPARAMS], int linenum, int reload, char *s)
Definition: config.c:680
E char * s_BotServ
Definition: extern.h:287
E IRCDVar * ircd
Definition: extern.h:39
int displayMessage(Message *m)
Definition: modules.c:1270
Command * c
Definition: modules.h:207
void(* helpHelp)(User *u)
Definition: modules.h:152
ModuleQueue * mod_operation_queue
Definition: modules.c:57
int delMessage(MessageHash *msgTable[], Message *m, char *mod_name)
Definition: modules.c:1668
void moduleCallBackDeleteEntry(ModuleCallBack *prev)
Definition: modules.c:1870
char * mod_name
Definition: modules.h:254
int destroyMessage(Message *m)
Definition: modules.c:1739
EvtHook * evh
Definition: modules.h:260
void moduleDeleteLanguage(int langNumber)
Definition: modules.c:2763
E void send_event(const char *name, int argc,...)
Definition: events.c:37
#define MAX_CMD_HASH
Definition: modules.h:51
int destroyCommand(Command *c)
Definition: modules.c:1028
MessageHash * next
Definition: modules.h:222
int helpmsg_oper
Definition: modules.h:184
EvtHook * next
Definition: modules.h:255
void * ptr
Definition: services.h:435
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
char * help_param3
Definition: modules.h:189
E void E void E void E void notice_user(char *source, User *u, const char *fmt,...) FORMAT(printf
E char * myStrGetTokenRemainder(const char *str, const char dilim, int token_number)
Definition: misc.c:720
ModuleLang lang[NUM_LANGS]
Definition: modules.h:156
int delEventHandler(EvtMessageHash *msgEvtTable[], EvtMessage *evm, char *mod_name)
Definition: events.c:611
int moduleAddCommand(CommandHash *cmdTable[], Command *c, int pos)
Definition: modules.c:1082
CommandHash * NICKSERV[MAX_CMD_HASH]
Definition: modules.c:45
int argc
Definition: modules.h:132
int(* func)(char *source, int ac, char **av)
Definition: modules.h:213
#define EVENT_MODLOAD
Definition: events.h:69
int(* regular_help)(User *u)
Definition: modules.h:197
int delModule(Module *m)
Definition: modules.c:439
ModuleData * moduleData
Definition: services.h:557
E int nofork
Definition: extern.h:779
E int NSDefLanguage
Definition: extern.h:378
NickAlias * next
Definition: services.h:525
Channel * next
Definition: services.h:999
uint16 language
Definition: services.h:549
EvtMessage * next
Definition: modules.h:240
#define EVENTHOOKS
Definition: modules.h:66
void moduleSetBotHelp(void(*func)(User *u))
Definition: modules.c:2114
char * mode
Definition: services.h:828
#define MOD_ERR_EXISTS
Definition: modules.h:74
char * mod_name
Definition: modules.h:239
int linenum
Definition: langcomp.c:53
int moduleDelCommand(CommandHash *cmdTable[], char *name)
Definition: modules.c:1161
EvtMessageHash * next
Definition: modules.h:246
#define SERVICES_CONF
Definition: config.h:25
int displayCommand(Command *c)
Definition: modules.c:1227
char * service
Definition: modules.h:195
char * help_param2
Definition: modules.h:188
MemoInfo memos
Definition: services.h:552
E char * strscpy(char *d, const char *s, size_t len)
Definition: db-merger.c:1886
int16 memocount
Definition: services.h:505
int(* func)(int argc, char *argv[])
Definition: modules.h:229
#define CA_PROTECTME
Definition: services.h:776
#define NUM_LANGS
Definition: services.h:1333
E int nothird
Definition: extern.h:781
#define MAXPARAMS
Definition: services.h:426
int helpmsg_all
Definition: modules.h:182
E char * IRCDModule
Definition: extern.h:50
ModuleCallBack * moduleCallBackHead
Definition: modules.c:56
E char * services_dir
Definition: extern.h:773
E void do_backtrace(int show_segheader)
Definition: main.c:729
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
Command * createCommand(const char *name, int(*func)(User *u), int(*has_priv)(User *u), int help_all, int help_reg, int help_oper, int help_admin, int help_root)
Definition: modules.c:987
E ChannelInfo * chanlists[256]
Definition: extern.h:167
char * version
Definition: modules.h:141
int encryption_module_init(void)
Definition: modules.c:158
int queueModuleUnload(char *name, User *u)
Definition: modules.c:2822
#define MOD_ERR_NOLOAD
Definition: modules.h:77
int moduleAddOperHelp(Command *c, int(*func)(User *u))
Definition: modules.c:2036
E char * sstrdup(const char *s)
Definition: memory.c:105
char * help_param1
Definition: modules.h:187
NickCore * nc
Definition: services.h:533
ModuleData * moduleData
Definition: services.h:535
E void * scalloc(long elsize, long els)
Definition: memory.c:55
int destroyEventHook(EvtHook *evh)
Definition: events.c:781
void moduleDisplayHelp(int service, User *u)
Definition: modules.c:2162
char * filename
Definition: modules.h:138
char * name
Definition: services.h:836
E void E void E void fatal(const char *fmt,...) FORMAT(printf
char * value
Definition: services.h:481
int(* all_help)(User *u)
Definition: modules.h:196
void modules_init(void)
Definition: modules.c:91
void moduleCallBackRun(void)
Definition: modules.c:1848
void(* hostHelp)(User *u)
Definition: modules.h:151
E char * s_OperServ
Definition: extern.h:289
int moduleAddMessage(Message *m, int pos)
Definition: modules.c:1612
char * name
Definition: modules.h:220
E char * s_MemoServ
Definition: extern.h:286
#define MOD_STOP
Definition: modules.h:53
int core
Definition: modules.h:193
int prepForUnload(Module *m)
Definition: modules.c:830
ModuleData * moduleData
Definition: services.h:496
Module * createModule(char *filename)
Definition: modules.c:325
E char * EncModule
Definition: extern.h:580
int moduleAddRootHelp(Command *c, int(*func)(User *u))
Definition: modules.c:2008
char * name
Definition: modules.h:174
E char ** ModulesDelayedAutoload
Definition: extern.h:479
MessageHash * IRCD[MAX_CMD_HASH]
Definition: modules.c:49
void(* botHelp)(User *u)
Definition: modules.h:149
Definition: modules.h:99
#define MOD_ERR_FILE_IO
Definition: modules.h:82
NickCore * next
Definition: services.h:540
int moduleAddAdminHelp(Command *c, int(*func)(User *u))
Definition: modules.c:2022
int unloadModule(Module *m, User *u)
Definition: modules.c:747
int displayMessageFromHash(char *name)
Definition: modules.c:1245
#define MOD_ERR_PARAMS
Definition: modules.h:73
char * name
Definition: services.h:826
int destroyEventHandler(EvtMessage *evm)
Definition: events.c:759
int(* routine)(User *u)
Definition: modules.h:175
E char * s_HelpServ
Definition: extern.h:288
CommandHash * HELPSERV[MAX_CMD_HASH]
Definition: modules.c:47
void(* memoHelp)(User *u)
Definition: modules.h:148
int helpmsg_root
Definition: modules.h:186
Module * findModule(char *name)
Definition: modules.c:473
void moduleDelAllData(ModuleData **md)
Definition: modules.c:2345
#define EVENT_DELCOMMAND
Definition: events.h:72
int moduleDataDebug(ModuleData **md)
Definition: modules.c:2205
#define ano_modclearerr()
Definition: modules.h:43
User * u
Definition: modules.h:168
Module * mod_current_module
Definition: modules.c:52
char ** argv
Definition: modules.h:231
int what
Definition: services.h:835
ModuleCallBack * next
Definition: modules.h:232
ModuleOperation op
Definition: modules.h:167
ModuleOperation
Definition: modules.h:100
void updateProtectDetails(char *level_info_protect_word, char *level_info_protectme_word, char *fant_protect_add, char *fant_protect_del, char *level_protect_word, char *protect_set_mode, char *protect_unset_mode)
Definition: modules.c:2512
char * moduleGetLastBuffer(void)
Definition: modules.c:1988
#define CA_PROTECT
Definition: services.h:777
CommandHash * HOSTSERV[MAX_CMD_HASH]
Definition: modules.c:42
char * name
Definition: modules.h:226
void moduleDelData(ModuleData **md, char *key)
Definition: modules.c:2301
Command * c
Definition: ns_recover.c:17
User * next
Definition: services.h:873
int loadModule(Module *m, User *u)
Definition: modules.c:599
#define MOD_ERR_NOSERVICE
Definition: modules.h:83
char * moduleName
Definition: services.h:479
char * owner_name
Definition: modules.h:227
E void alog(const char *fmt,...) FORMAT(printf
E char * myStrGetOnlyToken(const char *str, const char dilim, int token_number)
Definition: misc.c:685
#define EVENT_ADDCOMMAND
Definition: events.h:71
#define MOD_ERR_OK
Definition: modules.h:71
#define MOD_ERR_NOEXIST
Definition: modules.h:75
int(* oper_help)(User *u)
Definition: modules.h:198
E int ModulesDelayedNumber
Definition: extern.h:480
boolean moduleMinVersion(int major, int minor, int patch, int build)
Definition: modules.c:2465
#define ano_modopen(file)
Definition: modules.h:34
#define MOD_CONT
Definition: modules.h:54
int core
Definition: modules.h:214
int token
Definition: services.h:356
E int UseTS6
Definition: extern.h:364
int addMessage(MessageHash *msgTable[], Message *m, int pos)
Definition: modules.c:1531
Module * m
Definition: modules.h:166
void moduleAddAuthor(const char *author)
Definition: modules.c:1772
char * name
Definition: modules.h:137
E LevelInfo levelinfo[]
Definition: extern.h:169
char * moduleGetLangString(User *u, int number)
Definition: modules.c:2731
char * mod_current_buffer
Definition: modules.c:54
char * mod_name
Definition: modules.h:194
int addCommand(CommandHash *cmdTable[], Command *c, int pos)
Definition: modules.c:1293
int(* has_priv)(User *u)
Definition: modules.h:176
#define CA_AUTOPROTECT
Definition: services.h:772
int queueModuleLoad(char *name, User *u)
Definition: modules.c:2801
E int UseTokens
Definition: extern.h:360
E int debug
Definition: extern.h:775
int delCommand(CommandHash *cmdTable[], Command *c, char *mod_name)
Definition: modules.c:1367
#define EVENT
Definition: modules.h:65
#define MOD_ERR_MEMORY
Definition: modules.h:72
int moduleAddRegHelp(Command *c, int(*func)(User *u))
Definition: modules.c:2050
Module * m
Definition: modules.h:161
char * name
Definition: modules.h:160
E char * s_HostServ
Definition: extern.h:303
E NickAlias * nalists[1024]
Definition: extern.h:923
int tokencaseless
Definition: services.h:357
#define MOD_ERR_NOUNLOAD
Definition: modules.h:78
int helpmsg_reg
Definition: modules.h:183
void moduleInsertLanguage(int langNumber, int ac, char **av)
Definition: modules.c:2650
void moduleDelCallback(char *name)
Definition: modules.c:1927
char * moduleGetData(ModuleData **md, char *key)
Definition: modules.c:2266
Message * findMessage(MessageHash *msgTable[], const char *name)
Definition: modules.c:1494
char * name
Definition: modules.h:206
MODType
Definition: modules.h:99
char * help_param4
Definition: modules.h:190
char * author
Definition: modules.h:142
void ModuleRunTimeDirCleanUp(void)
Definition: modules.c:2880
CommandHash * MEMOSERV[MAX_CMD_HASH]
Definition: modules.c:44
#define ano_modsym(file, symbol)
Definition: modules.h:36
E int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
int moduleAddHelp(Command *c, int(*func)(User *u))
Definition: modules.c:2064
EvtHookHash * next
Definition: modules.h:261
int protocolModuleLoaded()
Definition: modules.c:495
#define ano_modclose(file)
Definition: modules.h:37
CommandHash * OPERSERV[MAX_CMD_HASH]
Definition: modules.c:48
void(* chanHelp)(User *u)
Definition: modules.h:147
#define MODULE_EXT
Definition: modules.h:44
int moduleGetConfigDirective(Directive *d)
Definition: modules.c:2553
MemoInfo memos
Definition: services.h:690
int protocol_module_init(void)
Definition: modules.c:183
struct Directive::@0 params[MAXPARAMS]
void modules_delayed_init(void)
Definition: modules.c:235
E char ** ModulesAutoload
Definition: extern.h:477
#define LANG_EN_US
Definition: services.h:1315
char * name
Definition: services.h:431
User * mod_current_user
Definition: modules.c:55
void moduleSetHostHelp(void(*func)(User *u))
Definition: modules.c:2138
int type
Definition: services.h:433
ModuleData * moduleData
Definition: services.h:894
int addCoreMessage(MessageHash *msgTable[], Message *m)
Definition: modules.c:1597
void moduleSetChanHelp(void(*func)(User *u))
Definition: modules.c:2090
void modules_unload_all(boolean fini, boolean unload_proto)
Definition: modules.c:276
#define EVENT_MODUNLOAD
Definition: events.h:70
Command * findCommand(CommandHash *cmdTable[], const char *name)
Definition: modules.c:1442
#define PARAM_STRING
Definition: services.h:443
Message * m
Definition: modules.h:221
int addCoreCommand(CommandHash *cmdTable[], Command *c)
Definition: modules.c:1063
void moduleDelAllDataMod(Module *m)
Definition: modules.c:2384
int displayCommandFromHash(CommandHash *cmdTable[], char *name)
Definition: modules.c:1201
E NickCore * nclists[1024]
Definition: extern.h:924
void moduleSetNickHelp(void(*func)(User *u))
Definition: modules.c:2078
int ts6
Definition: services.h:366
#define MOD_ERR_UNKNOWN
Definition: modules.h:81
char version[1024]
Definition: version.sh.c:24
time_t when
Definition: modules.h:228
E char * s_ChanServ
Definition: extern.h:285
#define ano_moderr()
Definition: modules.h:35
Memo * memos
Definition: services.h:506
time_t time
Definition: modules.h:140
void moduleCallBackPrepForUnload(char *mod_name)
Definition: modules.c:1968
E char * s_NickServ
Definition: extern.h:284
E User * userlist[1024]
Definition: extern.h:1138
void(* operHelp)(User *u)
Definition: modules.h:150
char * name
Definition: modules.h:212
int delEventHook(EvtHookHash *HookEvtTable[], EvtHook *evh, char *mod_name)
Definition: events.c:686
int(* admin_help)(User *u)
Definition: modules.h:199
ModuleQueue * next
Definition: modules.h:170
EvtMessage * evm
Definition: modules.h:245
CommandHash * CHANSERV[MAX_CMD_HASH]
Definition: modules.c:46
char * key
Definition: services.h:480
#define CMD_HASH(x)
Definition: modules.h:50
long build
Definition: version.sh.c:22
ChannelInfo * next
Definition: services.h:653
Message * createMessage(const char *name, int(*func)(char *source, int ac, char **av))
Definition: modules.c:1470
void moduleSetMemoHelp(void(*func)(User *u))
Definition: modules.c:2102
E char * Numeric
Definition: extern.h:362
char * bsname
Definition: services.h:827
int encryptionModuleLoaded()
Definition: modules.c:514
MODType type
Definition: modules.h:144
#define BUFSIZE
Definition: config.h:47
void(* nickHelp)(User *u)
Definition: modules.h:146
E char * normalizeBuffer(char *)
Definition: botserv.c:1101
int moduleAddData(ModuleData **md, char *key, char *value)
Definition: modules.c:2225
int helpmsg_admin
Definition: modules.h:185
NickAlias * na
Definition: services.h:892
void handleModuleOperationQueue(void)
Definition: modules.c:2840
E void anope_cmd_global(char *source, const char *fmt,...)
Definition: ircd.c:506
E CSModeUtil csmodeutils[]
Definition: extern.h:168
char * mod_current_module_name
Definition: modules.c:53
void queueModuleOperation(Module *m, ModuleOperation op, User *u)
Definition: modules.c:2783
Message * next
Definition: modules.h:216