source: irc_commands.c @ 36cf9fd

Last change on this file since 36cf9fd was b75acf6, checked in by Wilmer van der Gaast <wilmer@…>, at 2009-10-22T21:55:23Z

Don't include chat.h from bitlbee.h. make install-dev doesn't install
chat.h and it shouldn't ... but things broke because bitlbee.h includes
it. Fixes #534.

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