source: irc_commands.c @ 06b39f2

Last change on this file since 06b39f2 was 9a9b520, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-07-08T22:31:01Z

Allow nick changes if they're only different in capitalisation, fixed
faulty responses in the NICK command, and fixing crash bug in nick changes
before finishing login.

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