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