2 * This is the first client module for newserv :)
4 * A very simple bot which should give people some ideas for how to
5 * implement stuff on this thing
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"
25 #include "control_policy.h"
37 CommandTree
*controlcmds
;
38 DestroyExt controldestroyext
;
41 const flag no_commandflags
[] = {
46 { 'd', __NO_DEVELOPER
},
50 { 'R', __NO_ACCOUNT
},
55 const flag no_userflags
[] = {
60 { 'd', __NO_DEVELOPER
},
65 const flag no_noticeflags
[] = {
66 { 'm', NL_MANAGEMENT
}, /* hello, password, userflags, noticeflags */
67 { 't', NL_TRUSTS
}, /* trust stuff... */
68 { 'k', NL_KICKKILLS
}, /* KICK/KILL commands */
69 { 'I', NL_MISC
}, /* misc commands */
70 { 'g', NL_GLINES
}, /* GLINE commands */
71 { 'G', NL_GLINES_AUTO
}, /* automated gline messages */
72 { 'h', NL_HITS
}, /* Where a gline or kill is set automatically by the bot */
73 { 'c', NL_CLONING
}, /* Clone detection */
74 { 'C', NL_CLEARCHAN
}, /* When someone clearchans */
75 { 'f', NL_FAKEUSERS
}, /* Fakeuser addition */
76 { 'b', NL_BROADCASTS
}, /* Broadcast/mbroadcast/sbroadcast */
77 { 'o', NL_OPERATIONS
}, /* insmod/rmmod/etc */
78 { 'O', NL_OPERING
}, /* when someone opers */
79 { 'n', NL_NOTICES
}, /* turn off to receive notices instead of privmsgs */
80 { 'A', NL_ALL_COMMANDS
}, /* all commands sent */
81 { 'a', NL_CLEANUP
}, /* automated cleanup notices */
85 void controldestroycmdext(void *ext
);
86 void handlemessages(nick
*target
, int messagetype
, void **args
);
87 int controlstatus(void *sender
, int cargc
, char **cargv
);
88 void controlconnect(void *arg
);
89 int controlwhois(void *sender
, int cargc
, char **cargv
);
90 int controllistusers(void *sender
, int cargc
, char **cargv
);
91 int controlchannel(void *sender
, int cargc
, char **cargv
);
92 int relink(void *sender
, int cargc
, char **cargv
);
93 int die(void *sender
, int cargc
, char **cargv
);
94 int controlinsmod(void *sender
, int cargc
, char **cargv
);
95 int controllsmod(void *sender
, int cargc
, char **cargv
);
96 int controlrehash(void *sender
, int cargc
, char **cargv
);
97 int controlreload(void *sender
, int cargc
, char **cargv
);
98 int controlhelpcmd(void *sender
, int cargc
, char **cargv
);
99 void controlnoticeopers(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...) __attribute__ ((format (printf
, 3, 4)));
100 void controlnoticeopers(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...);
101 int controlcheckpermitted(flag_t level
, nick
*user
);
102 void handlesignal(int hooknum
, void *arg
);
103 void noperserv_oper_detection(int hooknum
, void *arg
);
104 void noperserv_whois_handler(int hooknum
, void *arg
);
105 void noperserv_whois_account_handler(int hooknum
, void *arg
);
107 #define HOOK_CONTROL_WHOISREQUEST_AUTHNAME -1
108 #define HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER -2
113 if(!noperserv_load_db())
116 controlcmds
=newcommandtree();
117 controldestroyext
=&controldestroycmdext
;
119 registercontrolhelpcmd("status",NO_DEVELOPER
,1,&controlstatus
,"Usage: status ?level?\nDisplays status information, increasing level gives more verbose information.");
120 registercontrolhelpcmd("whois",NO_OPERED
,1,&controlwhois
,"Usage: whois <nickname|#numeric>\nDisplays lots of information about the specified nickname or numeric.");
121 registercontrolhelpcmd("listusers", NO_OPERED
| NO_ACCOUNT
, 2, &controllistusers
, "Syntax: LISTUSERS\nLists all accounts.");
122 registercontrolhelpcmd("channel",NO_OPER
,1,&controlchannel
,"Usage: channel <#channel>\nDisplays channel information.");
123 registercontrolhelpcmd("relink",NO_DEVELOPER
,1,&relink
,"Usage: relink\nRelinks service to the network.");
124 registercontrolhelpcmd("die",NO_DEVELOPER
,1,&die
,"Usage: die <reason>\nTerminates the service.");
125 registercontrolhelpcmd("insmod",NO_DEVELOPER
,1,&controlinsmod
,"Usage: insmod <module>\nAdds a module to the running instance.");
126 registercontrolhelpcmd("rmmod",NO_DEVELOPER
,1,&controlrmmod
,"Usage: rmmod <module>\nRemoves a module from the running instance.");
127 registercontrolhelpcmd("lsmod",NO_OPER
,0,&controllsmod
,"Usage: lsmod\nLists currently running modules.");
128 registercontrolhelpcmd("rehash",NO_DEVELOPER
,1,&controlrehash
,"Usage: rehash\nReloads configuration file.");
129 registercontrolhelpcmd("showcommands",NO_ACCOUNT
,0,&controlshowcommands
,"Usage: showcommands\nShows all registered commands.");
130 registercontrolhelpcmd("reload",NO_DEVELOPER
,1,&controlreload
,"Usage: reload <module>\nReloads specified module.");
131 registercontrolhelpcmd("help",NO_ANYONE
,1,&controlhelpcmd
,"Usage: help <command>\nShows help for specified command.");
133 registerhook(HOOK_CORE_REHASH
, &handlesignal
);
134 registerhook(HOOK_CORE_SIGINT
, &handlesignal
);
135 registerhook(HOOK_NICK_MODEOPER
, &noperserv_oper_detection
);
136 registerhook(HOOK_CONTROL_WHOISREQUEST
, &noperserv_whois_handler
);
138 noperserv_ext
= registerauthnameext("noperserv", 1);
140 scheduleoneshot(time(NULL
)+1,&controlconnect
,NULL
);
149 deleteallschedules(&controlconnect
);
151 deregisterlocaluser(mynick
,"Leaving");
154 deregistercontrolcmd("status",&controlstatus
);
155 deregistercontrolcmd("whois",&controlwhois
);
156 deregistercontrolcmd("listusers", &controllistusers
);
157 deregistercontrolcmd("channel",&controlchannel
);
158 deregistercontrolcmd("relink",&relink
);
159 deregistercontrolcmd("die",&die
);
160 deregistercontrolcmd("insmod",&controlinsmod
);
161 deregistercontrolcmd("rmmod",&controlrmmod
);
162 deregistercontrolcmd("lsmod",&controllsmod
);
163 deregistercontrolcmd("rehash",&controlrehash
);
164 deregistercontrolcmd("showcommands",&controlshowcommands
);
165 deregistercontrolcmd("reload",&controlreload
);
166 deregistercontrolcmd("help",&controlhelpcmd
);
168 destroycommandtree(controlcmds
);
170 deregisterhook(HOOK_CORE_REHASH
, &handlesignal
);
171 deregisterhook(HOOK_CORE_SIGINT
, &handlesignal
);
172 deregisterhook(HOOK_NICK_MODEOPER
, &noperserv_oper_detection
);
173 deregisterhook(HOOK_CONTROL_WHOISREQUEST
, &noperserv_whois_handler
);
175 releaseauthnameext(noperserv_ext
);
177 noperserv_cleanup_db();
180 void registercontrolhelpcmd(const char *name
, int level
, int maxparams
, CommandHandler handler
, char *helpstr
) {
184 newcmd
= addcommandtotree(controlcmds
,name
,level
,maxparams
,handler
);
187 /* Allocate a help record */
188 help
=(cmdhelp
*)malloc(sizeof(cmdhelp
));
190 Error("control",ERR_ERROR
,"Malloc failed: registercontrolhelpcmd");
193 memset((void *)help
,0,sizeof(cmdhelp
));
195 /* this isn't an sstring atm, as sstring has a max length (512) */
196 int len
=strlen(helpstr
);
197 help
->helpstr
=(char *)malloc(len
+1);
199 strncpy(help
->helpstr
, helpstr
, len
);
200 help
->helpstr
[len
] = '\0';
202 newcmd
->ext
=(void *)help
;
203 newcmd
->destroyext
=controldestroyext
;
207 void registercontrolhelpfunccmd(const char *name
, int level
, int maxparams
, CommandHandler handler
, CommandHelp helpcmd
) {
211 /* Allocate a help record */
212 help
=(cmdhelp
*)malloc(sizeof(cmdhelp
));
214 Error("control",ERR_ERROR
,"Malloc failed: registercontrolhelpfunccmd");
217 memset((void *)help
,0,sizeof(cmdhelp
));
219 help
->helpcmd
=helpcmd
;
221 newcmd
= addcommandexttotree(controlcmds
,name
,level
,maxparams
,handler
, (void *)help
);
222 newcmd
->destroyext
=controldestroyext
;
226 int deregistercontrolcmd(const char *name
, CommandHandler handler
) {
227 return deletecommandfromtree(controlcmds
, name
, handler
);
230 void controlconnect(void *arg
) {
231 sstring
*cnick
, *myident
, *myhost
, *myrealname
, *myauthname
;
234 cnick
=getcopyconfigitem("control","nick","C",NICKLEN
);
235 myident
=getcopyconfigitem("control","ident","control",NICKLEN
);
236 myhost
=getcopyconfigitem("control","hostname",myserver
->content
,HOSTLEN
);
237 myrealname
=getcopyconfigitem("control","realname","NewServ Control Service",REALLEN
);
238 myauthname
=getcopyconfigitem("control","authname","C",ACCOUNTLEN
);
240 mynick
=registerlocaluser(cnick
->content
,myident
->content
,myhost
->content
,myrealname
->content
,myauthname
->content
,UMODE_SERVICE
|UMODE_DEAF
|UMODE_OPER
|UMODE_ACCOUNT
|UMODE_INV
,&handlemessages
);
241 triggerhook(HOOK_CONTROL_REGISTERED
, mynick
);
242 cp
=findchannel("#twilightzone");
244 localcreatechannel(mynick
,"#twilightzone");
246 localjoinchannel(mynick
,cp
);
247 localgetops(mynick
,cp
);
251 freesstring(myident
);
253 freesstring(myrealname
);
254 freesstring(myauthname
);
257 void handlestats(int hooknum
, void *arg
) {
258 controlreply(hooknick
,"%s",(char *)arg
);
261 int controlstatus(void *sender
, int cargc
, char **cargv
) {
262 unsigned long level
=999;
263 hooknick
=(nick
*)sender
;
266 level
=strtoul(cargv
[0],NULL
,10);
269 registerhook(HOOK_CORE_STATSREPLY
,&handlestats
);
271 triggerhook(HOOK_CORE_STATSREQUEST
,(void *)level
);
272 deregisterhook(HOOK_CORE_STATSREPLY
,&handlestats
);
276 int controlrehash(void *sender
, int cargc
, char **cargv
) {
277 nick
*np
=(nick
*)sender
;
279 controlreply(np
,"Rehashing the config file.");
282 triggerhook(HOOK_CORE_REHASH
,(void *)0);
286 void handlewhois(int hooknum
, void *arg
) {
287 controlreply(hooknick
,"%s",(char *)arg
);
290 static int controlwhois_plain(void *sender
, int cargc
, char **cargv
) {
299 if (cargv
[0][0]=='#') {
300 if (!(target
=getnickbynumericstr(cargv
[0]+1))) {
301 controlreply(sender
,"Sorry, couldn't find numeric %s",cargv
[0]+1);
305 if ((target
=getnickbynick(cargv
[0]))==NULL
) {
306 controlreply((nick
*)sender
,"Sorry, couldn't find that user");
311 controlreply((nick
*)sender
,"Nick : %s",target
->nick
);
312 controlreply((nick
*)sender
,"Numeric : %s",longtonumeric(target
->numeric
,5));
313 controlreply((nick
*)sender
,"User@Host : %s@%s (%d user(s) on this host)",target
->ident
,target
->host
->name
->content
,target
->host
->clonecount
);
314 if (IsSetHost(target
)) {
315 if (target
->shident
) {
316 controlreply((nick
*)sender
,"Fakehost : %s@%s",target
->shident
->content
, target
->sethost
->content
);
318 controlreply((nick
*)sender
,"Fakehost : %s",target
->sethost
->content
);
321 controlreply((nick
*)sender
,"Timestamp : %lu",target
->timestamp
);
325 int ext
= findnickext("signontracker");
328 time_t signedon
= (time_t)(target
->exts
[ext
]);
330 controlreply((nick
*)sender
,"Signed on : %lu",signedon
);
332 controlreply((nick
*)sender
,"Signed on : ???");
336 controlreply((nick
*)sender
,"IP address: %s",IPtostr(target
->ipaddress
));
337 controlreply((nick
*)sender
,"Realname : %s (%d user(s) have this realname)",target
->realname
->name
->content
,target
->realname
->usercount
);
338 if (target
->umodes
) {
339 controlreply((nick
*)sender
,"Umode(s) : %s",printflags(target
->umodes
,umodeflags
));
341 if (IsOper(target
) && target
->opername
)
342 controlreply((nick
*)sender
,"Opered as : %s",target
->opername
->content
);
343 if (IsAccount(target
)) {
344 controlreply((nick
*)sender
,"Account : %s",target
->authname
);
345 if (target
->accountts
)
346 controlreply((nick
*)sender
,"AccountTS : %ld",target
->accountts
);
348 controlreply((nick
*)sender
,"UserID : %ld",target
->auth
->userid
);
349 if (target
->auth
->flags
)
350 controlreply((nick
*)sender
,"AccFlags : %s",printflags(target
->auth
->flags
,accountflags
));
355 controlreply((nick
*)sender
, "Away : %s",target
->away
->content
);
358 hooknick
=(nick
*)sender
;
359 registerhook(HOOK_CONTROL_WHOISREPLY
,&handlewhois
);
360 triggerhook(HOOK_CONTROL_WHOISREQUEST
,target
);
361 deregisterhook(HOOK_CONTROL_WHOISREPLY
,&handlewhois
);
363 if (target
->channels
->cursi
==0) {
364 controlreply((nick
*)sender
,"Channels : none");
365 } else if (target
->channels
->cursi
>50) {
366 controlreply((nick
*)sender
,"Channels : - (total: %d)",target
->channels
->cursi
);
369 channels
=(channel
**)target
->channels
->content
;
370 for (i
=0;i
<=target
->channels
->cursi
;i
++) {
371 if (!((i
==target
->channels
->cursi
) || ((70-strlen(buf
))<channels
[i
]->index
->name
->length
&& strlen(buf
)>0))) {
372 strcat(buf
,channels
[i
]->index
->name
->content
);
375 if (strlen(buf
)==0) {
378 controlreply((nick
*)sender
,"Channels : %s",buf
);
389 int controlwhois(void *sender
, int cargc
, char **cargv
) {
392 nick
*np
= (nick
*)sender
;
395 return controlwhois_plain(sender
, cargc
, cargv
);
397 if(cargv
[0][0] != '#') {
398 if(cargv
[0][0] == '*')
400 return controlwhois_plain(sender
, cargc
, cargv
);
403 an
= findauthnamebyname(cargv
[0] + 1);
405 controlreply(np
, "Account not registered.");
409 au
= noperserv_get_autheduser(an
);
411 controlreply(np
, "User does not have a NOperserv account.");
415 controlreply(np
, "Account : %s", au
->authname
->name
);
419 registerhook(HOOK_CONTROL_WHOISREPLY
, &handlewhois
);
420 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
, (void *)au
);
421 deregisterhook(HOOK_CONTROL_WHOISREPLY
, &handlewhois
);
423 controlreply(np
, "Flags : %s", printflags(NOGetAuthLevel(au
), no_userflags
));
428 void noperserv_whois_handler(int hooknum
, void *arg
) {
430 nick
*np
= (nick
*)arg
;
436 au
= NOGetAuthedUser(np
);
438 snprintf(message
, sizeof(message
), "Flags : %s", printflags(NOGetAuthLevel(au
), no_userflags
));
439 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
, (void *)au
);
441 snprintf(message
, sizeof(message
), "Flags : (user not known)");
442 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHNAME
, (void *)np
->authname
);
444 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
449 void noperserv_whois_account_handler(int hooknum
, void *arg
) {
450 int count
= 0, found
= 0;
451 char nickbuffer
[(NICKLEN
+ 2) * NO_NICKS_PER_WHOIS_LINE
- 1]; /* since we don't need space or comma for the first item we're fine NULL wise */
452 char accountspace
[NICKLEN
+ 3]; /* space, comma, null */
456 nickbuffer
[0] = '\0';
457 if(hooknum
== HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
) {
458 /* we can just read out the authed user linked list */
459 no_autheduser
*au
= (void *)arg
;
461 if(au
->authname
->nicks
)
464 for(np
=au
->authname
->nicks
;np
;np
=np
->nextbyauthname
) {
465 snprintf(accountspace
, sizeof(accountspace
), "%s%s", count
++?", ":"", np
->nick
);
466 strncat(nickbuffer
, accountspace
, sizeof(nickbuffer
));
467 nickbuffer
[sizeof(nickbuffer
) - 1] = '\0';
469 if(count
>= NO_NICKS_PER_WHOIS_LINE
) {
470 snprintf(message
, sizeof(message
), "Authed : %s", nickbuffer
);
471 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
472 nickbuffer
[0] = '\0';
477 /* inefficient way */
478 char *authname
= (char *)arg
;
482 for(;i
<NICKHASHSIZE
;i
++)
483 for(sp
=nicktable
[i
];sp
;sp
=sp
->next
)
484 if(IsAccount(sp
) && !ircd_strcmp(sp
->authname
, authname
)) {
487 snprintf(accountspace
, sizeof(accountspace
), "%s%s", count
++?", ":"", sp
->nick
);
488 strncat(nickbuffer
, accountspace
, sizeof(nickbuffer
));
489 nickbuffer
[sizeof(nickbuffer
) - 1] = '\0';
491 if(count
>= NO_NICKS_PER_WHOIS_LINE
) {
492 snprintf(message
, sizeof(message
), "Authed : %s", nickbuffer
);
493 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
494 nickbuffer
[0] = '\0';
501 snprintf(message
, sizeof(message
), "Authed : (no nicks authed)");
502 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
503 } else if(nickbuffer
[0]) {
504 snprintf(message
, sizeof(message
), "Authed : %s", nickbuffer
);
505 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
509 int controllistusers(void *sender
, int cargc
, char **cargv
) {
510 nick
*np
= (nick
*)sender
;
517 registerhook(HOOK_CONTROL_WHOISREPLY
, &handlewhois
);
519 for (i
=0;i
<AUTHNAMEHASHSIZE
;i
++) {
520 for (anp
=authnametable
[i
];anp
;anp
=anp
->next
) {
521 au
= noperserv_get_autheduser(anp
);
526 controlreply(np
, "---");
528 controlreply(np
, "Account : %s", au
->authname
->name
);
529 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
, (void *)au
);
530 controlreply(np
, "Flags : %s", printflags(NOGetAuthLevel(au
), no_userflags
));
536 deregisterhook(HOOK_CONTROL_WHOISREPLY
, &handlewhois
);
538 controlreply(np
, "--- Found %d users.", count
);
543 int controlinsmod(void *sender
, int cargc
, char **cargv
) {
547 switch(insmod(cargv
[0])) {
549 controlreply((nick
*)sender
,"Unable to load module %s",cargv
[0]);
553 controlreply((nick
*)sender
,"Module %s already loaded, or name not valid",cargv
[0]);
557 controlreply((nick
*)sender
,"Module %s loaded.",cargv
[0]);
561 controlreply((nick
*)sender
,"An unknown error occured.");
566 int controlrmmod(void *sender
, int cargc
, char **cargv
) {
570 switch(rmmod(cargv
[0], 1)) {
572 controlreply((nick
*)sender
,"Module %s is not loaded.",cargv
[0]);
576 controlreply((nick
*)sender
,"Module %s unloaded.",cargv
[0]);
580 controlreply((nick
*)sender
,"An unknown error occured.");
585 int controllsmod(void *sender
, int cargc
, char **cargv
) {
589 if (cargc
< 1) { /* list all loaded modules */
590 const char *ver
, *buildid
;
591 time_t t
, t2
= time(NULL
);
592 ptr
= lsmod(i
, &ver
, &buildid
, &t
);
594 /* 9999d 24h 59m 59s fbf2a4a69ee1-tip */
595 controlreply((nick
*)sender
,"Module Loaded for Version Build id");
596 while (ptr
!= NULL
) {
597 controlreply((nick
*)sender
," %-40s %-17s %-30s %s", ptr
, longtoduration(t2
-t
, 2), ver
?ver
:"", buildid
?buildid
:"");
598 ptr
= lsmod(++i
, &ver
, &buildid
, &t
);
601 ptr
= lsmod(getindex(cargv
[0]), NULL
, NULL
, NULL
);
602 controlreply((nick
*)sender
,"Module \"%s\" %s", cargv
[0], (ptr
? "is loaded." : "is NOT loaded."));
607 int controlreload(void *sender
, int cargc
, char **cargv
) {
611 controlreply((nick
*)sender
,"Imma gonna try and reload %s",cargv
[0]);
613 safereload(cargv
[0]);
618 int relink(void *sender
, int cargc
, char **cargv
) {
620 controlreply((nick
*)sender
,"You must give a reason.");
624 irc_send("%s SQ %s 0 :%s",mynumeric
->content
,myserver
->content
,cargv
[0]);
630 int die(void *sender
, int cargc
, char **cargv
) {
631 if (cargc
<1 || (strlen(cargv
[0]) < 10)) {
632 controlreply((nick
*)sender
,"You must give a reason.");
636 controlwall(NO_OPER
,NL_OPERATIONS
,"DIE from %s: %s",((nick
*)sender
)->nick
, cargv
[0]);
638 newserv_shutdown_pending
=1;
643 int controlchannel(void *sender
, int cargc
, char **cargv
) {
649 int i
,j
, ops
=0, voice
=0;
655 if ((cp
=findchannel(cargv
[0]))==NULL
) {
656 controlreply((nick
*)sender
,"Couldn't find channel: %s",cargv
[0]);
661 sprintf(buf2
,"%d",cp
->limit
);
664 controlreply((nick
*)sender
,"Channel : %s",cp
->index
->name
->content
);
665 strftime(timebuf
, 30, "%d/%m/%y %H:%M", localtime(&(cp
->timestamp
)));
666 controlreply((nick
*)sender
,"C-time : %ld [%s]",cp
->timestamp
,timebuf
);
668 controlreply((nick
*)sender
,"Topic : %s",cp
->topic
->content
);
669 strftime(timebuf
, 30, "%d/%m/%y %H:%M", localtime(&(cp
->topictime
)));
670 controlreply((nick
*)sender
,"T-time : %ld [%s]",cp
->topictime
,timebuf
);
672 controlreply((nick
*)sender
,"Topic : (none)");
674 controlreply((nick
*)sender
,"Mode(s) : %s %s%s%s",printflags(cp
->flags
,cmodeflags
),IsLimit(cp
)?buf2
:"",
675 IsLimit(cp
)?" ":"",IsKey(cp
)?cp
->key
->content
:"");
676 controlreply((nick
*)sender
,"Users : %d (hash size %d, utilisation %.1f%%); %d unique hosts",
677 cp
->users
->totalusers
,cp
->users
->hashsize
,((float)(100*cp
->users
->totalusers
)/cp
->users
->hashsize
),
678 countuniquehosts(cp
));
682 for (j
=0;j
<=cp
->users
->hashsize
;j
++) {
683 if (i
==4 || j
==cp
->users
->hashsize
) {
685 controlreply((nick
*)sender
,"Users : %s",buf
);
689 if (j
==cp
->users
->hashsize
)
692 if (cp
->users
->content
[j
]!=nouser
) {
693 if (cp
->users
->content
[j
]&CUMODE_OP
)
695 else if (cp
->users
->content
[j
]&CUMODE_VOICE
)
697 np
=getnickbynumeric(cp
->users
->content
[j
]);
698 sprintf(&buf
[i
*18],"%c%c%-15s ",cp
->users
->content
[j
]&CUMODE_VOICE
?'+':' ',
699 cp
->users
->content
[j
]&CUMODE_OP
?'@':' ', np
?np
->nick
:"!BUG-NONICK!");
705 controlreply((nick
*)sender
, "Users : Opped: %d, Voiced: %d", ops
,voice
);
706 for (cbp
=cp
->bans
;cbp
;cbp
=cbp
->next
) {
707 controlreply((nick
*)sender
,"Ban : %s",bantostringdebug(cbp
));
712 int controlshowcommands(void *sender
, int cargc
, char **cargv
) {
713 nick
*np
= (nick
*)sender
;
714 Command
*cmdlist
[100];
717 n
= getcommandlist(controlcmds
, cmdlist
, 100);
719 controlreply(np
, "The following commands are registered at present:");
722 if(noperserv_policy_command_permitted(cmdlist
[i
]->level
, np
))
723 controlreply(np
, " %-25s %s", cmdlist
[i
]->command
->content
, printflags(cmdlist
[i
]->level
, no_commandflags
));
725 controlreply(np
, "End of list.");
729 void handlemessages(nick
*target
, int messagetype
, void **args
) {
735 switch(messagetype
) {
738 /* If it's a message, first arg is nick and second is message */
739 sender
= (nick
*)args
[0];
741 controlwall(NO_DEVELOPER
, NL_ALL_COMMANDS
, "From: %s!%s@%s%s%s: %s", sender
->nick
, sender
->ident
, sender
->host
->name
->content
, IsAccount(sender
)?"/":"", IsAccount(sender
)?sender
->authname
:"", (char *)args
[1]);
743 /* Split the line into params */
744 cargc
= splitline((char *)args
[1], cargv
, 50, 0);
746 if(!cargc
) /* Blank line */
749 cmd
= findcommandintree(controlcmds
,cargv
[0],1);
750 if(!cmd
|| !noperserv_policy_command_permitted(cmd
->level
, sender
)) {
751 controlreply(sender
, "Unknown command or access denied.");
755 /* Check the maxargs */
756 if (cmd
->maxparams
<(cargc
-1)) {
757 /* We need to do some rejoining */
758 rejoinline(cargv
[cmd
->maxparams
],cargc
-(cmd
->maxparams
));
759 cargc
=(cmd
->maxparams
)+1;
762 if((cmd
->handler
)((void *)sender
,cargc
-1,&(cargv
[1])) == CMD_USAGE
)
763 controlhelp(sender
, cmd
);
768 /* someone killed me? Bastards */
769 scheduleoneshot(time(NULL
)+1,&controlconnect
,NULL
);
771 triggerhook(HOOK_CONTROL_REGISTERED
, NULL
);
780 void controlmessage(nick
*target
, char *message
, ... ) {
788 va_start(va
,message
);
789 vsnprintf(buf
,512,message
,va
);
792 sendmessagetouser(mynick
,target
,"%s",buf
);
795 void controlchanmsg(channel
*cp
, char *message
, ...) {
803 va_start(va
,message
);
804 vsnprintf(buf
,512,message
,va
);
807 sendmessagetochannel(mynick
,cp
,"%s",buf
);
810 void controlnotice(nick
*target
, char *message
, ... ) {
818 va_start(va
,message
);
819 vsnprintf(buf
,512,message
,va
);
822 sendnoticetouser(mynick
,target
,"%s",buf
);
825 void controlreply(nick
*np
, char *format
, ...) {
828 no_autheduser
*au
= NOGetAuthedUser(np
);
830 va_start(va
, format
);
831 vsnprintf(buf
, sizeof(buf
), format
, va
);
834 if(au
&& !(NOGetNoticeLevel(au
) & NL_NOTICES
)) {
835 controlmessage(np
, "%s", buf
);
837 controlnotice(np
, "%s", buf
);
841 void controlwall(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...) {
844 char *flags
= printflags(noticelevel
, no_noticeflags
) + 1;
850 va_start(va
, format
);
851 vsnprintf(buf
, sizeof(buf
), format
, va
);
854 Error("noperserv", ERR_INFO
, "$%s$ %s", flags
, buf
);
856 for (i
=0;i
<AUTHNAMEHASHSIZE
;i
++) {
857 for (anp
=authnametable
[i
];anp
;anp
=anp
->next
) {
858 au
= noperserv_get_autheduser(anp
);
861 if((NOGetNoticeLevel(au
) & noticelevel
) && !(NOGetAuthLevel(au
) & __NO_RELAY
)) {
862 for(np
=anp
->nicks
;np
;np
=np
->nextbyauthname
)
863 if(noperserv_policy_command_permitted(permissionlevel
, np
))
864 controlreply(np
, "$%s$ %s", flags
, buf
);
870 void controlspecialrmmod(void *arg
) {
871 struct specialsched
*a
= (struct specialsched
*)arg
;
872 sstring
*froo
= a
->modulename
;
876 rmmod(froo
->content
, 1);
880 void controlspecialreloadmod(void *arg
) {
881 struct specialsched
*a
= (struct specialsched
*)arg
;
882 sstring
*froo
= a
->modulename
;
886 safereload(froo
->content
);
890 void controlhelp(nick
*np
, Command
*cmd
) {
893 cmdhelp
*help
=(cmdhelp
*)cmd
->ext
;
896 controlreply(np
, "Sorry, no help for this command.");
899 if ( help
->helpcmd
) {
900 (help
->helpcmd
)(np
, cmd
);
904 controlreply(np
, "Sorry, no help for this command.");
910 if(*cp
== '\0' || *cp
== '\n') {
918 controlreply(np
, "%s", sp
);
932 int controlhelpcmd(void *sender
, int cargc
, char **cargv
) {
934 nick
*np
= (nick
*)sender
;
939 cmd
= findcommandintree(controlcmds
, cargv
[0], 1);
940 if(!cmd
|| !noperserv_policy_command_permitted(cmd
->level
, np
)) {
941 controlreply(np
, "Unknown command or access denied.");
945 controlhelp(np
, cmd
);
949 void controlnoticeopers(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...) {
955 va_start(va
, format
);
956 vsnprintf(broadcast
, sizeof(broadcast
), format
, va
);
959 for(i
=0;i
<NICKHASHSIZE
;i
++)
960 for(np
=nicktable
[i
];np
;np
=np
->next
)
962 controlnotice(np
, "%s", broadcast
);
965 void controlnswall(int noticelevel
, char *format
, ...) {
969 va_start(va
, format
);
970 vsnprintf(broadcast
, sizeof(broadcast
), format
, va
);
973 controlwall(NO_OPER
, noticelevel
, "%s", broadcast
);
976 int controlpermitted(flag_t level
, nick
*user
) {
977 return noperserv_policy_command_permitted(level
, user
);
980 void handlesignal(int hooknum
, void *arg
) {
981 char *signal
, *action
;
983 if(hooknum
== HOOK_CORE_SIGINT
) {
985 action
= "terminating";
987 long hupped
= (long)arg
;
992 action
= "rehashing";
995 controlwall(NO_OPER
, NL_OPERATIONS
, "SIG%s received, %s...", signal
, action
);
998 void controldestroycmdext(void *ext
) {
999 if ( ((cmdhelp
*)ext
)->helpstr
)
1000 free( ((cmdhelp
*)ext
)->helpstr
);
1004 char *controlid(nick
*np
) {
1005 static char buf
[512];
1007 snprintf(buf
, sizeof(buf
), "%s!%s@%s/%s", np
->nick
, np
->ident
, np
->host
->name
->content
, np
->authname
);
1012 void noperserv_oper_detection(int hooknum
, void *arg
) {
1013 nick
*np
= (nick
*)arg
;
1015 if(np
->umodes
& UMODE_OPER
) {
1016 if(np
->opername
&& strcmp(np
->opername
->content
, "-")) {
1017 controlwall(NO_OPER
, NL_OPERING
, "%s!%s@%s%s%s just OPERed as %s", np
->nick
, np
->ident
, np
->host
->name
->content
, IsAccount(np
)?"/":"", IsAccount(np
)?np
->authname
:"", np
->opername
->content
);
1019 controlwall(NO_OPER
, NL_OPERING
, "%s!%s@%s%s%s just OPERed", np
->nick
, np
->ident
, np
->host
->name
->content
, IsAccount(np
)?"/":"", IsAccount(np
)?np
->authname
:"");
1022 controlwall(NO_OPER
, NL_OPERING
, "%s!%s@%s%s%s just DEOPERed", np
->nick
, np
->ident
, np
->host
->name
->content
, IsAccount(np
)?"/":"", IsAccount(np
)?np
->authname
:"");