source: irc_commands.c @ 39f93f0

Last change on this file since 39f93f0 was 39f93f0, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-08-31T13:42:33Z

/join can now be used to join chatrooms, join_chat should not be used
anymore. /join should not be used for unnamed groupchats anymore, use
"chat with" instead.

  • Property mode set to 100644
File size: 18.4 KB
RevLine 
[0298d11]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"
[0431ea1]28#include "ipc.h"
[0298d11]29
[f73b969]30static void irc_cmd_pass( irc_t *irc, char **cmd )
[0298d11]31{
[a199d33]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 &&
[c029350]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 ) )
[0298d11]48        {
[79e826a]49                irc->status |= USTATUS_AUTHORIZED;
[de3e100]50                irc_check_login( irc );
[0298d11]51        }
[a199d33]52        else if( global.conf->auth_pass )
[0298d11]53        {
[b23c5c7]54                irc_reply( irc, 464, ":Incorrect password" );
[0298d11]55        }
[a199d33]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        }
[0298d11]62}
63
[f73b969]64static void irc_cmd_user( irc_t *irc, char **cmd )
[0298d11]65{
[edf9657]66        irc->user = g_strdup( cmd[1] );
67        irc->realname = g_strdup( cmd[4] );
68       
69        irc_check_login( irc );
[0298d11]70}
71
[f73b969]72static void irc_cmd_nick( irc_t *irc, char **cmd )
[0298d11]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] );
[edf9657]91               
92                irc_check_login( irc );
[0298d11]93        }
94}
95
[f73b969]96static void irc_cmd_quit( irc_t *irc, char **cmd )
[0298d11]97{
[f73b969]98        if( cmd[1] && *cmd[1] )
99                irc_abort( irc, 0, "Quit: %s", cmd[1] );
100        else
101                irc_abort( irc, 0, "Leaving..." );
[0298d11]102}
103
[f73b969]104static void irc_cmd_ping( irc_t *irc, char **cmd )
[0298d11]105{
106        irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
107}
108
[f73b969]109static void irc_cmd_oper( irc_t *irc, char **cmd )
[0298d11]110{
[ec0355f]111        if( global.conf->oper_pass &&
[c029350]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 ) )
[b23c5c7]115        {
[0298d11]116                irc_umode_set( irc, "+o", 1 );
[b23c5c7]117                irc_reply( irc, 381, ":Password accepted" );
118        }
119        else
120        {
121                irc_reply( irc, 432, ":Incorrect password" );
122        }
[0298d11]123}
124
[f73b969]125static void irc_cmd_mode( irc_t *irc, char **cmd )
[0298d11]126{
[39f93f0]127        if( strchr( CTYPES, *cmd[1] ) )
[0298d11]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 );
[2f13222]145                        else
146                                irc_reply( irc, 221, "+%s", irc->umode );
[0298d11]147                }
148                else
149                        irc_reply( irc, 502, ":Don't touch their modes" );
150        }
151}
152
[f73b969]153static void irc_cmd_names( irc_t *irc, char **cmd )
[0298d11]154{
155        irc_names( irc, cmd[1]?cmd[1]:irc->channel );
156}
157
[f73b969]158static void irc_cmd_part( irc_t *irc, char **cmd )
[0298d11]159{
[0da65d5]160        struct groupchat *c;
[0298d11]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        }
[0e7ab64]170        else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) )
[0298d11]171        {
172                user_t *u = user_find( irc, irc->nick );
173               
174                irc_part( irc, u, c->channel );
175               
[0da65d5]176                if( c->ic )
[0298d11]177                {
178                        c->joined = 0;
[0da65d5]179                        c->ic->acc->prpl->chat_leave( c );
[0298d11]180                }
181        }
182        else
183        {
184                irc_reply( irc, 403, "%s :No such channel", cmd[1] );
185        }
186}
187
[f73b969]188static void irc_cmd_join( irc_t *irc, char **cmd )
[0298d11]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        {
[39f93f0]195                struct groupchat *gc;
196                struct chat *c;
197                user_t *u;
198               
199                if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 )
200                {
201                        irc_reply( irc, 403, "%s :No such channel", cmd[1] );
202                        return;
203                }
204               
205                if( ( c = chat_bychannel( irc, cmd[1] ) ) )
[0298d11]206                {
[39f93f0]207                        char *nick = set_getstr( &c->set, "nick" );
[0298d11]208                       
[39f93f0]209                        if( nick == NULL )
210                                nick = irc->nick;
211                       
212                        if( ( gc = c->acc->prpl->chat_join( c->acc->ic, c->handle, nick, NULL ) ) )
[0298d11]213                        {
[39f93f0]214                                g_free( gc->channel );
215                                gc->channel = g_strdup( c->channel );
[0298d11]216                        }
217                }
218                else
219                {
220                        irc_reply( irc, 403, "%s :No such channel", cmd[1] );
221                }
222        }
223}
224
[f73b969]225static void irc_cmd_invite( irc_t *irc, char **cmd )
[0298d11]226{
227        char *nick = cmd[1], *channel = cmd[2];
[0e7ab64]228        struct groupchat *c = irc_chat_by_channel( irc, channel );
[0298d11]229        user_t *u = user_find( irc, nick );
230       
[0da65d5]231        if( u && c && ( u->ic == c->ic ) )
232                if( c->ic && c->ic->acc->prpl->chat_invite )
[0298d11]233                {
[c058ff9]234                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
[0298d11]235                        irc_reply( irc, 341, "%s %s", nick, channel );
[f73b969]236                        return;
[0298d11]237                }
238       
239        irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
240}
241
[f73b969]242static void irc_cmd_privmsg( irc_t *irc, char **cmd )
[0298d11]243{
244        if ( !cmd[2] ) 
245        {
246                irc_reply( irc, 412, ":No text to send" );
247        }
248        else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 ) 
249        {
250                irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] ); 
251        }
252        else 
253        {
254                if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
255                {
256                        unsigned int i;
[5c9512f]257                        char *t = set_getstr( &irc->set, "default_target" );
[0298d11]258                       
259                        if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
260                                cmd[1] = irc->last_target;
261                        else if( g_strcasecmp( t, "root" ) == 0 )
262                                cmd[1] = irc->mynick;
263                       
264                        for( i = 0; i < strlen( cmd[2] ); i ++ )
265                        {
266                                if( cmd[2][i] == ' ' ) break;
267                                if( cmd[2][i] == ':' || cmd[2][i] == ',' )
268                                {
269                                        cmd[1] = cmd[2];
270                                        cmd[2] += i;
271                                        *cmd[2] = 0;
272                                        while( *(++cmd[2]) == ' ' );
273                                        break;
274                                }
275                        }
276                       
277                        irc->is_private = 0;
278                       
279                        if( cmd[1] != irc->last_target )
280                        {
[f9756bd]281                                g_free( irc->last_target );
[0298d11]282                                irc->last_target = g_strdup( cmd[1] );
283                        }
284                }
285                else
286                {
287                        irc->is_private = 1;
288                }
[6bbb939]289                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
[0298d11]290        }
291}
292
[f73b969]293static void irc_cmd_who( irc_t *irc, char **cmd )
[0298d11]294{
295        char *channel = cmd[1];
296        user_t *u = irc->users;
[0da65d5]297        struct groupchat *c;
[0298d11]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                }
[0e7ab64]313        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
[0298d11]314                for( l = c->in_room; l; l = l->next )
315                {
[0da65d5]316                        if( ( u = user_findhandle( c->ic, l->data ) ) )
[0298d11]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       
[b23c5c7]322        irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" );
[0298d11]323}
324
[f73b969]325static void irc_cmd_userhost( irc_t *irc, char **cmd )
[0298d11]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
[f73b969]346static void irc_cmd_ison( irc_t *irc, char **cmd )
[0298d11]347{
348        user_t *u;
[b4e4b95]349        char buff[IRC_MAX_LINE];
[0298d11]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        {
[42616d1]359                char *this, *next;
360               
361                this = cmd[i];
362                while( *this )
[0298d11]363                {
[42616d1]364                        if( ( next = strchr( this, ' ' ) ) )
365                                *next = 0;
[0298d11]366                       
[42616d1]367                        if( ( u = user_find( irc, this ) ) && u->online )
[0298d11]368                        {
[42616d1]369                                lenleft -= strlen( u->nick ) + 1;
370                               
371                                if( lenleft < 0 )
372                                        break;
373                               
374                                strcat( buff, u->nick );
375                                strcat( buff, " " );
[0298d11]376                        }
377                       
[42616d1]378                        if( next )
379                        {
380                                *next = ' ';
381                                this = next + 1;
382                        }
383                        else
384                        {
385                                break;
386                        }   
[0298d11]387                }
[42616d1]388               
389                /* *sigh* */
390                if( lenleft < 0 )
391                        break;
[0298d11]392        }
393       
394        if( strlen( buff ) > 0 )
395                buff[strlen(buff)-1] = '\0';
396       
397        irc_reply( irc, 303, ":%s", buff );
398}
399
[f73b969]400static void irc_cmd_watch( irc_t *irc, char **cmd )
[0298d11]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 )
[fc630f9]426                                irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
[0298d11]427                        else
[fc630f9]428                                irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
[0298d11]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
[f73b969]445static void irc_cmd_topic( irc_t *irc, char **cmd )
[0298d11]446{
[50e1776]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        }
[0298d11]457        else
[50e1776]458        {
459                /* Get the topic */
460                irc_topic( irc, channel );
461        }
[0298d11]462}
463
[f73b969]464static void irc_cmd_away( irc_t *irc, char **cmd )
[0298d11]465{
466        user_t *u = user_find( irc, irc->nick );
467        char *away = cmd[1];
[a91ecee]468        account_t *a;
[0298d11]469       
[f73b969]470        if( !u ) return;
[0298d11]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       
[a91ecee]495        for( a = irc->accounts; a; a = a->next )
[0298d11]496        {
[0da65d5]497                struct im_connection *ic = a->ic;
[0298d11]498               
[0da65d5]499                if( ic && ic->flags & OPT_LOGGED_IN )
[84b045d]500                        imc_set_away( ic, u->away );
[0298d11]501        }
502}
503
[f73b969]504static void irc_cmd_whois( irc_t *irc, char **cmd )
[0298d11]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               
[0da65d5]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 );
[0298d11]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
[f73b969]533static void irc_cmd_whowas( irc_t *irc, char **cmd )
[0298d11]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
[f73b969]544static void irc_cmd_nickserv( irc_t *irc, char **cmd )
[0298d11]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
[f73b969]551static void irc_cmd_motd( irc_t *irc, char **cmd )
[0298d11]552{
553        irc_motd( irc );
554}
555
[f73b969]556static void irc_cmd_pong( irc_t *irc, char **cmd )
[0298d11]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
[82898af]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
[f73b969]569static void irc_cmd_completions( irc_t *irc, char **cmd )
[0298d11]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 )
[0fbda193]582                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->title );
[0298d11]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
[f73b969]590static void irc_cmd_rehash( irc_t *irc, char **cmd )
[f4a5940]591{
[5424c76]592        if( global.conf->runmode == RUNMODE_INETD )
593                ipc_master_cmd_rehash( NULL, NULL );
594        else
595                ipc_to_master( cmd );
[f4a5940]596       
[eeb85a8]597        irc_reply( irc, 382, "%s :Rehashing", global.conf_file );
[f4a5940]598}
599
[0298d11]600static const command_t irc_commands[] = {
[a199d33]601        { "pass",        1, irc_cmd_pass,        0 },
[0298d11]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 },
[82898af]626        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
[0298d11]627        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
[0431ea1]628        { "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[565a1ea]629        { "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[48721c3]630        { "wallops",     1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[dfc8a46]631        { "wall",        1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[f4a5940]632        { "rehash",      0, irc_cmd_rehash,      IRC_CMD_OPER_ONLY },
[54879ab]633        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[48721c3]634        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[0298d11]635        { NULL }
636};
637
[f73b969]638void irc_exec( irc_t *irc, char *cmd[] )
[0298d11]639{       
[f1d38f2]640        int i, n_arg;
[0298d11]641       
642        if( !cmd[0] )
[f73b969]643                return;
[0298d11]644       
645        for( i = 0; irc_commands[i].command; i++ )
646                if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 )
647                {
[f1d38f2]648                        /* There should be no typo in the next line: */
649                        for( n_arg = 0; cmd[n_arg]; n_arg ++ ); n_arg --;
650                       
[79e826a]651                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
[edf9657]652                        {
653                                irc_reply( irc, 462, ":Only allowed before logging in" );
654                        }
[3af70b0]655                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
[edf9657]656                        {
657                                irc_reply( irc, 451, ":Register first" );
658                        }
[f73b969]659                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
[edf9657]660                        {
661                                irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" );
662                        }
[f1d38f2]663                        else if( n_arg < irc_commands[i].required_parameters )
[f73b969]664                        {
665                                irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
666                        }
667                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
668                        {
[5424c76]669                                /* IPC doesn't make sense in inetd mode,
670                                    but the function will catch that. */
[0431ea1]671                                ipc_to_master( cmd );
[f73b969]672                        }
[0431ea1]673                        else
[f73b969]674                        {
675                                irc_commands[i].execute( irc, cmd );
676                        }
677                       
[2f13222]678                        return;
[0298d11]679                }
[2f13222]680       
681        if( irc->status >= USTATUS_LOGGED_IN )
682                irc_reply( irc, 421, "%s :Unknown command", cmd[0] );
[0298d11]683}
Note: See TracBrowser for help on using the repository browser.