source: irc_commands.c @ 4a9fd5f

Last change on this file since 4a9fd5f was 4a9fd5f, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-05-08T14:19:12Z

Fixed *facepalm* memory management/scoping bug in /AWAY command.

  • Property mode set to 100644
File size: 17.7 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* IRC commands                                                         */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28#include "ipc.h"
29#include "chat.h"
30
31static void irc_cmd_pass( irc_t *irc, char **cmd )
32{
33        if( irc->status & USTATUS_LOGGED_IN )
34        {
35                char *send_cmd[] = { "identify", cmd[1], NULL };
36               
37                /* We're already logged in, this client seems to send the PASS
38                   command last. (Possibly it won't send it at all if it turns
39                   out we don't require it, which will break this feature.)
40                   Try to identify using the given password. */
41                return root_command( irc, send_cmd );
42        }
43        /* Handling in pre-logged-in state, first see if this server is
44           password-protected: */
45        else if( global.conf->auth_pass &&
46            ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ?
47                md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 :
48                strcmp( cmd[1], global.conf->auth_pass ) == 0 ) )
49        {
50                irc->status |= USTATUS_AUTHORIZED;
51                irc_check_login( irc );
52        }
53        else if( global.conf->auth_pass )
54        {
55                irc_send_num( irc, 464, ":Incorrect password" );
56        }
57        else
58        {
59                /* Remember the password and try to identify after USER/NICK. */
60                /*irc_setpass( irc, cmd[1] ); */
61                irc_check_login( irc );
62        }
63}
64
65static void irc_cmd_user( irc_t *irc, char **cmd )
66{
67        irc->user->user = g_strdup( cmd[1] );
68        irc->user->fullname = g_strdup( cmd[4] );
69       
70        irc_check_login( irc );
71}
72
73static void irc_cmd_nick( irc_t *irc, char **cmd )
74{
75        if( irc_user_by_name( irc, cmd[1] ) )
76        {
77                irc_send_num( irc, 433, ":This nick is already in use" );
78        }
79        else if( !nick_ok( cmd[1] ) )
80        {
81                /* [SH] Invalid characters. */
82                irc_send_num( irc, 432, ":This nick contains invalid characters" );
83        }
84        else if( irc->user->nick )
85        {
86                if( irc->status & USTATUS_IDENTIFIED )
87                {
88                        irc_setpass( irc, NULL );
89                        irc->status &= ~USTATUS_IDENTIFIED;
90                        irc_umode_set( irc, "-R", 1 );
91                }
92               
93                irc_user_set_nick( irc->user, cmd[1] );
94        }
95        else
96        {
97                irc->user->nick = g_strdup( cmd[1] );
98               
99                irc_check_login( irc );
100        }
101}
102
103static void irc_cmd_quit( irc_t *irc, char **cmd )
104{
105        if( cmd[1] && *cmd[1] )
106                irc_abort( irc, 0, "Quit: %s", cmd[1] );
107        else
108                irc_abort( irc, 0, "Leaving..." );
109}
110
111static void irc_cmd_ping( irc_t *irc, char **cmd )
112{
113        irc_write( irc, ":%s PONG %s :%s", irc->root->host,
114                   irc->root->host, cmd[1]?cmd[1]:irc->root->host );
115}
116
117static void irc_cmd_pong( irc_t *irc, char **cmd )
118{
119        /* We could check the value we get back from the user, but in
120           fact we don't care, we're just happy s/he's still alive. */
121        irc->last_pong = gettime();
122        irc->pinging = 0;
123}
124
125static void irc_cmd_join( irc_t *irc, char **cmd )
126{
127        irc_channel_t *ic;
128       
129        if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
130                ic = irc_channel_new( irc, cmd[1] );
131       
132        if( ic == NULL )
133        {
134                irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] );
135                return;
136        }
137       
138        if( ic->flags & IRC_CHANNEL_JOINED )
139                return; /* Dude, you're already there...
140                           RFC doesn't have any reply for that though? */
141       
142        irc_channel_add_user( ic, irc->user );
143}
144
145static void irc_cmd_names( irc_t *irc, char **cmd )
146{
147        irc_channel_t *ic;
148       
149        if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
150                irc_send_names( ic );
151        /* With no args, we should show /names of all chans. Make the code
152           below work well if necessary.
153        else
154        {
155                GSList *l;
156               
157                for( l = irc->channels; l; l = l->next )
158                        irc_send_names( l->data );
159        }
160        */
161}
162
163static void irc_cmd_part( irc_t *irc, char **cmd )
164{
165        irc_channel_t *ic;
166       
167        if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
168        {
169                irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
170        }
171        else if( !irc_channel_del_user( ic, irc->user ) )
172        {
173                irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] );
174        }
175}
176
177static void irc_cmd_whois( irc_t *irc, char **cmd )
178{
179        char *nick = cmd[1];
180        irc_user_t *iu = irc_user_by_name( irc, nick );
181       
182        if( iu )
183                irc_send_whois( iu );
184        else
185                irc_send_num( irc, 401, "%s :Nick does not exist", nick );
186}
187
188static void irc_cmd_whowas( irc_t *irc, char **cmd )
189{
190        /* For some reason irssi tries a whowas when whois fails. We can
191           ignore this, but then the user never gets a "user not found"
192           message from irssi which is a bit annoying. So just respond
193           with not-found and irssi users will get better error messages */
194       
195        irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] );
196        irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] );
197}
198
199static void irc_cmd_motd( irc_t *irc, char **cmd )
200{
201        irc_send_motd( irc );
202}
203
204static void irc_cmd_mode( irc_t *irc, char **cmd )
205{
206        if( irc_channel_name_ok( cmd[1] ) )
207        {
208                irc_channel_t *ic;
209               
210                if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
211                        irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
212                else if( cmd[2] )
213                {
214                        if( *cmd[2] == '+' || *cmd[2] == '-' )
215                                irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
216                        else if( *cmd[2] == 'b' )
217                                irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
218                }
219                else
220                        irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode );
221        }
222        else
223        {
224                if( nick_cmp( cmd[1], irc->user->nick ) == 0 )
225                {
226                        if( cmd[2] )
227                                irc_umode_set( irc, cmd[2], 0 );
228                        else
229                                irc_send_num( irc, 221, "+%s", irc->umode );
230                }
231                else
232                        irc_send_num( irc, 502, ":Don't touch their modes" );
233        }
234}
235
236static void irc_cmd_who( irc_t *irc, char **cmd )
237{
238        char *channel = cmd[1];
239        irc_channel_t *ic;
240       
241        if( !channel || *channel == '0' || *channel == '*' || !*channel )
242                irc_send_who( irc, irc->users, "**" );
243        else if( ( ic = irc_channel_by_name( irc, channel ) ) )
244                irc_send_who( irc, ic->users, channel );
245        else
246                irc_send_num( irc, 403, "%s :No such channel", channel );
247}
248
249static void irc_cmd_privmsg( irc_t *irc, char **cmd )
250{
251        irc_channel_t *ic;
252        irc_user_t *iu;
253       
254        if( !cmd[2] ) 
255        {
256                irc_send_num( irc, 412, ":No text to send" );
257                return;
258        }
259       
260        /* Don't treat CTCP actions as real CTCPs, just convert them right now. */
261        if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 )
262        {
263                cmd[2] += 4;
264                strcpy( cmd[2], "/me" );
265                if( cmd[2][strlen(cmd[2])-1] == '\001' )
266                        cmd[2][strlen(cmd[2])-1] = '\0';
267        }
268       
269        if( irc_channel_name_ok( cmd[1] ) &&
270            ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
271        {
272                if( ic->f->privmsg )
273                        ic->f->privmsg( ic, cmd[2] );
274        }
275        else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) )
276        {
277                if( cmd[2][0] == '\001' )
278                {
279                        char **ctcp;
280                       
281                        if( iu->f->ctcp == NULL )
282                                return;
283                        if( cmd[2][strlen(cmd[2])-1] == '\001' )
284                                cmd[2][strlen(cmd[2])-1] = '\0';
285                       
286                        ctcp = split_command_parts( cmd[2] + 1 );
287                        iu->f->ctcp( iu, ctcp );
288                }
289                else if( iu->f->privmsg )
290                {
291                        iu->flags |= IRC_USER_PRIVATE;
292                        iu->f->privmsg( iu, cmd[2] );
293                }
294        }
295        else
296        {
297                irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] );
298        }
299
300
301#if 0
302        else if( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
303        {
304        }
305        else
306        {
307                if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
308                {
309                        unsigned int i;
310                        char *t = set_getstr( &irc->set, "default_target" );
311                       
312                        if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
313                                cmd[1] = irc->last_target;
314                        else if( g_strcasecmp( t, "root" ) == 0 )
315                                cmd[1] = irc->mynick;
316                       
317                        for( i = 0; i < strlen( cmd[2] ); i ++ )
318                        {
319                                if( cmd[2][i] == ' ' ) break;
320                                if( cmd[2][i] == ':' || cmd[2][i] == ',' )
321                                {
322                                        cmd[1] = cmd[2];
323                                        cmd[2] += i;
324                                        *cmd[2] = 0;
325                                        while( *(++cmd[2]) == ' ' );
326                                        break;
327                                }
328                        }
329                       
330                        irc->is_private = 0;
331                       
332                        if( cmd[1] != irc->last_target )
333                        {
334                                g_free( irc->last_target );
335                                irc->last_target = g_strdup( cmd[1] );
336                        }
337                }
338                else
339                {
340                        irc->is_private = 1;
341                }
342                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
343        }
344#endif
345}
346
347static void irc_cmd_nickserv( irc_t *irc, char **cmd )
348{
349        /* [SH] This aliases the NickServ command to PRIVMSG root */
350        /* [TV] This aliases the NS command to PRIVMSG root as well */
351        root_command( irc, cmd + 1 );
352}
353
354
355
356static void irc_cmd_oper( irc_t *irc, char **cmd )
357{
358        if( global.conf->oper_pass &&
359            ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
360                md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
361                strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
362        {
363                irc_umode_set( irc, "+o", 1 );
364                irc_send_num( irc, 381, ":Password accepted" );
365        }
366        else
367        {
368                irc_send_num( irc, 432, ":Incorrect password" );
369        }
370}
371
372#if 0
373static void irc_cmd_invite( irc_t *irc, char **cmd )
374{
375        char *nick = cmd[1], *channel = cmd[2];
376        struct groupchat *c = irc_chat_by_channel( irc, channel );
377        user_t *u = user_find( irc, nick );
378       
379        if( u && c && ( u->ic == c->ic ) )
380                if( c->ic && c->ic->acc->prpl->chat_invite )
381                {
382                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
383                        irc_send_num( irc, 341, "%s %s", nick, channel );
384                        return;
385                }
386       
387        irc_send_num( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
388}
389#endif
390
391static void irc_cmd_userhost( irc_t *irc, char **cmd )
392{
393        int i;
394       
395        /* [TV] Usable USERHOST-implementation according to
396                RFC1459. Without this, mIRC shows an error
397                while connecting, and the used way of rejecting
398                breaks standards.
399        */
400       
401        for( i = 1; cmd[i]; i ++ )
402        {
403                irc_user_t *iu = irc_user_by_name( irc, cmd[i] );
404               
405                if( iu )
406                        irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick,
407                                      irc_user_get_away( iu ) ? '-' : '+',
408                                      iu->user, iu->host );
409        }
410}
411
412static void irc_cmd_ison( irc_t *irc, char **cmd )
413{
414        char buff[IRC_MAX_LINE];
415        int lenleft, i;
416       
417        buff[0] = '\0';
418       
419        /* [SH] Leave room for : and \0 */
420        lenleft = IRC_MAX_LINE - 2;
421       
422        for( i = 1; cmd[i]; i ++ )
423        {
424                char *this, *next;
425               
426                this = cmd[i];
427                while( *this )
428                {
429                        irc_user_t *iu;
430                       
431                        if( ( next = strchr( this, ' ' ) ) )
432                                *next = 0;
433                       
434                        if( ( iu = irc_user_by_name( irc, this ) ) &&
435                            iu->bu && iu->bu->flags & BEE_USER_ONLINE )
436                        {
437                                lenleft -= strlen( iu->nick ) + 1;
438                               
439                                if( lenleft < 0 )
440                                        break;
441                               
442                                strcat( buff, iu->nick );
443                                strcat( buff, " " );
444                        }
445                       
446                        if( next )
447                        {
448                                *next = ' ';
449                                this = next + 1;
450                        }
451                        else
452                        {
453                                break;
454                        }   
455                }
456               
457                /* *sigh* */
458                if( lenleft < 0 )
459                        break;
460        }
461       
462        if( strlen( buff ) > 0 )
463                buff[strlen(buff)-1] = '\0';
464       
465        irc_send_num( irc, 303, ":%s", buff );
466}
467
468static void irc_cmd_watch( irc_t *irc, char **cmd )
469{
470        int i;
471       
472        /* Obviously we could also mark a user structure as being
473           watched, but what if the WATCH command is sent right
474           after connecting? The user won't exist yet then... */
475        for( i = 1; cmd[i]; i ++ )
476        {
477                char *nick;
478                irc_user_t *iu;
479               
480                if( !cmd[i][0] || !cmd[i][1] )
481                        break;
482               
483                nick = g_strdup( cmd[i] + 1 );
484                nick_lc( nick );
485               
486                iu = irc_user_by_name( irc, nick );
487               
488                if( cmd[i][0] == '+' )
489                {
490                        if( !g_hash_table_lookup( irc->watches, nick ) )
491                                g_hash_table_insert( irc->watches, nick, nick );
492                       
493                        if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE )
494                                irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user,
495                                              iu->host, (int) time( NULL ), "is online" );
496                        else
497                                irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*",
498                                              (int) time( NULL ), "is offline" );
499                }
500                else if( cmd[i][0] == '-' )
501                {
502                        gpointer okey, ovalue;
503                       
504                        if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
505                        {
506                                g_hash_table_remove( irc->watches, okey );
507                                g_free( okey );
508                               
509                                irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
510                        }
511                }
512        }
513}
514
515#if 0
516static void irc_cmd_topic( irc_t *irc, char **cmd )
517{
518        char *channel = cmd[1];
519        char *topic = cmd[2];
520       
521        if( topic )
522        {
523                /* Send the topic */
524                struct groupchat *c = irc_chat_by_channel( irc, channel );
525                if( c && c->ic && c->ic->acc->prpl->chat_topic )
526                        c->ic->acc->prpl->chat_topic( c, topic );
527        }
528        else
529        {
530                /* Get the topic */
531                irc_topic( irc, channel );
532        }
533}
534#endif
535
536static void irc_cmd_away( irc_t *irc, char **cmd )
537{
538        char *set;
539       
540        if( cmd[1] && *cmd[1] )
541        {
542                char away[strlen(cmd[1])+1];
543                int i, j;
544               
545                /* Copy away string, but skip control chars. Mainly because
546                   Jabber really doesn't like them. */
547                for( i = j = 0; cmd[1][i]; i ++ )
548                        if( ( away[j] = cmd[1][i] ) >= ' ' )
549                                j ++;
550                away[j] = '\0';
551               
552                irc_send_num( irc, 306, ":You're now away: %s", away );
553                set_setstr( &irc->b->set, "away", away );
554        }
555        else
556        {
557                irc_send_num( irc, 305, ":Welcome back" );
558                set_setstr( &irc->b->set, "away", NULL );
559        }
560}
561
562static void irc_cmd_version( irc_t *irc, char **cmd )
563{
564        irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ",
565                      BITLBEE_VERSION, irc->root->host, ARCH, CPU );
566}
567
568static void irc_cmd_completions( irc_t *irc, char **cmd )
569{
570        help_t *h;
571        set_t *s;
572        int i;
573       
574        irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" );
575       
576        for( i = 0; commands[i].command; i ++ )
577                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command );
578       
579        for( h = global.help; h; h = h->next )
580                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title );
581       
582        for( s = irc->b->set; s; s = s->next )
583                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key );
584       
585        irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" );
586}
587
588static void irc_cmd_rehash( irc_t *irc, char **cmd )
589{
590        if( global.conf->runmode == RUNMODE_INETD )
591                ipc_master_cmd_rehash( NULL, NULL );
592        else
593                ipc_to_master( cmd );
594       
595        irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
596}
597
598static const command_t irc_commands[] = {
599        { "pass",        1, irc_cmd_pass,        0 },
600        { "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
601        { "nick",        1, irc_cmd_nick,        0 },
602        { "quit",        0, irc_cmd_quit,        0 },
603        { "ping",        0, irc_cmd_ping,        0 },
604        { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
605        { "join",        1, irc_cmd_join,        IRC_CMD_LOGGED_IN },
606        { "names",       1, irc_cmd_names,       IRC_CMD_LOGGED_IN },
607        { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
608        { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
609        { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
610        { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
611        { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
612        { "who",         0, irc_cmd_who,         IRC_CMD_LOGGED_IN },
613        { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
614        { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
615        { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
616        { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
617        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
618        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
619        { "userhost",    1, irc_cmd_userhost,    IRC_CMD_LOGGED_IN },
620        { "ison",        1, irc_cmd_ison,        IRC_CMD_LOGGED_IN },
621        { "watch",       1, irc_cmd_watch,       IRC_CMD_LOGGED_IN },
622#if 0
623        { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
624        { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
625        { "topic",       1, irc_cmd_topic,       IRC_CMD_LOGGED_IN },
626#endif
627        { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
628        { "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
629        { "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
630        { "wallops",     1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
631        { "wall",        1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
632        { "rehash",      0, irc_cmd_rehash,      IRC_CMD_OPER_ONLY },
633        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
634        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
635        { NULL }
636};
637
638void irc_exec( irc_t *irc, char *cmd[] )
639{       
640        int i, n_arg;
641       
642        if( !cmd[0] )
643                return;
644       
645        for( i = 0; irc_commands[i].command; i++ )
646                if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 )
647                {
648                        /* There should be no typo in the next line: */
649                        for( n_arg = 0; cmd[n_arg]; n_arg ++ ); n_arg --;
650                       
651                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
652                        {
653                                irc_send_num( irc, 462, ":Only allowed before logging in" );
654                        }
655                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
656                        {
657                                irc_send_num( irc, 451, ":Register first" );
658                        }
659                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
660                        {
661                                irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
662                        }
663                        else if( n_arg < irc_commands[i].required_parameters )
664                        {
665                                irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
666                        }
667                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
668                        {
669                                /* IPC doesn't make sense in inetd mode,
670                                    but the function will catch that. */
671                                ipc_to_master( cmd );
672                        }
673                        else
674                        {
675                                irc_commands[i].execute( irc, cmd );
676                        }
677                       
678                        return;
679                }
680       
681        if( irc->status >= USTATUS_LOGGED_IN )
682                irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
683}
Note: See TracBrowser for help on using the repository browser.