source: irc_commands.c @ 5a75d15

Last change on this file since 5a75d15 was 5a75d15, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-06-05T22:32:36Z

Chatroom improvements. Merged chatroom stub into normal chatroom stuff,
restored "chat add" behaviour a little bit better (don't clean up a
channel when its room disappears, just disconnect it from the groupchat).

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