1 #include "../control/control.h"
2 #include "../localuser/localuser.h"
3 #include "../core/schedule.h"
4 #include "../core/modules.h"
5 #include "../lib/splitline.h"
6 #include "../lib/flags.h"
7 #include "../lib/irc_string.h"
8 #include "../lib/strlfunc.h"
10 #include "noperserv.h"
11 #include "noperserv_db.h"
12 #include "noperserv_hooks.h"
13 #include "noperserv_policy.h"
24 struct storedhook
*next
;
27 struct storedhook
*storedhooks
= NULL
;
30 nick
*replynick
= NULL
;
32 UserMessageHandler oldhandler
;
35 ControlPermitted oldpermitted
;
37 void noperserv_trap_registration(int hooknum
, void *arg
);
38 int noperserv_showcommands(void *sender
, int cargc
, char **cargv
);
39 int noperserv_rmmod(void *sender
, int cargc
, char **cargv
);
40 int noperserv_reload(void *sender
, int cargc
, char **cargv
);
41 int noperserv_whois(void *sender
, int cargc
, char **cargv
);
42 int noperserv_help(void *sender
, int cargc
, char **cargv
);
43 void noperserv_whois_handler(int hooknum
, void *arg
);
44 void noperserv_whois_account_handler(int hooknum
, void *arg
);
45 void noperserv_handle_messages(nick
*target
, int messagetype
, void **args
);
46 void noperserv_reply(nick
*np
, char *format
, ...) __attribute__ ((format (printf
, 2, 3)));
47 void noperserv_wall(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...);
49 struct specialsched special
;
51 #define HOOK_CONTROL_WHOISREQUEST_AUTHNAME -1
52 #define HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER -2
54 void noperserv_setup_hooks(void) {
55 oldreply
= controlreply
;
56 controlreply
= &noperserv_reply
;
58 oldwall
= controlwall
;
59 controlwall
= &noperserv_wall
;
61 oldpermitted
= controlpermitted
;
62 controlpermitted
= &noperserv_policy_command_permitted
;
64 memset(&special
, 0, sizeof(struct specialsched
));
67 registerhook(HOOK_CONTROL_REGISTERED
, &noperserv_trap_registration
);
69 noperserv_trap_registration(0, (void *)mynick
);
72 registerhook(HOOK_CONTROL_WHOISREQUEST
, &noperserv_whois_handler
);
75 int noperserv_hook_command(char *command
, CommandHandler newcommand
, char *newhelp
) {
76 struct storedhook
*newhook
;
77 Command
*fetchcommand
= findcommandintree(controlcmds
, command
, 1);
82 newhook
= (struct storedhook
*)malloc(sizeof(struct storedhook
));
86 newhook
->name
= getsstring(command
, strlen(command
));
92 newhook
->old
= fetchcommand
->handler
;
94 newhook
->newhelp
= (cmdhelp
*)malloc(sizeof(cmdhelp
));
95 memset(newhook
->newhelp
,0,sizeof(cmdhelp
));
96 if(!newhook
->newhelp
) {
97 freesstring(newhook
->name
);
100 int len
= strlen(newhelp
) + 1;
101 newhook
->newhelp
->helpstr
= (char *)malloc(len
);
102 if (newhook
->newhelp
->helpstr
) {
103 strlcpy(newhook
->newhelp
->helpstr
, newhelp
, len
);
105 newhook
->oldhelp
= fetchcommand
->ext
;
106 fetchcommand
->ext
= newhook
->newhelp
;
109 newhook
->newhelp
= NULL
;
112 newhook
->next
= storedhooks
;
113 storedhooks
= newhook
;
115 fetchcommand
->handler
= newcommand
;
120 void noperserv_unhook_all_commands(void) {
121 struct storedhook
*nh
, *ch
= storedhooks
;
122 Command
*fetchcommand
;
125 if(ch
->old
&& (fetchcommand
= findcommandintree(controlcmds
, ch
->name
->content
, 1))) {
126 fetchcommand
->handler
= ch
->old
;
128 fetchcommand
->ext
= ch
->oldhelp
;
129 if ( ((cmdhelp
*)ch
->newhelp
)->helpstr
)
130 free( ((cmdhelp
*)ch
->newhelp
)->helpstr
);
135 freesstring(ch
->name
);
141 void noperserv_cleanup_hooks(void) {
142 deregisterhook(HOOK_CONTROL_WHOISREQUEST
, &noperserv_whois_handler
);
143 deregisterhook(HOOK_CONTROL_REGISTERED
, &noperserv_trap_registration
);
146 noperserv_unhook_all_commands();
150 if(oldhandler
&& mynick
)
151 hooklocaluserhandler(mynick
, oldhandler
);
153 controlwall
= oldwall
;
154 controlreply
= oldreply
;
155 controlpermitted
= oldpermitted
;
158 void noperserv_trap_registration(int hooknum
, void *arg
) {
159 nick
*np
= (nick
*)arg
;
163 oldhandler
= hooklocaluserhandler((nick
*)arg
, &noperserv_handle_messages
);
169 noperserv_hook_command("rmmod", &noperserv_rmmod
, NULL
);
170 noperserv_hook_command("reload", &noperserv_reload
, NULL
);
171 noperserv_hook_command("showcommands", &noperserv_showcommands
, NULL
);
172 noperserv_hook_command("whois", &noperserv_whois
, "Usage: whois <nickname|#authname|*numeric>\nDisplays lots of information about the specified nickname, auth name or numeric.");
173 noperserv_hook_command("help", &noperserv_help
, NULL
);
177 CommandHandler
noperserv_find_hook(char *command
) {
178 struct storedhook
*hh
= storedhooks
;
180 if(!ircd_strcmp(hh
->name
->content
, command
))
186 int noperserv_modules_loaded(char *mask
) {
190 for(i
=0,ptr
=lsmod(i
,NULL
,NULL
,NULL
);ptr
;ptr
=lsmod(++i
,NULL
,NULL
,NULL
))
191 if(match2strings(mask
, ptr
))
197 int noperserv_specialmod(nick
*np
, char *command
, ScheduleCallback reloadhandler
, int cargc
, char **cargv
) {
198 CommandHandler oldcommand
= noperserv_find_hook(command
);
201 return oldcommand(np
, cargc
, cargv
);
205 if(!strcmp(cargv
[0], "noperserv")) {
206 if(special
.schedule
) {
207 controlreply(np
, "Previous attempt at un/reload still in progress.");
210 special
.modulename
= getsstring(cargv
[0], strlen(cargv
[0]));
211 if(!special
.modulename
) {
212 controlreply(np
, "Unable to copy module name. Seek cow herd to trample on server.");
215 special
.schedule
= scheduleoneshot(time(NULL
) + 1, reloadhandler
, &special
);
216 if(!special
.schedule
) {
217 freesstring(special
.modulename
);
218 special
.modulename
= NULL
;
219 controlreply(np
, "Unable to allocate schedule. Seek cow herd to trample on server.");
222 controlreply(np
, "Special case un/reload in <1 second, no response will be sent, standby. . .");
228 return oldcommand(np
, cargc
, cargv
);
233 int noperserv_rmmod(void *sender
, int cargc
, char **cargv
) {
234 return noperserv_specialmod(sender
, "rmmod", &controlspecialrmmod
, cargc
, cargv
);
237 int noperserv_reload(void *sender
, int cargc
, char **cargv
) {
238 return noperserv_specialmod(sender
, "reload", &controlspecialreloadmod
, cargc
, cargv
);
241 void noperserv_whois_hook(int hooknum
, void *arg
) {
242 controlreply(replynick
, "%s", (char *)arg
);
245 int noperserv_whois(void *sender
, int cargc
, char **cargv
) {
248 nick
*np
= (nick
*)sender
;
249 CommandHandler oldwhois
= noperserv_find_hook("whois");
253 return oldwhois(sender
, cargc
, cargv
);
257 if(cargv
[0][0] != '#') {
258 if(cargv
[0][0] == '*')
261 return oldwhois(sender
, cargc
, cargv
);
265 an
= findauthnamebyname(cargv
[0] + 1);
267 controlreply(np
, "Account not registered.");
271 au
= noperserv_get_autheduser(an
);
273 controlreply(np
, "User does not have a NOperserv account.");
277 controlreply(np
, "Account : %s", au
->authname
->name
);
281 registerhook(HOOK_CONTROL_WHOISREPLY
, &noperserv_whois_hook
);
282 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
, (void *)au
);
283 deregisterhook(HOOK_CONTROL_WHOISREPLY
, &noperserv_whois_hook
);
285 controlreply(np
, "Flags : %s", printflags(NOGetAuthLevel(au
), no_userflags
));
290 int noperserv_showcommands(void *sender
, int cargc
, char **cargv
) {
291 nick
*np
= (nick
*)sender
;
292 Command
*cmdlist
[100];
295 n
= getcommandlist(controlcmds
, cmdlist
, 100);
297 controlreply(np
, "The following commands are registered at present:");
300 if(noperserv_policy_command_permitted(cmdlist
[i
]->level
, np
))
301 controlreply(np
, " %-25s %s", cmdlist
[i
]->command
->content
, printflags(cmdlist
[i
]->level
, no_commandflags
));
303 controlreply(np
, "End of list.");
307 void noperserv_whois_handler(int hooknum
, void *arg
) {
309 nick
*np
= (nick
*)arg
;
315 au
= NOGetAuthedUser(np
);
317 snprintf(message
, sizeof(message
), "Flags : %s", printflags(NOGetAuthLevel(au
), no_userflags
));
318 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
, (void *)au
);
320 snprintf(message
, sizeof(message
), "Flags : (user not known)");
321 noperserv_whois_account_handler(HOOK_CONTROL_WHOISREQUEST_AUTHNAME
, (void *)np
->authname
);
323 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
328 void noperserv_whois_account_handler(int hooknum
, void *arg
) {
329 int count
= 0, found
= 0;
330 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 */
331 char accountspace
[NICKLEN
+ 3]; /* space, comma, null */
335 nickbuffer
[0] = '\0';
336 if(hooknum
== HOOK_CONTROL_WHOISREQUEST_AUTHEDUSER
) {
337 /* we can just read out the authed user linked list */
338 no_autheduser
*au
= (void *)arg
;
340 if(au
->authname
->nicks
)
343 for(np
=au
->authname
->nicks
;np
;np
=np
->nextbyauthname
) {
344 snprintf(accountspace
, sizeof(accountspace
), "%s%s", count
++?", ":"", np
->nick
);
345 strlcat(nickbuffer
, accountspace
, sizeof(nickbuffer
));
347 if(count
>= NO_NICKS_PER_WHOIS_LINE
) {
348 snprintf(message
, sizeof(message
), "Authed : %s", nickbuffer
);
349 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
350 nickbuffer
[0] = '\0';
355 /* inefficient way */
356 char *authname
= (char *)arg
;
360 for(;i
<NICKHASHSIZE
;i
++)
361 for(sp
=nicktable
[i
];sp
;sp
=sp
->next
)
362 if(IsAccount(sp
) && !ircd_strcmp(sp
->authname
, authname
)) {
365 snprintf(accountspace
, sizeof(accountspace
), "%s%s", count
++?", ":"", sp
->nick
);
366 strlcat(nickbuffer
, accountspace
, sizeof(nickbuffer
));
368 if(count
>= NO_NICKS_PER_WHOIS_LINE
) {
369 snprintf(message
, sizeof(message
), "Authed : %s", nickbuffer
);
370 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
371 nickbuffer
[0] = '\0';
378 snprintf(message
, sizeof(message
), "Authed : (no nicks authed)");
379 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
380 } else if(nickbuffer
[0]) {
381 snprintf(message
, sizeof(message
), "Authed : %s", nickbuffer
);
382 triggerhook(HOOK_CONTROL_WHOISREPLY
, message
);
386 /* Obviously pinched from control.c */
387 void noperserv_handle_messages(nick
*target
, int messagetype
, void **args
) {
393 switch(messagetype
) {
394 case LU_PRIVMSG
: /* override these two commands only */
396 /* If it's a message, first arg is nick and second is message */
397 sender
= (nick
*)args
[0];
399 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]);
401 /* Split the line into params */
402 cargc
= splitline((char *)args
[1], cargv
, 50, 0);
404 if(!cargc
) /* Blank line */
407 cmd
= findcommandintree(controlcmds
,cargv
[0],1);
409 controlreply(sender
, "Unknown command or access denied.");
413 /* If we were doing "authed user tracking" here we'd put a check in for authlevel */
415 if (!noperserv_policy_command_permitted(cmd
->level
, sender
)) {
416 controlreply(sender
, "Unknown command or access denied.");
420 /* Check the maxargs */
421 if(cmd
->maxparams
< (cargc
- 1)) {
422 /* We need to do some rejoining */
423 rejoinline(cargv
[cmd
->maxparams
], cargc
- (cmd
->maxparams
));
424 cargc
= (cmd
->maxparams
) + 1;
427 if((cmd
->handler
)((void *)sender
,cargc
-1,&(cargv
[1])) == CMD_USAGE
)
428 controlhelp(sender
, cmd
);
433 oldhandler(target
, messagetype
, args
);
438 void noperserv_reply(nick
*np
, char *format
, ...) {
441 no_autheduser
*au
= NOGetAuthedUser(np
);
443 va_start(va
, format
);
444 vsnprintf(buf
, sizeof(buf
), format
, va
);
447 if(au
&& !(NOGetNoticeLevel(au
) & NL_NOTICES
)) {
448 controlmessage(np
, "%s", buf
);
450 controlnotice(np
, "%s", buf
);
454 int noperserv_help(void *sender
, int cargc
, char **cargv
) {
456 nick
*np
= (nick
*)sender
;
461 cmd
= findcommandintree(controlcmds
, cargv
[0], 1);
462 if(!cmd
|| !noperserv_policy_command_permitted(cmd
->level
, np
)) {
463 controlreply(np
, "Unknown command or access denied.");
467 controlhelp(np
, cmd
);
471 void noperserv_wall(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...) {
474 char *flags
= printflags(noticelevel
, no_noticeflags
) + 1;
480 va_start(va
, format
);
481 vsnprintf(buf
, sizeof(buf
), format
, va
);
484 Error("noperserv", ERR_INFO
, "$%s$ %s", flags
, buf
);
486 for (i
=0;i
<AUTHNAMEHASHSIZE
;i
++) {
487 for (anp
=authnametable
[i
];anp
;anp
=anp
->next
) {
488 au
= noperserv_get_autheduser(anp
);
491 if((NOGetNoticeLevel(au
) & noticelevel
) && !(NOGetAuthLevel(au
) & __NO_RELAY
)) {
492 for(np
=anp
->nicks
;np
;np
=np
->nextbyauthname
)
493 if(noperserv_policy_command_permitted(permissionlevel
, np
))
494 controlreply(np
, "$%s$ %s", flags
, buf
);