source: irc_commands.c @ 0d9d53e

Last change on this file since 0d9d53e was 92cb8c4, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-06-06T23:47:46Z

Complete (hopefully) fix for nickname changes: Add flags to the identify
command to allow identifying without loading any new settings. With some
documentation hints.

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