source: irc_commands.c @ e4e0b37

Last change on this file since e4e0b37 was 228fc18, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-05-23T14:31:30Z

Allow nick changes. (Based on patch from zibri) This mostly closes #6!

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