]> jfr.im git - irc/quakenet/newserv.git/blob - control/control.c
NICK: Add "away" functionality.
[irc/quakenet/newserv.git] / control / control.c
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"
22 #include "../lib/version.h"
23 #include "../lib/irc_string.h"
24 #include "control.h"
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29
30 MODULE_VERSION("");
31
32 nick *hooknick;
33
34 nick *mynick;
35
36 CommandTree *controlcmds;
37 ControlMsg controlreply;
38 ControlWall controlwall;
39 ControlPermitted controlpermitted;
40 DestroyExt controldestroyext;
41
42 void controldestroycmdext(void *ext);
43 void handlemessages(nick *target, int messagetype, void **args);
44 int controlstatus(void *sender, int cargc, char **cargv);
45 void controlconnect(void *arg);
46 int controlwhois(void *sender, int cargc, char **cargv);
47 int controlchannel(void *sender, int cargc, char **cargv);
48 int relink(void *sender, int cargc, char **cargv);
49 int die(void *sender, int cargc, char **cargv);
50 int controlinsmod(void *sender, int cargc, char **cargv);
51 int controllsmod(void *sender, int cargc, char **cargv);
52 int controlrehash(void *sender, int cargc, char **cargv);
53 int controlreload(void *sender, int cargc, char **cargv);
54 int controlhelpcmd(void *sender, int cargc, char **cargv);
55 void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...) __attribute__ ((format (printf, 3, 4)));
56 void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...);
57 int controlcheckpermitted(flag_t level, nick *user);
58 void handlesignal(int hooknum, void *arg);
59
60 void _init() {
61 controlcmds=newcommandtree();
62 controlreply=&controlmessage;
63 controlwall=&controlnoticeopers;
64 controlpermitted=&controlcheckpermitted;
65 controldestroyext=&controldestroycmdext;
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.");
74 registercontrolhelpcmd("lsmod",NO_OPER,0,&controllsmod,"Usage: lsmod\nLists currently running modules.");
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.");
79
80 registerhook(HOOK_CORE_REHASH, &handlesignal);
81 registerhook(HOOK_CORE_SIGINT, &handlesignal);
82 scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
83 }
84
85 void _fini() {
86 deleteallschedules(&controlconnect);
87 if (mynick) {
88 deregisterlocaluser(mynick,"Leaving");
89 }
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);
105
106 deregisterhook(HOOK_CORE_REHASH, &handlesignal);
107 deregisterhook(HOOK_CORE_SIGINT, &handlesignal);
108 }
109
110 void 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
137 void 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;
153 }
154
155
156 int deregistercontrolcmd(const char *name, CommandHandler handler) {
157 return deletecommandfromtree(controlcmds, name, handler);
158 }
159
160 void 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
170 mynick=registerlocaluser(cnick->content,myident->content,myhost->content,myrealname->content,myauthname->content,UMODE_SERVICE|UMODE_DEAF|UMODE_OPER|UMODE_ACCOUNT|UMODE_INV,&handlemessages);
171 triggerhook(HOOK_CONTROL_REGISTERED, mynick);
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
187 void handlestats(int hooknum, void *arg) {
188 controlreply(hooknick,"%s",(char *)arg);
189 }
190
191 int controlstatus(void *sender, int cargc, char **cargv) {
192 unsigned long level=999;
193 hooknick=(nick *)sender;
194
195 if (cargc>0) {
196 level=strtoul(cargv[0],NULL,10);
197 }
198
199 registerhook(HOOK_CORE_STATSREPLY,&handlestats);
200
201 triggerhook(HOOK_CORE_STATSREQUEST,(void *)level);
202 deregisterhook(HOOK_CORE_STATSREPLY,&handlestats);
203 return CMD_OK;
204 }
205
206 int 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 }
215
216 void handlewhois(int hooknum, void *arg) {
217 controlreply(hooknick,"%s",(char *)arg);
218 }
219
220 int controlwhois(void *sender, int cargc, char **cargv) {
221 nick *target;
222 channel **channels;
223 char buf[BUFSIZE];
224 int i;
225
226 if (cargc<1)
227 return CMD_USAGE;
228
229 if (cargv[0][0]=='#') {
230 if (!(target=getnickbynumericstr(cargv[0]+1))) {
231 controlreply(sender,"Sorry, couldn't find numeric %s",cargv[0]+1);
232 return CMD_ERROR;
233 }
234 } else {
235 if ((target=getnickbynick(cargv[0]))==NULL) {
236 controlreply((nick *)sender,"Sorry, couldn't find that user");
237 return CMD_ERROR;
238 }
239 }
240
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);
244 if (IsSetHost(target)) {
245 if (target->shident) {
246 controlreply((nick *)sender,"Fakehost : %s@%s",target->shident->content, target->sethost->content);
247 } else {
248 controlreply((nick *)sender,"Fakehost : %s",target->sethost->content);
249 }
250 }
251 controlreply((nick *)sender,"Timestamp : %lu",target->timestamp);
252 controlreply((nick *)sender,"IP address: %s",IPtostr(target->p_ipaddr));
253 controlreply((nick *)sender,"Realname : %s (%d user(s) have this realname)",target->realname->name->content,target->realname->usercount);
254 if (target->umodes) {
255 controlreply((nick *)sender,"Umode(s) : %s",printflags(target->umodes,umodeflags));
256 }
257 if (IsOper(target) && target->opername)
258 controlreply((nick *)sender,"Opered as : %s",target->opername->content);
259 if (IsAccount(target)) {
260 controlreply((nick *)sender,"Account : %s",target->authname);
261 if (target->accountts)
262 controlreply((nick *)sender,"AccountTS : %ld",target->accountts);
263 if (target->auth) {
264 controlreply((nick *)sender,"UserID : %ld",target->auth->userid);
265 if (target->auth->flags)
266 controlreply((nick *)sender,"AccFlags : %s",printflags(target->auth->flags,accountflags));
267 }
268 }
269
270 if (target->away) {
271 controlreply((nick *)sender, "Away : %s",target->away->content);
272 }
273
274 hooknick=(nick *)sender;
275 registerhook(HOOK_CONTROL_WHOISREPLY,&handlewhois);
276 triggerhook(HOOK_CONTROL_WHOISREQUEST,target);
277 deregisterhook(HOOK_CONTROL_WHOISREPLY,&handlewhois);
278
279 if (target->channels->cursi==0) {
280 controlreply((nick *)sender,"Channels : none");
281 } else if (target->channels->cursi>50) {
282 controlreply((nick *)sender,"Channels : - (total: %d)",target->channels->cursi);
283 } else {
284 buf[0]='\0';
285 channels=(channel **)target->channels->content;
286 for (i=0;i<=target->channels->cursi;i++) {
287 if (!((i==target->channels->cursi) || ((70-strlen(buf))<channels[i]->index->name->length && strlen(buf)>0))) {
288 strcat(buf,channels[i]->index->name->content);
289 strcat(buf," ");
290 } else {
291 if (strlen(buf)==0) {
292 break;
293 } else {
294 controlreply((nick *)sender,"Channels : %s",buf);
295 buf[0]='\0';
296 i--;
297 }
298 }
299 }
300 }
301
302 return CMD_OK;
303 }
304
305 int controlinsmod(void *sender, int cargc, char **cargv) {
306 if (cargc<1)
307 return CMD_USAGE;
308
309 switch(insmod(cargv[0])) {
310 case -1:
311 controlreply((nick *)sender,"Unable to load module %s",cargv[0]);
312 return CMD_ERROR;
313
314 case 1:
315 controlreply((nick *)sender,"Module %s already loaded, or name not valid",cargv[0]);
316 return CMD_ERROR;
317
318 case 0:
319 controlreply((nick *)sender,"Module %s loaded.",cargv[0]);
320 return CMD_OK;
321
322 default:
323 controlreply((nick *)sender,"An unknown error occured.");
324 return CMD_ERROR;
325 }
326 }
327
328 int controlrmmod(void *sender, int cargc, char **cargv) {
329 if (cargc<1)
330 return CMD_USAGE;
331
332 switch(rmmod(cargv[0])) {
333 case 1:
334 controlreply((nick *)sender,"Module %s is not loaded.",cargv[0]);
335 return CMD_ERROR;
336
337 case 0:
338 controlreply((nick *)sender,"Module %s unloaded.",cargv[0]);
339 return CMD_OK;
340
341 default:
342 controlreply((nick *)sender,"An unknown error occured.");
343 return CMD_ERROR;
344 }
345 }
346
347 int controllsmod(void *sender, int cargc, char **cargv) {
348 int i=0;
349 char *ptr;
350
351 if (cargc < 1) { /* list all loaded modules */
352 const char *ver, *buildid;
353 time_t t, t2 = time(NULL);
354 ptr = lsmod(i, &ver, &buildid, &t);
355
356 /* 9999d 24h 59m 59s fbf2a4a69ee1-tip */
357 controlreply((nick *)sender,"Module Loaded for Version Build id");
358 while (ptr != NULL) {
359 controlreply((nick *)sender," %-40s %-17s %-30s %s", ptr, longtoduration(t2-t, 2), ver?ver:"", buildid?buildid:"");
360 ptr = lsmod(++i, &ver, &buildid, &t);
361 }
362 } else {
363 ptr = lsmod(getindex(cargv[0]), NULL, NULL, NULL);
364 controlreply((nick *)sender,"Module \"%s\" %s", cargv[0], (ptr ? "is loaded." : "is NOT loaded."));
365 }
366 return CMD_OK;
367 }
368
369 int controlreload(void *sender, int cargc, char **cargv) {
370 if (cargc<1)
371 return CMD_USAGE;
372
373 controlreply((nick *)sender,"Imma gonna try and reload %s",cargv[0]);
374
375 safereload(cargv[0]);
376
377 return CMD_OK;
378 }
379
380 int relink(void *sender, int cargc, char **cargv) {
381 if (cargc<1) {
382 controlreply((nick *)sender,"You must give a reason.");
383 return CMD_USAGE;
384 }
385
386 irc_send("%s SQ %s 0 :%s",mynumeric->content,myserver->content,cargv[0]);
387 irc_disconnected();
388
389 return CMD_OK;
390 }
391
392 int die(void *sender, int cargc, char **cargv) {
393 if (cargc<1 || (strlen(cargv[0]) < 10)) {
394 controlreply((nick *)sender,"You must give a reason.");
395 return CMD_USAGE;
396 }
397
398 controlwall(NO_OPER,NL_OPERATIONS,"DIE from %s: %s",((nick *)sender)->nick, cargv[0]);
399
400 newserv_shutdown_pending=1;
401
402 return CMD_OK;
403 }
404
405 int controlchannel(void *sender, int cargc, char **cargv) {
406 channel *cp;
407 nick *np;
408 chanban *cbp;
409 char buf[BUFSIZE];
410 char buf2[12];
411 int i,j, ops=0, voice=0;
412 char timebuf[30];
413
414 if (cargc<1)
415 return CMD_USAGE;
416
417 if ((cp=findchannel(cargv[0]))==NULL) {
418 controlreply((nick *)sender,"Couldn't find channel: %s",cargv[0]);
419 return CMD_ERROR;
420 }
421
422 if (IsLimit(cp)) {
423 sprintf(buf2,"%d",cp->limit);
424 }
425
426 controlreply((nick *)sender,"Channel : %s",cp->index->name->content);
427 strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(cp->timestamp)));
428 controlreply((nick *)sender,"C-time : %ld [%s]",cp->timestamp,timebuf);
429 if (cp->topic) {
430 controlreply((nick *)sender,"Topic : %s",cp->topic->content);
431 strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(cp->topictime)));
432 controlreply((nick *)sender,"T-time : %ld [%s]",cp->topictime,timebuf);
433 } else {
434 controlreply((nick *)sender,"Topic : (none)");
435 }
436 controlreply((nick *)sender,"Mode(s) : %s %s%s%s",printflags(cp->flags,cmodeflags),IsLimit(cp)?buf2:"",
437 IsLimit(cp)?" ":"",IsKey(cp)?cp->key->content:"");
438 controlreply((nick *)sender,"Users : %d (hash size %d, utilisation %.1f%%); %d unique hosts",
439 cp->users->totalusers,cp->users->hashsize,((float)(100*cp->users->totalusers)/cp->users->hashsize),
440 countuniquehosts(cp));
441 i=0;
442 memset(buf,' ',90);
443 buf[72]='\0';
444 for (j=0;j<=cp->users->hashsize;j++) {
445 if (i==4 || j==cp->users->hashsize) {
446 if(i>0) {
447 controlreply((nick *)sender,"Users : %s",buf);
448 }
449 i=0;
450 memset(buf,' ',72);
451 if (j==cp->users->hashsize)
452 break;
453 }
454 if (cp->users->content[j]!=nouser) {
455 if (cp->users->content[j]&CUMODE_OP)
456 ops++;
457 else if (cp->users->content[j]&CUMODE_VOICE)
458 voice++;
459 np=getnickbynumeric(cp->users->content[j]);
460 sprintf(&buf[i*18],"%c%c%-15s ",cp->users->content[j]&CUMODE_VOICE?'+':' ',
461 cp->users->content[j]&CUMODE_OP?'@':' ', np?np->nick:"!BUG-NONICK!");
462 i++;
463 if (i<4)
464 buf[i*18]=' ';
465 }
466 }
467 controlreply((nick *)sender, "Users : Opped: %d, Voiced: %d", ops,voice);
468 for (cbp=cp->bans;cbp;cbp=cbp->next) {
469 controlreply((nick *)sender,"Ban : %s",bantostringdebug(cbp));
470 }
471 return CMD_OK;
472 }
473
474 int controlshowcommands(void *sender, int cargc, char **cargv) {
475 nick *np=(nick *)sender;
476 Command *cmdlist[100];
477 int i,n;
478
479 n=getcommandlist(controlcmds,cmdlist,100);
480
481 controlreply(np,"The following commands are registered at present:");
482
483 for(i=0;i<n;i++) {
484 controlreply(np,"%s",cmdlist[i]->command->content);
485 }
486
487 controlreply(np,"End of list.");
488 return CMD_OK;
489 }
490
491 void handlemessages(nick *target, int messagetype, void **args) {
492 Command *cmd;
493 char *cargv[50];
494 int cargc;
495 nick *sender;
496
497 switch(messagetype) {
498 case LU_PRIVMSG:
499 case LU_SECUREMSG:
500 /* If it's a message, first arg is nick and second is message */
501 sender=(nick *)args[0];
502
503 Error("control",ERR_INFO,"From: %s!%s@%s: %s",sender->nick,sender->ident,sender->host->name->content, (char *)args[1]);
504
505 /* Split the line into params */
506 cargc=splitline((char *)args[1],cargv,50,0);
507
508 if (!cargc) {
509 /* Blank line */
510 return;
511 }
512
513 cmd=findcommandintree(controlcmds,cargv[0],1);
514 if (cmd==NULL) {
515 controlreply(sender,"Unknown command.");
516 return;
517 }
518
519 if (cmd->level>0 && !IsOper(sender)) {
520 controlreply(sender,"You need to be opered to use this command.");
521 return;
522 }
523
524 /* If we were doing "authed user tracking" here we'd put a check in for authlevel */
525
526 /* Check the maxargs */
527 if (cmd->maxparams<(cargc-1)) {
528 /* We need to do some rejoining */
529 rejoinline(cargv[cmd->maxparams],cargc-(cmd->maxparams));
530 cargc=(cmd->maxparams)+1;
531 }
532
533 if((cmd->handler)((void *)sender,cargc-1,&(cargv[1])) == CMD_USAGE)
534 controlhelp(sender, cmd);
535 break;
536
537 case LU_KILLED:
538 /* someone killed me? Bastards */
539 scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
540 mynick=NULL;
541 triggerhook(HOOK_CONTROL_REGISTERED, NULL);
542 break;
543
544 default:
545 break;
546 }
547 }
548
549 void controlmessage(nick *target, char *message, ... ) {
550 char buf[512];
551 va_list va;
552
553 if (mynick==NULL) {
554 return;
555 }
556
557 va_start(va,message);
558 vsnprintf(buf,512,message,va);
559 va_end(va);
560
561 sendmessagetouser(mynick,target,"%s",buf);
562 }
563
564 void controlchanmsg(channel *cp, char *message, ...) {
565 char buf[512];
566 va_list va;
567
568 if (mynick==NULL) {
569 return;
570 }
571
572 va_start(va,message);
573 vsnprintf(buf,512,message,va);
574 va_end(va);
575
576 sendmessagetochannel(mynick,cp,"%s",buf);
577 }
578
579 void controlnotice(nick *target, char *message, ... ) {
580 char buf[512];
581 va_list va;
582
583 if (mynick==NULL) {
584 return;
585 }
586
587 va_start(va,message);
588 vsnprintf(buf,512,message,va);
589 va_end(va);
590
591 sendnoticetouser(mynick,target,"%s",buf);
592 }
593
594 void controlspecialrmmod(void *arg) {
595 struct specialsched *a = (struct specialsched *)arg;
596 sstring *froo = a->modulename;
597
598 a->schedule = NULL;
599
600 rmmod(froo->content);
601 freesstring(froo);
602 }
603
604 void controlspecialreloadmod(void *arg) {
605 struct specialsched *a = (struct specialsched *)arg;
606 sstring *froo = a->modulename;
607
608 a->schedule = NULL;
609
610 safereload(froo->content);
611 freesstring(froo);
612 }
613
614 void controlhelp(nick *np, Command *cmd) {
615 char *cp, *sp;
616 char *scp;
617 cmdhelp *help=(cmdhelp *)cmd->ext;
618
619 if (!help) {
620 controlreply(np, "Sorry, no help for this command.");
621 return;
622 }
623 if ( help->helpcmd ) {
624 (help->helpcmd)(np, cmd);
625 } else {
626 scp = help->helpstr;
627 if (!scp) {
628 controlreply(np, "Sorry, no help for this command.");
629 } else {
630 cp = scp;
631 sp = cp;
632 int finished = 0;
633 for(;;cp++) {
634 if(*cp == '\0' || *cp == '\n') {
635 if(*cp == '\0') {
636 finished = 1;
637 } else {
638 *cp = '\0';
639 }
640
641 if(sp != cp)
642 controlreply(np, "%s", sp);
643
644 if(finished)
645 break;
646
647 *cp = '\n';
648
649 sp = cp + 1;
650 }
651 }
652 }
653 }
654 }
655
656 int controlhelpcmd(void *sender, int cargc, char **cargv) {
657 Command *cmd;
658 nick *np = (nick *)sender;
659
660 if (cargc<1)
661 return CMD_USAGE;
662
663 cmd=findcommandintree(controlcmds,cargv[0],1);
664 if (cmd==NULL) {
665 controlreply(np,"Unknown command.");
666 return CMD_ERROR;
667 }
668
669 controlhelp(np, cmd);
670 return CMD_OK;
671 }
672
673 void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...) {
674 int i;
675 nick *np;
676 char broadcast[512];
677 va_list va;
678
679 va_start(va, format);
680 vsnprintf(broadcast, sizeof(broadcast), format, va);
681 va_end(va);
682
683 for(i=0;i<NICKHASHSIZE;i++)
684 for(np=nicktable[i];np;np=np->next)
685 if (IsOper(np))
686 controlnotice(np, "%s", broadcast);
687 }
688
689 void controlnswall(int noticelevel, char *format, ...) {
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 controlwall(NO_OPER, noticelevel, "%s", broadcast);
698 }
699
700 int controlcheckpermitted(flag_t level, nick *user) {
701 return 1;
702 }
703
704 void handlesignal(int hooknum, void *arg) {
705 char *signal, *action;
706
707 if(hooknum == HOOK_CORE_SIGINT) {
708 signal = "INT";
709 action = "terminating";
710 } else {
711 long hupped = (long)arg;
712 if(!hupped)
713 return;
714
715 signal = "HUP";
716 action = "rehashing";
717 }
718
719 controlwall(NO_OPER, NL_OPERATIONS, "SIG%s received, %s...", signal, action);
720 }
721
722 void controldestroycmdext(void *ext) {
723 if ( ((cmdhelp *)ext)->helpstr)
724 free( ((cmdhelp *)ext)->helpstr);
725 free(ext);
726 }
727
728 char *controlid(nick *np) {
729 static char buf[512];
730
731 snprintf(buf, sizeof(buf), "%s!%s@%s/%s", np->nick, np->ident, np->host->name->content, np->authname);
732
733 return buf;
734 }
735