source: irc_commands.c @ 46d215d

Last change on this file since 46d215d was 46d215d, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-06-08T23:43:13Z

Allow moving contacts around between groups. Works with at least Jabber,
will check the others now.

  • Property mode set to 100644
File size: 18.4 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 )
406                irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] );
407        else if( ic->f->invite( ic, iu ) )
408                irc_send_num( irc, 341, "%s %s", iu->nick, ic->name );
409}
410
411static void irc_cmd_userhost( irc_t *irc, char **cmd )
412{
413        int i;
414       
415        /* [TV] Usable USERHOST-implementation according to
416                RFC1459. Without this, mIRC shows an error
417                while connecting, and the used way of rejecting
418                breaks standards.
419        */
420       
421        for( i = 1; cmd[i]; i ++ )
422        {
423                irc_user_t *iu = irc_user_by_name( irc, cmd[i] );
424               
425                if( iu )
426                        irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick,
427                                      irc_user_get_away( iu ) ? '-' : '+',
428                                      iu->user, iu->host );
429        }
430}
431
432static void irc_cmd_ison( irc_t *irc, char **cmd )
433{
434        char buff[IRC_MAX_LINE];
435        int lenleft, i;
436       
437        buff[0] = '\0';
438       
439        /* [SH] Leave room for : and \0 */
440        lenleft = IRC_MAX_LINE - 2;
441       
442        for( i = 1; cmd[i]; i ++ )
443        {
444                char *this, *next;
445               
446                this = cmd[i];
447                while( *this )
448                {
449                        irc_user_t *iu;
450                       
451                        if( ( next = strchr( this, ' ' ) ) )
452                                *next = 0;
453                       
454                        if( ( iu = irc_user_by_name( irc, this ) ) &&
455                            iu->bu && iu->bu->flags & BEE_USER_ONLINE )
456                        {
457                                lenleft -= strlen( iu->nick ) + 1;
458                               
459                                if( lenleft < 0 )
460                                        break;
461                               
462                                strcat( buff, iu->nick );
463                                strcat( buff, " " );
464                        }
465                       
466                        if( next )
467                        {
468                                *next = ' ';
469                                this = next + 1;
470                        }
471                        else
472                        {
473                                break;
474                        }   
475                }
476               
477                /* *sigh* */
478                if( lenleft < 0 )
479                        break;
480        }
481       
482        if( strlen( buff ) > 0 )
483                buff[strlen(buff)-1] = '\0';
484       
485        irc_send_num( irc, 303, ":%s", buff );
486}
487
488static void irc_cmd_watch( irc_t *irc, char **cmd )
489{
490        int i;
491       
492        /* Obviously we could also mark a user structure as being
493           watched, but what if the WATCH command is sent right
494           after connecting? The user won't exist yet then... */
495        for( i = 1; cmd[i]; i ++ )
496        {
497                char *nick;
498                irc_user_t *iu;
499               
500                if( !cmd[i][0] || !cmd[i][1] )
501                        break;
502               
503                nick = g_strdup( cmd[i] + 1 );
504                nick_lc( nick );
505               
506                iu = irc_user_by_name( irc, nick );
507               
508                if( cmd[i][0] == '+' )
509                {
510                        if( !g_hash_table_lookup( irc->watches, nick ) )
511                                g_hash_table_insert( irc->watches, nick, nick );
512                       
513                        if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE )
514                                irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user,
515                                              iu->host, (int) time( NULL ), "is online" );
516                        else
517                                irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*",
518                                              (int) time( NULL ), "is offline" );
519                }
520                else if( cmd[i][0] == '-' )
521                {
522                        gpointer okey, ovalue;
523                       
524                        if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
525                        {
526                                g_hash_table_remove( irc->watches, okey );
527                                g_free( okey );
528                               
529                                irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
530                        }
531                }
532        }
533}
534
535static void irc_cmd_topic( irc_t *irc, char **cmd )
536{
537        irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] );
538        const char *new = cmd[2];
539       
540        if( ic == NULL )
541        {
542                irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
543        }
544        else if( new )
545        {
546                if( ic->f->topic == NULL )
547                        irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name );
548                else if( ic->f->topic( ic, new ) )
549                        irc_send_topic( ic, TRUE );
550        }
551        else
552        {
553                irc_send_topic( ic, FALSE );
554        }
555}
556
557static void irc_cmd_away( irc_t *irc, char **cmd )
558{
559        if( cmd[1] && *cmd[1] )
560        {
561                char away[strlen(cmd[1])+1];
562                int i, j;
563               
564                /* Copy away string, but skip control chars. Mainly because
565                   Jabber really doesn't like them. */
566                for( i = j = 0; cmd[1][i]; i ++ )
567                        if( ( away[j] = cmd[1][i] ) >= ' ' )
568                                j ++;
569                away[j] = '\0';
570               
571                irc_send_num( irc, 306, ":You're now away: %s", away );
572                set_setstr( &irc->b->set, "away", away );
573        }
574        else
575        {
576                irc_send_num( irc, 305, ":Welcome back" );
577                set_setstr( &irc->b->set, "away", NULL );
578        }
579}
580
581static void irc_cmd_version( irc_t *irc, char **cmd )
582{
583        irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ",
584                      BITLBEE_VERSION, irc->root->host, ARCH, CPU );
585}
586
587static void irc_cmd_completions( irc_t *irc, char **cmd )
588{
589        help_t *h;
590        set_t *s;
591        int i;
592       
593        irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" );
594       
595        for( i = 0; commands[i].command; i ++ )
596                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command );
597       
598        for( h = global.help; h; h = h->next )
599                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title );
600       
601        for( s = irc->b->set; s; s = s->next )
602                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key );
603       
604        irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" );
605}
606
607static void irc_cmd_rehash( irc_t *irc, char **cmd )
608{
609        if( global.conf->runmode == RUNMODE_INETD )
610                ipc_master_cmd_rehash( NULL, NULL );
611        else
612                ipc_to_master( cmd );
613       
614        irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
615}
616
617static const command_t irc_commands[] = {
618        { "pass",        1, irc_cmd_pass,        0 },
619        { "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
620        { "nick",        1, irc_cmd_nick,        0 },
621        { "quit",        0, irc_cmd_quit,        0 },
622        { "ping",        0, irc_cmd_ping,        0 },
623        { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
624        { "join",        1, irc_cmd_join,        IRC_CMD_LOGGED_IN },
625        { "names",       1, irc_cmd_names,       IRC_CMD_LOGGED_IN },
626        { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
627        { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
628        { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
629        { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
630        { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
631        { "who",         0, irc_cmd_who,         IRC_CMD_LOGGED_IN },
632        { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
633        { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
634        { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
635        { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
636        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
637        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
638        { "userhost",    1, irc_cmd_userhost,    IRC_CMD_LOGGED_IN },
639        { "ison",        1, irc_cmd_ison,        IRC_CMD_LOGGED_IN },
640        { "watch",       1, irc_cmd_watch,       IRC_CMD_LOGGED_IN },
641        { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
642#if 0
643        { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
644#endif
645        { "topic",       1, irc_cmd_topic,       IRC_CMD_LOGGED_IN },
646        { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
647        { "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
648        { "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
649        { "wallops",     1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
650        { "wall",        1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
651        { "rehash",      0, irc_cmd_rehash,      IRC_CMD_OPER_ONLY },
652        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
653        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
654        { NULL }
655};
656
657void irc_exec( irc_t *irc, char *cmd[] )
658{       
659        int i, n_arg;
660       
661        if( !cmd[0] )
662                return;
663       
664        for( i = 0; irc_commands[i].command; i++ )
665                if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 )
666                {
667                        /* There should be no typo in the next line: */
668                        for( n_arg = 0; cmd[n_arg]; n_arg ++ ); n_arg --;
669                       
670                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
671                        {
672                                irc_send_num( irc, 462, ":Only allowed before logging in" );
673                        }
674                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
675                        {
676                                irc_send_num( irc, 451, ":Register first" );
677                        }
678                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
679                        {
680                                irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
681                        }
682                        else if( n_arg < irc_commands[i].required_parameters )
683                        {
684                                irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
685                        }
686                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
687                        {
688                                /* IPC doesn't make sense in inetd mode,
689                                    but the function will catch that. */
690                                ipc_to_master( cmd );
691                        }
692                        else
693                        {
694                                irc_commands[i].execute( irc, cmd );
695                        }
696                       
697                        return;
698                }
699       
700        if( irc->status >= USTATUS_LOGGED_IN )
701                irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
702}
Note: See TracBrowser for help on using the repository browser.