source: irc_commands.c @ 18ff38f

Last change on this file since 18ff38f was a199d33, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-03-29T22:19:17Z

Closing bug #209: The PASS command can now be used to identify yourself
to BitlBee. The advantage: No more messing with NickServ hooks. Just set
a server password.

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