]> jfr.im git - irc/quakenet/newserv.git/blame - control/control.c
Don't unload modules at shutdown when we're running on Valgrind.
[irc/quakenet/newserv.git] / control / control.c
CommitLineData
c86edd1d
Q
1/*
2 * This is the first client module for newserv :)
3 *
4 * A very simple bot which should give people some ideas for how to
5 * implement stuff on this thing
6 */
7
8#include "../irc/irc_config.h"
9#include "../parser/parser.h"
10#include "../localuser/localuser.h"
11#include "../localuser/localuserchannel.h"
12#include "../nick/nick.h"
13#include "../lib/sstring.h"
14#include "../core/config.h"
15#include "../irc/irc.h"
16#include "../lib/splitline.h"
17#include "../channel/channel.h"
18#include "../lib/flags.h"
19#include "../core/schedule.h"
20#include "../lib/base64.h"
21#include "../core/modules.h"
87698d77 22#include "../lib/version.h"
2fb74c5e 23#include "../lib/irc_string.h"
c86edd1d
Q
24#include "control.h"
25
26#include <stdio.h>
27#include <string.h>
28#include <stdarg.h>
29
70b0a4e5 30MODULE_VERSION("");
87698d77 31
38cee035 32nick *hooknick;
c86edd1d 33
38cee035 34nick *mynick;
c86edd1d 35
38cee035
CP
36CommandTree *controlcmds;
37ControlMsg controlreply;
38ControlWall controlwall;
6ebc9d2f
P
39ControlPermitted controlpermitted;
40DestroyExt controldestroyext;
c86edd1d 41
6ebc9d2f 42void controldestroycmdext(void *ext);
c86edd1d
Q
43void handlemessages(nick *target, int messagetype, void **args);
44int controlstatus(void *sender, int cargc, char **cargv);
45void controlconnect(void *arg);
46int controlwhois(void *sender, int cargc, char **cargv);
47int controlchannel(void *sender, int cargc, char **cargv);
48int relink(void *sender, int cargc, char **cargv);
49int die(void *sender, int cargc, char **cargv);
50int controlinsmod(void *sender, int cargc, char **cargv);
1fab6211 51int controllsmod(void *sender, int cargc, char **cargv);
c86edd1d 52int controlrehash(void *sender, int cargc, char **cargv);
c86edd1d 53int controlreload(void *sender, int cargc, char **cargv);
38cee035 54int controlhelpcmd(void *sender, int cargc, char **cargv);
bb4b25ee 55void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...) __attribute__ ((format (printf, 3, 4)));
38cee035 56void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...);
6ebc9d2f 57int controlcheckpermitted(flag_t level, nick *user);
9e8f9fd1 58void handlesignal(int hooknum, void *arg);
c86edd1d
Q
59
60void _init() {
61 controlcmds=newcommandtree();
38cee035
CP
62 controlreply=&controlmessage;
63 controlwall=&controlnoticeopers;
6ebc9d2f
P
64 controlpermitted=&controlcheckpermitted;
65 controldestroyext=&controldestroycmdext;
38cee035
CP
66
67 registercontrolhelpcmd("status",NO_DEVELOPER,1,&controlstatus,"Usage: status ?level?\nDisplays status information, increasing level gives more verbose information.");
68 registercontrolhelpcmd("whois",NO_OPERED,1,&controlwhois,"Usage: whois <nickname|#numeric>\nDisplays lots of information about the specified nickname or numeric.");
69 registercontrolhelpcmd("channel",NO_OPER,1,&controlchannel,"Usage: channel <#channel>\nDisplays channel information.");
70 registercontrolhelpcmd("relink",NO_DEVELOPER,1,&relink,"Usage: relink\nRelinks service to the network.");
71 registercontrolhelpcmd("die",NO_DEVELOPER,1,&die,"Usage: die <reason>\nTerminates the service.");
72 registercontrolhelpcmd("insmod",NO_DEVELOPER,1,&controlinsmod,"Usage: insmod <module>\nAdds a module to the running instance.");
73 registercontrolhelpcmd("rmmod",NO_DEVELOPER,1,&controlrmmod,"Usage: rmmod <module>\nRemoves a module from the running instance.");
007f8c93 74 registercontrolhelpcmd("lsmod",NO_OPER,0,&controllsmod,"Usage: lsmod\nLists currently running modules.");
38cee035
CP
75 registercontrolhelpcmd("rehash",NO_DEVELOPER,1,&controlrehash,"Usage: rehash\nReloads configuration file.");
76 registercontrolhelpcmd("showcommands",NO_ACCOUNT,0,&controlshowcommands,"Usage: showcommands\nShows all registered commands.");
77 registercontrolhelpcmd("reload",NO_DEVELOPER,1,&controlreload,"Usage: reload <module>\nReloads specified module.");
78 registercontrolhelpcmd("help",NO_ANYONE,1,&controlhelpcmd,"Usage: help <command>\nShows help for specified command.");
f69c0032 79
9e8f9fd1
CP
80 registerhook(HOOK_CORE_REHASH, &handlesignal);
81 registerhook(HOOK_CORE_SIGINT, &handlesignal);
c86edd1d
Q
82 scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
83}
84
0f003446 85void _fini() {
a7f301e5 86 deleteallschedules(&controlconnect);
0f003446 87 if (mynick) {
88 deregisterlocaluser(mynick,"Leaving");
89 }
a7f301e5 90
91 deregistercontrolcmd("status",&controlstatus);
92 deregistercontrolcmd("whois",&controlwhois);
93 deregistercontrolcmd("channel",&controlchannel);
94 deregistercontrolcmd("relink",&relink);
95 deregistercontrolcmd("die",&die);
96 deregistercontrolcmd("insmod",&controlinsmod);
97 deregistercontrolcmd("rmmod",&controlrmmod);
98 deregistercontrolcmd("lsmod",&controllsmod);
99 deregistercontrolcmd("rehash",&controlrehash);
100 deregistercontrolcmd("showcommands",&controlshowcommands);
101 deregistercontrolcmd("reload",&controlreload);
102 deregistercontrolcmd("help",&controlhelpcmd);
103
104 destroycommandtree(controlcmds);
f69c0032 105
9e8f9fd1
CP
106 deregisterhook(HOOK_CORE_REHASH, &handlesignal);
107 deregisterhook(HOOK_CORE_SIGINT, &handlesignal);
0f003446 108}
109
6ebc9d2f
P
110void registercontrolhelpcmd(const char *name, int level, int maxparams, CommandHandler handler, char *helpstr) {
111 cmdhelp *help;
112 Command *newcmd;
113
114 newcmd = addcommandtotree(controlcmds,name,level,maxparams,handler);
115
116 if (helpstr) {
117 /* Allocate a help record */
118 help=(cmdhelp *)malloc(sizeof(cmdhelp));
119 if(!help) {
120 Error("control",ERR_ERROR,"Malloc failed: registercontrolhelpcmd");
121 return;
122 }
123 memset((void *)help,0,sizeof(cmdhelp));
124
125 /* this isn't an sstring atm, as sstring has a max length (512) */
126 int len=strlen(helpstr);
127 help->helpstr=(char *)malloc(len+1);
128 if(help->helpstr) {
129 strncpy(help->helpstr, helpstr, len);
130 help->helpstr[len] = '\0';
131 }
132 newcmd->ext=(void *)help;
133 newcmd->destroyext=controldestroyext;
134 }
135}
136
137void registercontrolhelpfunccmd(const char *name, int level, int maxparams, CommandHandler handler, CommandHelp helpcmd) {
138 cmdhelp *help;
139 Command *newcmd;
140
141 /* Allocate a help record */
142 help=(cmdhelp *)malloc(sizeof(cmdhelp));
143 if (!help) {
144 Error("control",ERR_ERROR,"Malloc failed: registercontrolhelpfunccmd");
145 return;
146 }
147 memset((void *)help,0,sizeof(cmdhelp));
148
149 help->helpcmd=helpcmd;
150
151 newcmd = addcommandexttotree(controlcmds,name,level,maxparams,handler, (void *)help);
152 newcmd->destroyext=controldestroyext;
c86edd1d
Q
153}
154
6ebc9d2f 155
c86edd1d
Q
156int deregistercontrolcmd(const char *name, CommandHandler handler) {
157 return deletecommandfromtree(controlcmds, name, handler);
158}
159
160void controlconnect(void *arg) {
161 sstring *cnick, *myident, *myhost, *myrealname, *myauthname;
162 channel *cp;
163
164 cnick=getcopyconfigitem("control","nick","C",NICKLEN);
165 myident=getcopyconfigitem("control","ident","control",NICKLEN);
166 myhost=getcopyconfigitem("control","hostname",myserver->content,HOSTLEN);
167 myrealname=getcopyconfigitem("control","realname","NewServ Control Service",REALLEN);
168 myauthname=getcopyconfigitem("control","authname","C",ACCOUNTLEN);
169
84e923c7 170 mynick=registerlocaluser(cnick->content,myident->content,myhost->content,myrealname->content,myauthname->content,UMODE_SERVICE|UMODE_DEAF|UMODE_OPER|UMODE_ACCOUNT|UMODE_INV,&handlemessages);
38cee035 171 triggerhook(HOOK_CONTROL_REGISTERED, mynick);
c86edd1d
Q
172 cp=findchannel("#twilightzone");
173 if (!cp) {
174 localcreatechannel(mynick,"#twilightzone");
175 } else {
176 localjoinchannel(mynick,cp);
177 localgetops(mynick,cp);
178 }
179
180 freesstring(cnick);
181 freesstring(myident);
182 freesstring(myhost);
183 freesstring(myrealname);
184 freesstring(myauthname);
185}
186
187void handlestats(int hooknum, void *arg) {
38cee035 188 controlreply(hooknick,"%s",(char *)arg);
c86edd1d
Q
189}
190
191int controlstatus(void *sender, int cargc, char **cargv) {
5edf52e3 192 unsigned long level=999;
38cee035 193 hooknick=(nick *)sender;
c86edd1d
Q
194
195 if (cargc>0) {
196 level=strtoul(cargv[0],NULL,10);
197 }
c56c22bc 198
c86edd1d 199 registerhook(HOOK_CORE_STATSREPLY,&handlestats);
c56c22bc 200
c86edd1d
Q
201 triggerhook(HOOK_CORE_STATSREQUEST,(void *)level);
202 deregisterhook(HOOK_CORE_STATSREPLY,&handlestats);
203 return CMD_OK;
204}
205
206int controlrehash(void *sender, int cargc, char **cargv) {
207 nick *np=(nick *)sender;
208
209 controlreply(np,"Rehashing the config file.");
210
211 rehashconfig();
212 triggerhook(HOOK_CORE_REHASH,(void *)0);
213 return CMD_OK;
214}
38cee035
CP
215
216void handlewhois(int hooknum, void *arg) {
217 controlreply(hooknick,"%s",(char *)arg);
218}
219
c86edd1d
Q
220int controlwhois(void *sender, int cargc, char **cargv) {
221 nick *target;
222 channel **channels;
223 char buf[BUFSIZE];
224 int i;
225
38cee035
CP
226 if (cargc<1)
227 return CMD_USAGE;
c86edd1d
Q
228
229 if (cargv[0][0]=='#') {
230 if (!(target=getnickbynumericstr(cargv[0]+1))) {
38cee035 231 controlreply(sender,"Sorry, couldn't find numeric %s",cargv[0]+1);
c86edd1d
Q
232 return CMD_ERROR;
233 }
234 } else {
235 if ((target=getnickbynick(cargv[0]))==NULL) {
38cee035 236 controlreply((nick *)sender,"Sorry, couldn't find that user");
c86edd1d
Q
237 return CMD_ERROR;
238 }
239 }
240
38cee035
CP
241 controlreply((nick *)sender,"Nick : %s",target->nick);
242 controlreply((nick *)sender,"Numeric : %s",longtonumeric(target->numeric,5));
243 controlreply((nick *)sender,"User@Host : %s@%s (%d user(s) on this host)",target->ident,target->host->name->content,target->host->clonecount);
c86edd1d
Q
244 if (IsSetHost(target)) {
245 if (target->shident) {
38cee035 246 controlreply((nick *)sender,"Fakehost : %s@%s",target->shident->content, target->sethost->content);
c86edd1d 247 } else {
38cee035 248 controlreply((nick *)sender,"Fakehost : %s",target->sethost->content);
c86edd1d
Q
249 }
250 }
38cee035 251 controlreply((nick *)sender,"Timestamp : %lu",target->timestamp);
39e9e93e
CP
252
253 /* HACK */
254 {
255 int ext = findnickext("signontracker");
256
257 if(ext >= 0) {
258 time_t signedon = (time_t)(target->exts[ext]);
259 if(signedon) {
260 controlreply((nick *)sender,"Signed on : %lu",signedon);
261 } else {
262 controlreply((nick *)sender,"Signed on : ???");
263 }
264 }
265 }
526e7c1d 266 controlreply((nick *)sender,"IP address: %s",IPtostr(target->p_ipaddr));
38cee035 267 controlreply((nick *)sender,"Realname : %s (%d user(s) have this realname)",target->realname->name->content,target->realname->usercount);
c86edd1d 268 if (target->umodes) {
38cee035 269 controlreply((nick *)sender,"Umode(s) : %s",printflags(target->umodes,umodeflags));
c86edd1d 270 }
843184e3
CP
271 if (IsOper(target) && target->opername)
272 controlreply((nick *)sender,"Opered as : %s",target->opername->content);
c86edd1d 273 if (IsAccount(target)) {
38cee035 274 controlreply((nick *)sender,"Account : %s",target->authname);
c86edd1d 275 if (target->accountts)
38cee035 276 controlreply((nick *)sender,"AccountTS : %ld",target->accountts);
0b0fb773 277 if (target->auth) {
c56c22bc 278 controlreply((nick *)sender,"UserID : %ld",target->auth->userid);
0b0fb773
CP
279 if (target->auth->flags)
280 controlreply((nick *)sender,"AccFlags : %s",printflags(target->auth->flags,accountflags));
281 }
c86edd1d 282 }
38cee035 283
5144ddc4 284 if (target->away) {
285 controlreply((nick *)sender, "Away : %s",target->away->content);
286 }
287
38cee035
CP
288 hooknick=(nick *)sender;
289 registerhook(HOOK_CONTROL_WHOISREPLY,&handlewhois);
290 triggerhook(HOOK_CONTROL_WHOISREQUEST,target);
291 deregisterhook(HOOK_CONTROL_WHOISREPLY,&handlewhois);
292
c86edd1d 293 if (target->channels->cursi==0) {
38cee035 294 controlreply((nick *)sender,"Channels : none");
c86edd1d 295 } else if (target->channels->cursi>50) {
38cee035 296 controlreply((nick *)sender,"Channels : - (total: %d)",target->channels->cursi);
c86edd1d
Q
297 } else {
298 buf[0]='\0';
299 channels=(channel **)target->channels->content;
300 for (i=0;i<=target->channels->cursi;i++) {
301 if (!((i==target->channels->cursi) || ((70-strlen(buf))<channels[i]->index->name->length && strlen(buf)>0))) {
302 strcat(buf,channels[i]->index->name->content);
303 strcat(buf," ");
304 } else {
305 if (strlen(buf)==0) {
306 break;
307 } else {
38cee035 308 controlreply((nick *)sender,"Channels : %s",buf);
c86edd1d
Q
309 buf[0]='\0';
310 i--;
311 }
312 }
313 }
314 }
315
316 return CMD_OK;
317}
318
319int controlinsmod(void *sender, int cargc, char **cargv) {
38cee035
CP
320 if (cargc<1)
321 return CMD_USAGE;
c86edd1d
Q
322
323 switch(insmod(cargv[0])) {
324 case -1:
38cee035 325 controlreply((nick *)sender,"Unable to load module %s",cargv[0]);
c86edd1d
Q
326 return CMD_ERROR;
327
328 case 1:
38cee035 329 controlreply((nick *)sender,"Module %s already loaded, or name not valid",cargv[0]);
c86edd1d
Q
330 return CMD_ERROR;
331
332 case 0:
38cee035 333 controlreply((nick *)sender,"Module %s loaded.",cargv[0]);
c86edd1d
Q
334 return CMD_OK;
335
336 default:
38cee035 337 controlreply((nick *)sender,"An unknown error occured.");
c86edd1d
Q
338 return CMD_ERROR;
339 }
340}
341
342int controlrmmod(void *sender, int cargc, char **cargv) {
38cee035
CP
343 if (cargc<1)
344 return CMD_USAGE;
c86edd1d 345
95ab9d6b 346 switch(rmmod(cargv[0], 1)) {
c86edd1d 347 case 1:
38cee035 348 controlreply((nick *)sender,"Module %s is not loaded.",cargv[0]);
c86edd1d
Q
349 return CMD_ERROR;
350
351 case 0:
38cee035 352 controlreply((nick *)sender,"Module %s unloaded.",cargv[0]);
c86edd1d
Q
353 return CMD_OK;
354
355 default:
38cee035 356 controlreply((nick *)sender,"An unknown error occured.");
c86edd1d
Q
357 return CMD_ERROR;
358 }
359}
360
1fab6211 361int controllsmod(void *sender, int cargc, char **cargv) {
362 int i=0;
363 char *ptr;
364
365 if (cargc < 1) { /* list all loaded modules */
2fb74c5e
CP
366 const char *ver, *buildid;
367 time_t t, t2 = time(NULL);
368 ptr = lsmod(i, &ver, &buildid, &t);
369
370 /* 9999d 24h 59m 59s fbf2a4a69ee1-tip */
c3c955ee 371 controlreply((nick *)sender,"Module Loaded for Version Build id");
1fab6211 372 while (ptr != NULL) {
c3c955ee 373 controlreply((nick *)sender," %-40s %-17s %-30s %s", ptr, longtoduration(t2-t, 2), ver?ver:"", buildid?buildid:"");
2fb74c5e 374 ptr = lsmod(++i, &ver, &buildid, &t);
1fab6211 375 }
376 } else {
2fb74c5e 377 ptr = lsmod(getindex(cargv[0]), NULL, NULL, NULL);
38cee035 378 controlreply((nick *)sender,"Module \"%s\" %s", cargv[0], (ptr ? "is loaded." : "is NOT loaded."));
1fab6211 379 }
380 return CMD_OK;
381}
382
c86edd1d 383int controlreload(void *sender, int cargc, char **cargv) {
38cee035
CP
384 if (cargc<1)
385 return CMD_USAGE;
65f2c6a3 386
387 controlreply((nick *)sender,"Imma gonna try and reload %s",cargv[0]);
3fa581ac 388
65f2c6a3 389 safereload(cargv[0]);
3fa581ac 390
391 return CMD_OK;
65f2c6a3 392}
c86edd1d
Q
393
394int relink(void *sender, int cargc, char **cargv) {
395 if (cargc<1) {
38cee035
CP
396 controlreply((nick *)sender,"You must give a reason.");
397 return CMD_USAGE;
c86edd1d
Q
398 }
399
400 irc_send("%s SQ %s 0 :%s",mynumeric->content,myserver->content,cargv[0]);
401 irc_disconnected();
402
403 return CMD_OK;
404}
405
406int die(void *sender, int cargc, char **cargv) {
33f134c9 407 if (cargc<1 || (strlen(cargv[0]) < 10)) {
38cee035
CP
408 controlreply((nick *)sender,"You must give a reason.");
409 return CMD_USAGE;
c86edd1d 410 }
83951d54 411
bec7f5c6 412 controlwall(NO_OPER,NL_OPERATIONS,"DIE from %s: %s",((nick *)sender)->nick, cargv[0]);
c86edd1d 413
83951d54 414 newserv_shutdown_pending=1;
c86edd1d 415
83951d54 416 return CMD_OK;
c86edd1d
Q
417}
418
419int controlchannel(void *sender, int cargc, char **cargv) {
420 channel *cp;
421 nick *np;
422 chanban *cbp;
423 char buf[BUFSIZE];
424 char buf2[12];
c6aa54dd 425 int i,j, ops=0, voice=0;
08454d38
P
426 char timebuf[30];
427
38cee035
CP
428 if (cargc<1)
429 return CMD_USAGE;
c86edd1d
Q
430
431 if ((cp=findchannel(cargv[0]))==NULL) {
38cee035 432 controlreply((nick *)sender,"Couldn't find channel: %s",cargv[0]);
c86edd1d
Q
433 return CMD_ERROR;
434 }
435
436 if (IsLimit(cp)) {
437 sprintf(buf2,"%d",cp->limit);
438 }
439
38cee035 440 controlreply((nick *)sender,"Channel : %s",cp->index->name->content);
08454d38
P
441 strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(cp->timestamp)));
442 controlreply((nick *)sender,"C-time : %ld [%s]",cp->timestamp,timebuf);
c86edd1d 443 if (cp->topic) {
38cee035 444 controlreply((nick *)sender,"Topic : %s",cp->topic->content);
08454d38
P
445 strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(cp->topictime)));
446 controlreply((nick *)sender,"T-time : %ld [%s]",cp->topictime,timebuf);
c6aa54dd
P
447 } else {
448 controlreply((nick *)sender,"Topic : (none)");
c86edd1d 449 }
38cee035 450 controlreply((nick *)sender,"Mode(s) : %s %s%s%s",printflags(cp->flags,cmodeflags),IsLimit(cp)?buf2:"",
c86edd1d 451 IsLimit(cp)?" ":"",IsKey(cp)?cp->key->content:"");
38cee035 452 controlreply((nick *)sender,"Users : %d (hash size %d, utilisation %.1f%%); %d unique hosts",
c86edd1d
Q
453 cp->users->totalusers,cp->users->hashsize,((float)(100*cp->users->totalusers)/cp->users->hashsize),
454 countuniquehosts(cp));
455 i=0;
456 memset(buf,' ',90);
457 buf[72]='\0';
458 for (j=0;j<=cp->users->hashsize;j++) {
459 if (i==4 || j==cp->users->hashsize) {
460 if(i>0) {
38cee035 461 controlreply((nick *)sender,"Users : %s",buf);
c86edd1d
Q
462 }
463 i=0;
464 memset(buf,' ',72);
465 if (j==cp->users->hashsize)
466 break;
467 }
468 if (cp->users->content[j]!=nouser) {
f6698909 469 if (cp->users->content[j]&CUMODE_OP)
c6aa54dd 470 ops++;
f6698909
P
471 else if (cp->users->content[j]&CUMODE_VOICE)
472 voice++;
c86edd1d
Q
473 np=getnickbynumeric(cp->users->content[j]);
474 sprintf(&buf[i*18],"%c%c%-15s ",cp->users->content[j]&CUMODE_VOICE?'+':' ',
475 cp->users->content[j]&CUMODE_OP?'@':' ', np?np->nick:"!BUG-NONICK!");
476 i++;
477 if (i<4)
478 buf[i*18]=' ';
479 }
480 }
c6aa54dd 481 controlreply((nick *)sender, "Users : Opped: %d, Voiced: %d", ops,voice);
c86edd1d 482 for (cbp=cp->bans;cbp;cbp=cbp->next) {
38cee035 483 controlreply((nick *)sender,"Ban : %s",bantostringdebug(cbp));
c86edd1d
Q
484 }
485 return CMD_OK;
486}
487
488int controlshowcommands(void *sender, int cargc, char **cargv) {
489 nick *np=(nick *)sender;
490 Command *cmdlist[100];
491 int i,n;
492
493 n=getcommandlist(controlcmds,cmdlist,100);
494
495 controlreply(np,"The following commands are registered at present:");
496
497 for(i=0;i<n;i++) {
38cee035 498 controlreply(np,"%s",cmdlist[i]->command->content);
c86edd1d
Q
499 }
500
501 controlreply(np,"End of list.");
502 return CMD_OK;
503}
504
505void handlemessages(nick *target, int messagetype, void **args) {
506 Command *cmd;
507 char *cargv[50];
508 int cargc;
509 nick *sender;
510
511 switch(messagetype) {
512 case LU_PRIVMSG:
513 case LU_SECUREMSG:
514 /* If it's a message, first arg is nick and second is message */
515 sender=(nick *)args[0];
516
517 Error("control",ERR_INFO,"From: %s!%s@%s: %s",sender->nick,sender->ident,sender->host->name->content, (char *)args[1]);
518
519 /* Split the line into params */
520 cargc=splitline((char *)args[1],cargv,50,0);
521
522 if (!cargc) {
523 /* Blank line */
524 return;
525 }
526
527 cmd=findcommandintree(controlcmds,cargv[0],1);
528 if (cmd==NULL) {
38cee035 529 controlreply(sender,"Unknown command.");
c86edd1d
Q
530 return;
531 }
532
38cee035
CP
533 if (cmd->level>0 && !IsOper(sender)) {
534 controlreply(sender,"You need to be opered to use this command.");
c86edd1d
Q
535 return;
536 }
537
538 /* If we were doing "authed user tracking" here we'd put a check in for authlevel */
539
540 /* Check the maxargs */
541 if (cmd->maxparams<(cargc-1)) {
542 /* We need to do some rejoining */
543 rejoinline(cargv[cmd->maxparams],cargc-(cmd->maxparams));
544 cargc=(cmd->maxparams)+1;
545 }
546
38cee035
CP
547 if((cmd->handler)((void *)sender,cargc-1,&(cargv[1])) == CMD_USAGE)
548 controlhelp(sender, cmd);
c86edd1d
Q
549 break;
550
551 case LU_KILLED:
552 /* someone killed me? Bastards */
553 scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
554 mynick=NULL;
4c551b15 555 triggerhook(HOOK_CONTROL_REGISTERED, NULL);
c86edd1d
Q
556 break;
557
558 default:
559 break;
560 }
561}
562
38cee035 563void controlmessage(nick *target, char *message, ... ) {
c86edd1d
Q
564 char buf[512];
565 va_list va;
566
567 if (mynick==NULL) {
568 return;
569 }
570
571 va_start(va,message);
572 vsnprintf(buf,512,message,va);
573 va_end(va);
574
575 sendmessagetouser(mynick,target,"%s",buf);
576}
577
578void controlchanmsg(channel *cp, char *message, ...) {
579 char buf[512];
580 va_list va;
581
582 if (mynick==NULL) {
583 return;
584 }
585
586 va_start(va,message);
587 vsnprintf(buf,512,message,va);
588 va_end(va);
589
590 sendmessagetochannel(mynick,cp,"%s",buf);
591}
592
593void controlnotice(nick *target, char *message, ... ) {
594 char buf[512];
595 va_list va;
596
597 if (mynick==NULL) {
598 return;
599 }
600
601 va_start(va,message);
602 vsnprintf(buf,512,message,va);
603 va_end(va);
604
605 sendnoticetouser(mynick,target,"%s",buf);
606}
607
38cee035
CP
608void controlspecialrmmod(void *arg) {
609 struct specialsched *a = (struct specialsched *)arg;
a8d791b4 610 sstring *froo = a->modulename;
b015c3e9 611
38cee035 612 a->schedule = NULL;
38cee035 613
95ab9d6b 614 rmmod(froo->content, 1);
38cee035
CP
615 freesstring(froo);
616}
617
618void controlspecialreloadmod(void *arg) {
619 struct specialsched *a = (struct specialsched *)arg;
a8d791b4 620 sstring *froo = a->modulename;
38cee035
CP
621
622 a->schedule = NULL;
38cee035 623
65f2c6a3 624 safereload(froo->content);
38cee035
CP
625 freesstring(froo);
626}
627
628void controlhelp(nick *np, Command *cmd) {
6ebc9d2f
P
629 char *cp, *sp;
630 char *scp;
631 cmdhelp *help=(cmdhelp *)cmd->ext;
632
633 if (!help) {
38cee035 634 controlreply(np, "Sorry, no help for this command.");
6ebc9d2f
P
635 return;
636 }
637 if ( help->helpcmd ) {
638 (help->helpcmd)(np, cmd);
38cee035 639 } else {
6ebc9d2f
P
640 scp = help->helpstr;
641 if (!scp) {
642 controlreply(np, "Sorry, no help for this command.");
643 } else {
644 cp = scp;
645 sp = cp;
646 int finished = 0;
647 for(;;cp++) {
648 if(*cp == '\0' || *cp == '\n') {
649 if(*cp == '\0') {
650 finished = 1;
651 } else {
652 *cp = '\0';
653 }
654
655 if(sp != cp)
656 controlreply(np, "%s", sp);
657
658 if(finished)
659 break;
660
661 *cp = '\n';
662
663 sp = cp + 1;
38cee035 664 }
38cee035
CP
665 }
666 }
667 }
668}
b015c3e9 669
38cee035
CP
670int controlhelpcmd(void *sender, int cargc, char **cargv) {
671 Command *cmd;
672 nick *np = (nick *)sender;
673
674 if (cargc<1)
675 return CMD_USAGE;
676
677 cmd=findcommandintree(controlcmds,cargv[0],1);
678 if (cmd==NULL) {
679 controlreply(np,"Unknown command.");
680 return CMD_ERROR;
681 }
682
683 controlhelp(np, cmd);
684 return CMD_OK;
b015c3e9 685}
a80cbef6
CP
686
687void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...) {
688 int i;
689 nick *np;
690 char broadcast[512];
691 va_list va;
692
693 va_start(va, format);
694 vsnprintf(broadcast, sizeof(broadcast), format, va);
695 va_end(va);
696
697 for(i=0;i<NICKHASHSIZE;i++)
698 for(np=nicktable[i];np;np=np->next)
699 if (IsOper(np))
700 controlnotice(np, "%s", broadcast);
701}
271ef2d2 702
0a659cde
CP
703void controlnswall(int noticelevel, char *format, ...) {
704 char broadcast[512];
705 va_list va;
706
707 va_start(va, format);
708 vsnprintf(broadcast, sizeof(broadcast), format, va);
709 va_end(va);
710
711 controlwall(NO_OPER, noticelevel, "%s", broadcast);
712}
713
6ebc9d2f
P
714int controlcheckpermitted(flag_t level, nick *user) {
715 return 1;
716}
717
9e8f9fd1 718void handlesignal(int hooknum, void *arg) {
efa44d15
CP
719 char *signal, *action;
720
721 if(hooknum == HOOK_CORE_SIGINT) {
722 signal = "INT";
723 action = "terminating";
724 } else {
725 long hupped = (long)arg;
726 if(!hupped)
727 return;
f69c0032 728
efa44d15
CP
729 signal = "HUP";
730 action = "rehashing";
731 }
732
733 controlwall(NO_OPER, NL_OPERATIONS, "SIG%s received, %s...", signal, action);
734}
dd35c00e 735
6ebc9d2f
P
736void controldestroycmdext(void *ext) {
737 if ( ((cmdhelp *)ext)->helpstr)
738 free( ((cmdhelp *)ext)->helpstr);
739 free(ext);
740}
c6b287fd
CP
741
742char *controlid(nick *np) {
743 static char buf[512];
744
745 snprintf(buf, sizeof(buf), "%s!%s@%s/%s", np->nick, np->ident, np->host->name->content, np->authname);
746
747 return buf;
748}
749