source: irc_commands.c @ d7d677d

Last change on this file since d7d677d was d7d677d, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-04-14T12:34:39Z

Restored a few more trivial commands including all the oper stuff.

  • Property mode set to 100644
File size: 17.5 KB
RevLine 
[0298d11]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[3ddb7477]4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
[0298d11]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"
[b75acf6]29#include "chat.h"
[0298d11]30
[f73b969]31static void irc_cmd_pass( irc_t *irc, char **cmd )
[0298d11]32{
[a199d33]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. */
[fb117aee]41                return root_command( irc, send_cmd );
[a199d33]42        }
43        /* Handling in pre-logged-in state, first see if this server is
44           password-protected: */
45        else if( global.conf->auth_pass &&
[c029350]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 ) )
[0298d11]49        {
[79e826a]50                irc->status |= USTATUS_AUTHORIZED;
[de3e100]51                irc_check_login( irc );
[0298d11]52        }
[a199d33]53        else if( global.conf->auth_pass )
[0298d11]54        {
[3ddb7477]55                irc_send_num( irc, 464, ":Incorrect password" );
[0298d11]56        }
[a199d33]57        else
58        {
59                /* Remember the password and try to identify after USER/NICK. */
[3ddb7477]60                /*irc_setpass( irc, cmd[1] ); */
[a199d33]61                irc_check_login( irc );
62        }
[0298d11]63}
64
[f73b969]65static void irc_cmd_user( irc_t *irc, char **cmd )
[0298d11]66{
[3ddb7477]67        irc->user->user = g_strdup( cmd[1] );
68        irc->user->fullname = g_strdup( cmd[4] );
[edf9657]69       
70        irc_check_login( irc );
[0298d11]71}
72
[f73b969]73static void irc_cmd_nick( irc_t *irc, char **cmd )
[0298d11]74{
[ffa1173]75        if( irc_user_by_name( irc, cmd[1] ) )
[0298d11]76        {
[3ddb7477]77                irc_send_num( irc, 433, ":This nick is already in use" );
[0298d11]78        }
79        else if( !nick_ok( cmd[1] ) )
80        {
81                /* [SH] Invalid characters. */
[3ddb7477]82                irc_send_num( irc, 432, ":This nick contains invalid characters" );
[0298d11]83        }
[ffa1173]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        }
[0298d11]95        else
96        {
[3ddb7477]97                irc->user->nick = g_strdup( cmd[1] );
[edf9657]98               
99                irc_check_login( irc );
[0298d11]100        }
101}
102
[f73b969]103static void irc_cmd_quit( irc_t *irc, char **cmd )
[0298d11]104{
[f73b969]105        if( cmd[1] && *cmd[1] )
106                irc_abort( irc, 0, "Quit: %s", cmd[1] );
107        else
108                irc_abort( irc, 0, "Leaving..." );
[0298d11]109}
110
[f73b969]111static void irc_cmd_ping( irc_t *irc, char **cmd )
[0298d11]112{
[ebaebfe]113        irc_write( irc, ":%s PONG %s :%s", irc->root->host,
114                   irc->root->host, cmd[1]?cmd[1]:irc->root->host );
[0298d11]115}
116
[3923003]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
[b9e020a]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 )
[57119e8]133        {
[b9e020a]134                irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] );
[57119e8]135                return;
136        }
[b9e020a]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        irc_channel_add_user( ic, irc->user );
143}
144
145static void irc_cmd_names( irc_t *irc, char **cmd )
146{
147        irc_channel_t *ic;
148       
149        if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
150                irc_send_names( ic );
151        /* With no args, we should show /names of all chans. Make the code
152           below work well if necessary.
153        else
154        {
155                GSList *l;
156               
157                for( l = irc->channels; l; l = l->next )
158                        irc_send_names( l->data );
159        }
160        */
161}
162
163static void irc_cmd_part( irc_t *irc, char **cmd )
164{
165        irc_channel_t *ic;
166       
167        if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
168        {
169                irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
170        }
171        else if( !irc_channel_del_user( ic, irc->user ) )
172        {
173                irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] );
174        }
175}
176
[b95932e]177static void irc_cmd_whois( irc_t *irc, char **cmd )
178{
179        char *nick = cmd[1];
[280c56a]180        irc_user_t *iu = irc_user_by_name( irc, nick );
[b95932e]181       
182        if( iu )
183                irc_send_whois( iu );
184        else
185                irc_send_num( irc, 401, "%s :Nick does not exist", nick );
186}
187
188static void irc_cmd_whowas( irc_t *irc, char **cmd )
189{
190        /* For some reason irssi tries a whowas when whois fails. We can
191           ignore this, but then the user never gets a "user not found"
192           message from irssi which is a bit annoying. So just respond
193           with not-found and irssi users will get better error messages */
194       
195        irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] );
196        irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] );
197}
198
[9b69eb7]199static void irc_cmd_motd( irc_t *irc, char **cmd )
200{
201        irc_send_motd( irc );
202}
203
[f73b969]204static void irc_cmd_mode( irc_t *irc, char **cmd )
[0298d11]205{
[b919363]206        if( irc_channel_name_ok( cmd[1] ) )
[0298d11]207        {
[b919363]208                irc_channel_t *ic;
209               
210                if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
211                        irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
212                else if( cmd[2] )
[0298d11]213                {
214                        if( *cmd[2] == '+' || *cmd[2] == '-' )
[3ddb7477]215                                irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
[0298d11]216                        else if( *cmd[2] == 'b' )
[3ddb7477]217                                irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
[0298d11]218                }
219                else
[b919363]220                        irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode );
[0298d11]221        }
222        else
223        {
[b919363]224                if( nick_cmp( cmd[1], irc->user->nick ) == 0 )
[0298d11]225                {
226                        if( cmd[2] )
227                                irc_umode_set( irc, cmd[2], 0 );
[2f13222]228                        else
[3ddb7477]229                                irc_send_num( irc, 221, "+%s", irc->umode );
[0298d11]230                }
231                else
[3ddb7477]232                        irc_send_num( irc, 502, ":Don't touch their modes" );
[0298d11]233        }
234}
235
[2f53ada]236static void irc_cmd_who( irc_t *irc, char **cmd )
237{
238        char *channel = cmd[1];
239        irc_channel_t *ic;
240       
241        if( !channel || *channel == '0' || *channel == '*' || !*channel )
242                irc_send_who( irc, irc->users, "**" );
243        else if( ( ic = irc_channel_by_name( irc, channel ) ) )
244                irc_send_who( irc, ic->users, channel );
245        else
246                irc_send_num( irc, 403, "%s :No such channel", channel );
247}
248
[280c56a]249static void irc_cmd_privmsg( irc_t *irc, char **cmd )
[b919363]250{
[280c56a]251        irc_channel_t *ic;
252        irc_user_t *iu;
253       
254        if( !cmd[2] ) 
[b919363]255        {
[280c56a]256                irc_send_num( irc, 412, ":No text to send" );
[24b8bbb]257                return;
[280c56a]258        }
[24b8bbb]259       
260        /* Don't treat CTCP actions as real CTCPs, just convert them right now. */
261        if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 )
262        {
263                cmd[2] += 4;
264                strcpy( cmd[2], "/me" );
265                if( cmd[2][strlen(cmd[2])-1] == '\001' )
266                        cmd[2][strlen(cmd[2])-1] = '\0';
267        }
268       
269        if( irc_channel_name_ok( cmd[1] ) &&
270            ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
[280c56a]271        {
272                if( ic->f->privmsg )
273                        ic->f->privmsg( ic, cmd[2] );
274        }
275        else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) )
276        {
[24b8bbb]277                if( cmd[2][0] == '\001' )
278                {
279                        char **ctcp;
280                       
281                        if( iu->f->ctcp == NULL )
282                                return;
283                        if( cmd[2][strlen(cmd[2])-1] == '\001' )
284                                cmd[2][strlen(cmd[2])-1] = '\0';
285                       
286                        ctcp = split_command_parts( cmd[2] + 1 );
287                        iu->f->ctcp( iu, ctcp );
288                }
289                else if( iu->f->privmsg )
[280c56a]290                        iu->f->privmsg( iu, cmd[2] );
[b919363]291        }
292        else
293        {
[280c56a]294                irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] );
[b919363]295        }
296
[0298d11]297
[280c56a]298#if 0
[9b69eb7]299        else if( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
[0298d11]300        {
301        }
302        else
303        {
304                if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
305                {
306                        unsigned int i;
[5c9512f]307                        char *t = set_getstr( &irc->set, "default_target" );
[0298d11]308                       
309                        if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
310                                cmd[1] = irc->last_target;
311                        else if( g_strcasecmp( t, "root" ) == 0 )
312                                cmd[1] = irc->mynick;
313                       
314                        for( i = 0; i < strlen( cmd[2] ); i ++ )
315                        {
316                                if( cmd[2][i] == ' ' ) break;
317                                if( cmd[2][i] == ':' || cmd[2][i] == ',' )
318                                {
319                                        cmd[1] = cmd[2];
320                                        cmd[2] += i;
321                                        *cmd[2] = 0;
322                                        while( *(++cmd[2]) == ' ' );
323                                        break;
324                                }
325                        }
326                       
327                        irc->is_private = 0;
328                       
329                        if( cmd[1] != irc->last_target )
330                        {
[f9756bd]331                                g_free( irc->last_target );
[0298d11]332                                irc->last_target = g_strdup( cmd[1] );
333                        }
334                }
335                else
336                {
337                        irc->is_private = 1;
338                }
[6bbb939]339                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
[0298d11]340        }
[280c56a]341#endif
342}
343
[d860a8d]344static void irc_cmd_nickserv( irc_t *irc, char **cmd )
345{
346        /* [SH] This aliases the NickServ command to PRIVMSG root */
347        /* [TV] This aliases the NS command to PRIVMSG root as well */
348        root_command( irc, cmd + 1 );
349}
350
[280c56a]351
352
353static void irc_cmd_oper( irc_t *irc, char **cmd )
354{
355        if( global.conf->oper_pass &&
356            ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
357                md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
358                strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
359        {
360                irc_umode_set( irc, "+o", 1 );
361                irc_send_num( irc, 381, ":Password accepted" );
362        }
363        else
364        {
365                irc_send_num( irc, 432, ":Incorrect password" );
366        }
367}
368
[d7d677d]369#if 0
[280c56a]370static void irc_cmd_invite( irc_t *irc, char **cmd )
371{
372        char *nick = cmd[1], *channel = cmd[2];
373        struct groupchat *c = irc_chat_by_channel( irc, channel );
374        user_t *u = user_find( irc, nick );
375       
376        if( u && c && ( u->ic == c->ic ) )
377                if( c->ic && c->ic->acc->prpl->chat_invite )
378                {
379                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
380                        irc_send_num( irc, 341, "%s %s", nick, channel );
381                        return;
382                }
383       
384        irc_send_num( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
[0298d11]385}
386
[f73b969]387static void irc_cmd_userhost( irc_t *irc, char **cmd )
[0298d11]388{
389        user_t *u;
390        int i;
391       
392        /* [TV] Usable USERHOST-implementation according to
393                RFC1459. Without this, mIRC shows an error
394                while connecting, and the used way of rejecting
395                breaks standards.
396        */
397       
398        for( i = 1; cmd[i]; i ++ )
399                if( ( u = user_find( irc, cmd[i] ) ) )
400                {
401                        if( u->online && u->away )
[3ddb7477]402                                irc_send_num( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
[0298d11]403                        else
[3ddb7477]404                                irc_send_num( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
[0298d11]405                }
406}
407
[f73b969]408static void irc_cmd_ison( irc_t *irc, char **cmd )
[0298d11]409{
410        user_t *u;
[b4e4b95]411        char buff[IRC_MAX_LINE];
[0298d11]412        int lenleft, i;
413       
414        buff[0] = '\0';
415       
416        /* [SH] Leave room for : and \0 */
417        lenleft = IRC_MAX_LINE - 2;
418       
419        for( i = 1; cmd[i]; i ++ )
420        {
[42616d1]421                char *this, *next;
422               
423                this = cmd[i];
424                while( *this )
[0298d11]425                {
[42616d1]426                        if( ( next = strchr( this, ' ' ) ) )
427                                *next = 0;
[0298d11]428                       
[42616d1]429                        if( ( u = user_find( irc, this ) ) && u->online )
[0298d11]430                        {
[42616d1]431                                lenleft -= strlen( u->nick ) + 1;
432                               
433                                if( lenleft < 0 )
434                                        break;
435                               
436                                strcat( buff, u->nick );
437                                strcat( buff, " " );
[0298d11]438                        }
439                       
[42616d1]440                        if( next )
441                        {
442                                *next = ' ';
443                                this = next + 1;
444                        }
445                        else
446                        {
447                                break;
448                        }   
[0298d11]449                }
[42616d1]450               
451                /* *sigh* */
452                if( lenleft < 0 )
453                        break;
[0298d11]454        }
455       
456        if( strlen( buff ) > 0 )
457                buff[strlen(buff)-1] = '\0';
458       
[3ddb7477]459        irc_send_num( irc, 303, ":%s", buff );
[0298d11]460}
461
[f73b969]462static void irc_cmd_watch( irc_t *irc, char **cmd )
[0298d11]463{
464        int i;
465       
466        /* Obviously we could also mark a user structure as being
467           watched, but what if the WATCH command is sent right
468           after connecting? The user won't exist yet then... */
469        for( i = 1; cmd[i]; i ++ )
470        {
471                char *nick;
472                user_t *u;
473               
474                if( !cmd[i][0] || !cmd[i][1] )
475                        break;
476               
477                nick = g_strdup( cmd[i] + 1 );
478                nick_lc( nick );
479               
480                u = user_find( irc, nick );
481               
482                if( cmd[i][0] == '+' )
483                {
484                        if( !g_hash_table_lookup( irc->watches, nick ) )
485                                g_hash_table_insert( irc->watches, nick, nick );
486                       
487                        if( u && u->online )
[3ddb7477]488                                irc_send_num( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
[0298d11]489                        else
[3ddb7477]490                                irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
[0298d11]491                }
492                else if( cmd[i][0] == '-' )
493                {
494                        gpointer okey, ovalue;
495                       
496                        if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
497                        {
498                                g_hash_table_remove( irc->watches, okey );
[e59b4f6]499                                g_free( okey );
[0298d11]500                               
[3ddb7477]501                                irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
[0298d11]502                        }
503                }
504        }
505}
506
[f73b969]507static void irc_cmd_topic( irc_t *irc, char **cmd )
[0298d11]508{
[50e1776]509        char *channel = cmd[1];
510        char *topic = cmd[2];
511       
512        if( topic )
513        {
514                /* Send the topic */
515                struct groupchat *c = irc_chat_by_channel( irc, channel );
516                if( c && c->ic && c->ic->acc->prpl->chat_topic )
517                        c->ic->acc->prpl->chat_topic( c, topic );
518        }
[0298d11]519        else
[50e1776]520        {
521                /* Get the topic */
522                irc_topic( irc, channel );
523        }
[0298d11]524}
[81186cab]525#endif
[0298d11]526
[f73b969]527static void irc_cmd_away( irc_t *irc, char **cmd )
[0298d11]528{
[81186cab]529        char *set;
[0298d11]530       
[81186cab]531        if( cmd[1] && *cmd[1] )
[0298d11]532        {
[81186cab]533                char away[strlen(cmd[1])+1];
[0298d11]534                int i, j;
535               
536                /* Copy away string, but skip control chars. Mainly because
537                   Jabber really doesn't like them. */
[81186cab]538                for( i = j = 0; cmd[1][i]; i ++ )
539                        if( ( away[j] = cmd[1][i] ) >= ' ' )
[0298d11]540                                j ++;
[81186cab]541                away[j] = '\0';
[0298d11]542               
[81186cab]543                irc_send_num( irc, 306, ":You're now away: %s", away );
544                set = away;
[0298d11]545        }
546        else
547        {
[3ddb7477]548                irc_send_num( irc, 305, ":Welcome back" );
[81186cab]549                set = NULL;
[0298d11]550        }
551       
[81186cab]552        set_setstr( &irc->b->set, "away", set );
[0298d11]553}
554
[82898af]555static void irc_cmd_version( irc_t *irc, char **cmd )
556{
[d7d677d]557        irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ",
558                      BITLBEE_VERSION, irc->root->host, ARCH, CPU );
[82898af]559}
560
[f73b969]561static void irc_cmd_completions( irc_t *irc, char **cmd )
[0298d11]562{
563        help_t *h;
564        set_t *s;
565        int i;
566       
[d7d677d]567        irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" );
[0298d11]568       
569        for( i = 0; commands[i].command; i ++ )
[d7d677d]570                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command );
[0298d11]571       
572        for( h = global.help; h; h = h->next )
[d7d677d]573                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title );
[0298d11]574       
[d7d677d]575        for( s = irc->b->set; s; s = s->next )
576                irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key );
[0298d11]577       
[d7d677d]578        irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" );
[0298d11]579}
580
[f73b969]581static void irc_cmd_rehash( irc_t *irc, char **cmd )
[f4a5940]582{
[5424c76]583        if( global.conf->runmode == RUNMODE_INETD )
584                ipc_master_cmd_rehash( NULL, NULL );
585        else
586                ipc_to_master( cmd );
[f4a5940]587       
[3ddb7477]588        irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
[f4a5940]589}
590
[0298d11]591static const command_t irc_commands[] = {
[a199d33]592        { "pass",        1, irc_cmd_pass,        0 },
[0298d11]593        { "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
594        { "nick",        1, irc_cmd_nick,        0 },
595        { "quit",        0, irc_cmd_quit,        0 },
596        { "ping",        0, irc_cmd_ping,        0 },
[3923003]597        { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
[b9e020a]598        { "join",        1, irc_cmd_join,        IRC_CMD_LOGGED_IN },
599        { "names",       1, irc_cmd_names,       IRC_CMD_LOGGED_IN },
600        { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
[b95932e]601        { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
602        { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
[9b69eb7]603        { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
[b919363]604        { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
[2f53ada]605        { "who",         0, irc_cmd_who,         IRC_CMD_LOGGED_IN },
[280c56a]606        { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
[d860a8d]607        { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
608        { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
[81186cab]609        { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
[d7d677d]610        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
611        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
[0298d11]612        { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
[d7d677d]613#if 0
[0298d11]614        { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
615        { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
616        { "userhost",    1, irc_cmd_userhost,    IRC_CMD_LOGGED_IN },
617        { "ison",        1, irc_cmd_ison,        IRC_CMD_LOGGED_IN },
618        { "watch",       1, irc_cmd_watch,       IRC_CMD_LOGGED_IN },
619        { "topic",       1, irc_cmd_topic,       IRC_CMD_LOGGED_IN },
[d7d677d]620#endif
[0431ea1]621        { "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[565a1ea]622        { "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[48721c3]623        { "wallops",     1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[dfc8a46]624        { "wall",        1, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[f4a5940]625        { "rehash",      0, irc_cmd_rehash,      IRC_CMD_OPER_ONLY },
[54879ab]626        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[48721c3]627        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
[0298d11]628        { NULL }
629};
630
[f73b969]631void irc_exec( irc_t *irc, char *cmd[] )
[0298d11]632{       
[f1d38f2]633        int i, n_arg;
[0298d11]634       
635        if( !cmd[0] )
[f73b969]636                return;
[0298d11]637       
638        for( i = 0; irc_commands[i].command; i++ )
639                if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 )
640                {
[f1d38f2]641                        /* There should be no typo in the next line: */
642                        for( n_arg = 0; cmd[n_arg]; n_arg ++ ); n_arg --;
643                       
[79e826a]644                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
[edf9657]645                        {
[3ddb7477]646                                irc_send_num( irc, 462, ":Only allowed before logging in" );
[edf9657]647                        }
[3af70b0]648                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
[edf9657]649                        {
[3ddb7477]650                                irc_send_num( irc, 451, ":Register first" );
[edf9657]651                        }
[f73b969]652                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
[edf9657]653                        {
[3ddb7477]654                                irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
[edf9657]655                        }
[f1d38f2]656                        else if( n_arg < irc_commands[i].required_parameters )
[f73b969]657                        {
[3ddb7477]658                                irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
[f73b969]659                        }
660                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
661                        {
[5424c76]662                                /* IPC doesn't make sense in inetd mode,
663                                    but the function will catch that. */
[0431ea1]664                                ipc_to_master( cmd );
[f73b969]665                        }
[0431ea1]666                        else
[f73b969]667                        {
668                                irc_commands[i].execute( irc, cmd );
669                        }
670                       
[2f13222]671                        return;
[0298d11]672                }
[2f13222]673       
674        if( irc->status >= USTATUS_LOGGED_IN )
[3ddb7477]675                irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
[0298d11]676}
Note: See TracBrowser for help on using the repository browser.