Changes in / [9d6b229:0431ea1]


Ignore:
Files:
3 added
6 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r9d6b229 r0431ea1  
    1010
    1111# Program variables
    12 objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o irc.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o
     12objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o set.o storage.o storage_text.o unix.o url.o user.o util.o
    1313subdirs = protocols
    1414
  • bitlbee.c

    r9d6b229 r0431ea1  
    2929#include "protocols/nogaim.h"
    3030#include "help.h"
     31#include "ipc.h"
    3132#include <signal.h>
    3233#include <stdio.h>
    3334#include <errno.h>
    3435
    35 struct bitlbee_child
    36 {
    37         pid_t pid;
    38         int ipc_fd;
    39         gint ipc_inpa;
    40 };
    41 
    42 static GSList *child_list = NULL;
    43 
    4436gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data );
    45  
     37
    4638int bitlbee_daemon_init()
    4739{
     
    232224}
    233225
    234 gboolean bitlbee_io_master_ipc_read( gpointer data, gint source, GaimInputCondition cond );
    235 gboolean bitlbee_io_child_ipc_read( gpointer data, gint source, GaimInputCondition cond );
    236 
    237226gboolean bitlbee_io_new_client( GIOChannel *source, GIOCondition condition, gpointer data )
    238227{
     
    264253                        child->pid = client_pid;
    265254                        child->ipc_fd = fds[0];
    266                         child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, bitlbee_io_master_ipc_read, child );
     255                        child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    267256                        child_list = g_slist_append( child_list, child );
    268257                       
     258                        log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", client_pid );
     259                       
     260                        /* Close some things we don't need in the parent process. */
     261                        close( new_socket );
    269262                        close( fds[1] );
    270263                }
    271264                else if( client_pid == 0 )
    272265                {
     266                        irc_t *irc;
     267                       
    273268                        /* Close the listening socket, we're a client. */
    274269                        close( global.listen_socket );
    275270                        g_source_remove( global.listen_watch_source_id );
    276271                       
     272                        /* Make the connection. */
     273                        irc = irc_new( new_socket );
     274                       
    277275                        /* We can store the IPC fd there now. */
    278276                        global.listen_socket = fds[1];
    279                         global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, bitlbee_io_child_ipc_read, NULL );
     277                        global.listen_watch_source_id = gaim_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
    280278                       
    281279                        close( fds[0] );
    282280                }
    283281        }
    284        
    285         if( client_pid == 0 )
     282        else
    286283        {
    287284                log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket );
    288285                irc_new( new_socket );
    289         }
    290         else
    291         {
    292                 /* We don't need this one, only the client does. */
    293                 close( new_socket );
    294286        }
    295287       
     
    306298        g_main_quit( global.loop );
    307299}
    308 
    309 gboolean bitlbee_io_master_ipc_read( gpointer data, gint source, GaimInputCondition cond )
    310 {
    311         struct bitlbee_child *child = data;
    312         char buf[513], *eol;
    313         int size;
    314        
    315         size = recv( child->ipc_fd, buf, sizeof( buf ) - 1, MSG_PEEK );
    316        
    317         if( size < 0 || ( size < 0 && !sockerr_again() ) )
    318                 goto error_abort;
    319         else
    320                 buf[size] = 0;
    321        
    322         eol = strstr( buf, "\r\n" );
    323         if( eol == NULL )
    324                 goto error_abort;
    325        
    326         size = recv( child->ipc_fd, buf, eol - buf + 2, 0 );
    327         buf[size] = 0;
    328        
    329         if( strcmp( buf, "DIE\r\n" ) == 0 )
    330         {
    331                 printf( "Bye...\n" );
    332                 exit( 0 );
    333         }
    334        
    335         return TRUE;
    336        
    337 error_abort:
    338         {
    339                 GSList *l;
    340                 struct bitlbee_child *c;
    341                
    342                 for( l = child_list; l; l = l->next )
    343                 {
    344                         c = l->data;
    345                         if( c->ipc_fd == source )
    346                         {
    347                                 close( c->ipc_fd );
    348                                 gaim_input_remove( c->ipc_inpa );
    349                                 g_free( c );
    350                                
    351                                 child_list = g_slist_remove( child_list, l );
    352                                
    353                                 break;
    354                         }
    355                 }
    356                
    357                 return FALSE;
    358         }
    359 }
    360 
    361 gboolean bitlbee_io_child_ipc_read( gpointer data, gint source, GaimInputCondition cond )
    362 {
    363         return TRUE;
    364 }
  • commands.c

    r9d6b229 r0431ea1  
    3232#include <string.h>
    3333
    34 const command_t commands[] = {
    35         { "help",           0, cmd_help },
    36         { "identify",       1, cmd_identify },
    37         { "register",       1, cmd_register },
    38         { "drop",           1, cmd_drop },
    39         { "account",        1, cmd_account },
    40         { "add",            2, cmd_add },
    41         { "info",           1, cmd_info },
    42         { "rename",         2, cmd_rename },
    43         { "remove",         1, cmd_remove },
    44         { "block",          1, cmd_block },
    45         { "allow",          1, cmd_allow },
    46         { "save",           0, cmd_save },
    47         { "set",            0, cmd_set },
    48         { "yes",            0, cmd_yesno },
    49         { "no",             0, cmd_yesno },
    50         { "blist",          0, cmd_blist },
    51         { "nick",           1, cmd_nick },
    52         { "import_buddies", 1, cmd_import_buddies },
    53         { "qlist",          0, cmd_qlist },
    54         { NULL }
    55 };
    56 
    5734int root_command_string( irc_t *irc, user_t *u, char *command, int flags )
    5835{
     
    11491}
    11592
    116 int cmd_help( irc_t *irc, char **cmd )
     93static int cmd_help( irc_t *irc, char **cmd )
    11794{
    11895        char param[80];
     
    143120}
    144121
    145 int cmd_identify( irc_t *irc, char **cmd )
     122static int cmd_identify( irc_t *irc, char **cmd )
    146123{
    147124        storage_status_t status = storage_load( irc->nick, cmd[1], irc );
     
    166143}
    167144
    168 int cmd_register( irc_t *irc, char **cmd )
     145static int cmd_register( irc_t *irc, char **cmd )
    169146{
    170147        if( global.conf->authmode == AUTHMODE_REGISTERED )
     
    193170}
    194171
    195 int cmd_drop( irc_t *irc, char **cmd )
     172static int cmd_drop( irc_t *irc, char **cmd )
    196173{
    197174        storage_status_t status;
     
    217194}
    218195
    219 int cmd_account( irc_t *irc, char **cmd )
     196static int cmd_account( irc_t *irc, char **cmd )
    220197{
    221198        account_t *a;
     
    377354}
    378355
    379 int cmd_add( irc_t *irc, char **cmd )
     356static int cmd_add( irc_t *irc, char **cmd )
    380357{
    381358        account_t *a;
     
    417394}
    418395
    419 int cmd_info( irc_t *irc, char **cmd )
     396static int cmd_info( irc_t *irc, char **cmd )
    420397{
    421398        struct gaim_connection *gc;
     
    454431}
    455432
    456 int cmd_rename( irc_t *irc, char **cmd )
     433static int cmd_rename( irc_t *irc, char **cmd )
    457434{
    458435        user_t *u;
     
    495472}
    496473
    497 int cmd_remove( irc_t *irc, char **cmd )
     474static int cmd_remove( irc_t *irc, char **cmd )
    498475{
    499476        user_t *u;
     
    517494}
    518495
    519 int cmd_block( irc_t *irc, char **cmd )
     496static int cmd_block( irc_t *irc, char **cmd )
    520497{
    521498        struct gaim_connection *gc;
     
    558535}
    559536
    560 int cmd_allow( irc_t *irc, char **cmd )
     537static int cmd_allow( irc_t *irc, char **cmd )
    561538{
    562539        struct gaim_connection *gc;
     
    600577}
    601578
    602 int cmd_yesno( irc_t *irc, char **cmd )
     579static int cmd_yesno( irc_t *irc, char **cmd )
    603580{
    604581        query_t *q = NULL;
     
    640617}
    641618
    642 int cmd_set( irc_t *irc, char **cmd )
     619static int cmd_set( irc_t *irc, char **cmd )
    643620{
    644621        if( cmd[1] && cmd[2] )
     
    666643}
    667644
    668 int cmd_save( irc_t *irc, char **cmd )
     645static int cmd_save( irc_t *irc, char **cmd )
    669646{
    670647        if( storage_save( irc, TRUE ) == STORAGE_OK )
     
    676653}
    677654
    678 int cmd_blist( irc_t *irc, char **cmd )
     655static int cmd_blist( irc_t *irc, char **cmd )
    679656{
    680657        int online = 0, away = 0, offline = 0;
     
    722699}
    723700
    724 int cmd_nick( irc_t *irc, char **cmd )
     701static int cmd_nick( irc_t *irc, char **cmd )
    725702{
    726703        account_t *a;
     
    758735}
    759736
    760 int cmd_qlist( irc_t *irc, char **cmd )
     737static int cmd_qlist( irc_t *irc, char **cmd )
    761738{
    762739        query_t *q = irc->queries;
     
    780757}
    781758
    782 int cmd_import_buddies( irc_t *irc, char **cmd )
     759static int cmd_import_buddies( irc_t *irc, char **cmd )
    783760{
    784761        struct gaim_connection *gc;
     
    832809        return( 0 );
    833810}
     811
     812const command_t commands[] = {
     813        { "help",           0, cmd_help,           0 },
     814        { "identify",       1, cmd_identify,       0 },
     815        { "register",       1, cmd_register,       0 },
     816        { "drop",           1, cmd_drop,           0 },
     817        { "account",        1, cmd_account,        0 },
     818        { "add",            2, cmd_add,            0 },
     819        { "info",           1, cmd_info,           0 },
     820        { "rename",         2, cmd_rename,         0 },
     821        { "remove",         1, cmd_remove,         0 },
     822        { "block",          1, cmd_block,          0 },
     823        { "allow",          1, cmd_allow,          0 },
     824        { "save",           0, cmd_save,           0 },
     825        { "set",            0, cmd_set,            0 },
     826        { "yes",            0, cmd_yesno,          0 },
     827        { "no",             0, cmd_yesno,          0 },
     828        { "blist",          0, cmd_blist,          0 },
     829        { "nick",           1, cmd_nick,           0 },
     830        { "import_buddies", 1, cmd_import_buddies, 0 },
     831        { "qlist",          0, cmd_qlist,          0 },
     832        { NULL }
     833};
  • commands.h

    r9d6b229 r0431ea1  
    2929#include "bitlbee.h"
    3030
    31 typedef struct command_t
     31typedef struct command
    3232{
    3333        char *command;
    3434        int required_parameters;
    3535        int (*execute)(irc_t *, char **args);
     36        int flags;
    3637} command_t;
    37 
    38 int cmd_account( irc_t *irc, char **cmd );
    39 int cmd_help( irc_t *irc, char **args);
    40 int cmd_info( irc_t *irc, char **args);
    41 int cmd_add( irc_t *irc, char **args) ;
    42 int cmd_rename( irc_t *irc, char **args );
    43 int cmd_remove( irc_t *irc, char **args );
    44 int cmd_block( irc_t *irc, char **args );
    45 int cmd_allow( irc_t *irc, char **args );
    46 int cmd_save( irc_t *irc, char **args );
    47 int cmd_set( irc_t *irc, char **args );
    48 int cmd_yesno( irc_t *irc, char **args );
    49 int cmd_identify( irc_t *irc, char **args );
    50 int cmd_register( irc_t *irc, char **args );
    51 int cmd_drop( irc_t *irc, char **args );
    52 int cmd_blist( irc_t *irc, char **cmd );
    53 int cmd_nick( irc_t *irc, char **cmd );
    54 int cmd_qlist( irc_t *irc, char **cmd );
    55 int cmd_import_buddies( irc_t *irc, char **cmd );
    56 int cmd_dump( irc_t *irc, char **cmd );
    5738
    5839extern const command_t commands[];
    5940
     41#define IRC_CMD_PRE_LOGIN       1
     42#define IRC_CMD_LOGGED_IN       2
     43#define IRC_CMD_OPER_ONLY       4
     44#define IRC_CMD_TO_MASTER       8
     45
    6046#endif
  • irc.c

    r9d6b229 r0431ea1  
    293293int irc_process( irc_t *irc )
    294294{
    295         char **lines, *temp;   
     295        char **lines, *temp, **cmd;
    296296        int i;
    297297
    298         if( irc->readbuffer != NULL ) {
    299                 lines = irc_tokenize(irc->readbuffer );
    300                 for( i = 0; *lines[i] != '\0'; i++ ) {
    301                         if( lines[i+1] == NULL ) {
     298        if( irc->readbuffer != NULL )
     299        {
     300                lines = irc_tokenize( irc->readbuffer );
     301               
     302                for( i = 0; *lines[i] != '\0'; i ++ )
     303                {
     304                        if( lines[i+1] == NULL )
     305                        {
    302306                                temp = g_strdup( lines[i] );
    303307                                g_free( irc->readbuffer );
    304308                                irc->readbuffer = temp;
    305                                 i++;
     309                                i ++;
    306310                                break;
    307311                        }                       
    308                         if (!irc_process_line(irc, lines[i])) {
     312                       
     313                        if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     314                                continue;
     315                        if( !irc_exec( irc, cmd ) )
     316                        {
     317                                g_free( cmd );
    309318                                g_free( lines );
    310319                                return 0;
    311320                        }
    312                 }
    313                 if(lines[i]!=NULL) {
    314                         g_free(irc->readbuffer);
    315                         irc->readbuffer=NULL;   
    316                 }
     321                       
     322                        g_free( cmd );
     323                }
     324               
     325                if( lines[i] != NULL )
     326                {
     327                        g_free( irc->readbuffer );
     328                        irc->readbuffer = NULL;
     329                }
     330               
    317331                g_free( lines );
    318332        }
     333       
    319334        return 1;       
    320335}
     
    326341
    327342        /* Count the number of elements we're gonna need. */
    328         for(i=0, j=1; buffer[i]!='\0'; i++ ) {
    329                 if(buffer[i]=='\n' )
    330                         if(buffer[i+1]!='\r' && buffer[i+1]!='\n')
    331                                 j++;
     343        for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
     344        {
     345                if( buffer[i] == '\n' )
     346                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     347                                j ++;
    332348        }
    333349       
    334350        /* Allocate j+1 elements. */
    335         lines=g_new (char *, j+1);
     351        lines = g_new( char *, j + 1 );
    336352       
    337353        /* NULL terminate our list. */
    338         lines[j]=NULL;
    339        
    340         lines[0]=buffer;
     354        lines[j] = NULL;
     355       
     356        lines[0] = buffer;
    341357       
    342358        /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    343359         * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    344360         */
    345         for( i=0, j=0; buffer[i]!='\0'; i++) {
    346                 if(buffer[i]=='\n') {
    347                         buffer[i]='\0';
    348 
    349                         /* We dont want to read 1 byte before our buffer
    350                          * and (in rare cases) generate a SIGSEGV.
    351                          */
    352                         if(i!=0)
    353                                 if(buffer[i-1]=='\r')
    354                                         buffer[i-1]='\0';
    355                         if(buffer[i+1]!='\r'&&buffer[i+1]!='\n')
    356                                 lines[++j]=buffer+i+1;
    357                 }
    358         }
    359 
    360         return(lines);
    361 }
    362 
    363 int irc_process_line( irc_t *irc, char *line )
     361        for( i = 0, j = 0; buffer[i] != '\0'; i ++)
     362        {
     363                if( buffer[i] == '\n' )
     364                {
     365                        buffer[i] = '\0';
     366                       
     367                        if( i > 0 && buffer[i-1] == '\r' )
     368                                buffer[i-1] = '\0';
     369                        if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
     370                                lines[++j] = buffer + i + 1;
     371                }
     372        }
     373       
     374        return( lines );
     375}
     376
     377char **irc_parse_line( char *line )
    364378{
    365379        int i, j;
     
    367381       
    368382        /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */
    369         if(line[0]==':') {
    370                 for(i=0; line[i]!=32; i++);
    371                 line=line+i;
    372         }
    373         for(i=0; line[i]==32; i++);
    374         line=line+i;
    375 
     383        if( line[0] == ':' )
     384        {
     385                for( i = 0; line[i] != ' '; i ++ );
     386                line = line + i;
     387        }
     388        for( i = 0; line[i] == ' '; i ++ );
     389        line = line + i;
     390       
    376391        /* If we're already at the end of the line, return. If not, we're going to need at least one element. */
    377         if(line[0]=='\0')
    378                 return 1;
    379         else
    380                 j=1;   
    381        
    382         /* Count the number of char **cmd elements we're going to need. */     
    383         for(i=0; line[i]!='\0'; i++) {
    384                 if((line[i]==32) && (line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    385                         j++;
    386                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]==32)) {
    387                         j++;
    388                         break;
    389                 }
     392        if( line[0] == '\0')
     393                return NULL;
     394       
     395        /* Count the number of char **cmd elements we're going to need. */
     396        j = 1;
     397        for( i = 0; line[i] != '\0'; i ++ )
     398        {
     399                if( line[i] == ' ' )
     400                {
     401                        j ++;
    390402                       
     403                        if( line[i+1] == ':' )
     404                                break;
     405                }
    391406        }       
    392407
    393408        /* Allocate the space we need. */
    394         cmd=g_new(char *, j+1);
    395         cmd[j]=NULL;
     409        cmd = g_new( char *, j + 1 );
     410        cmd[j] = NULL;
    396411       
    397412        /* Do the actual line splitting, format is:
     
    400415         */
    401416
    402         cmd[0]=line;
    403         for(i=0, j=0; line[i]!='\0'; i++) {
    404                 if((line[i]==32)) {
    405                         line[i]='\0';
    406                         if((line[i+1]!=32) && (line[i+1]!='\0') && (line[i+1]!=':'))           
    407                                 cmd[++j]=line+i+1;
    408                 }
    409                 else if((line[i]==':') && (line[i+1]!='\0') && (line[i-1]=='\0')) {
    410                         cmd[++j]=line+i+1;
    411                         break;
    412                 }
    413         }
    414        
    415         i=irc_exec(irc, cmd);
    416         g_free(cmd);
    417 
    418         return(i);     
    419 }
    420 
    421 int irc_exec( irc_t *irc, char **cmd )
    422 {       
    423         int i;
    424 
    425         if( (global.conf)->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
    426         {
    427                 if( g_strcasecmp( cmd[0], "PASS" ) == 0 )
    428                 {
    429                         if( !cmd[1] )
     417        cmd[0] = line;
     418        for( i = 0, j = 0; line[i] != '\0'; i ++ )
     419        {
     420                if( line[i] == ' ' )
     421                {
     422                        line[i] = '\0';
     423                        cmd[++j] = line + i + 1;
     424                       
     425                        if( line[i+1] == ':' )
    430426                        {
    431                                 irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
     427                                cmd[j] ++;
     428                                break;
    432429                        }
    433                         else if( strcmp( cmd[1], (global.conf)->auth_pass ) == 0 )
    434                         {
    435                                 irc->status = USTATUS_AUTHORIZED;
    436                         }
    437                         else
    438                         {
    439                                 irc_reply( irc, 464, ":Nope, maybe you should try it again..." );
    440                         }
    441                 }
    442                 else
    443                 {
    444                         irc_reply( irc, 464, ":Uhh, fine, but I want the password first." );
    445                 }
    446                
    447                 return( 1 );
    448         }
    449        
    450         if( g_strcasecmp( cmd[0], "USER" ) == 0 )
    451         {
    452                 if( !( cmd[1] && cmd[2] && cmd[3] && cmd[4] ) )
    453                 {
    454                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    455                 }
    456                 else if( irc->user )
    457                 {
    458                         irc_reply( irc, 462, ":You can't change your nick/userinfo" );
    459                 }
    460                 else
    461                 {
    462                         irc->user = g_strdup( cmd[1] );
    463                         irc->realname = g_strdup( cmd[4] );
    464                         if( irc->nick ) irc_login( irc );
    465                 }
    466                 return( 1 );
    467         }
    468         else if( g_strcasecmp( cmd[0], "NICK" ) == 0 )
    469         {
    470                 if( !cmd[1] )
    471                 {
    472                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    473                 }
    474                 else if( irc->nick )
    475                 {
    476                         irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" );
    477                 }
    478                 /* This is not clean, but for now it'll have to be like this... */
    479                 else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) )
    480                 {
    481                         irc_reply( irc, 433, ":This nick is already in use" );
    482                 }
    483                 else if( !nick_ok( cmd[1] ) )
    484                 {
    485                         /* [SH] Invalid characters. */
    486                         irc_reply( irc, 432, ":This nick contains invalid characters" );
    487                 }
    488                 else
    489                 {
    490                         irc->nick = g_strdup( cmd[1] );
    491                         if( irc->user ) irc_login( irc );
    492                 }
    493                 return( 1 );
    494         }
    495         else if( g_strcasecmp( cmd[0], "QUIT" ) == 0 )
    496         {
    497                 irc_write( irc, "ERROR :%s%s", cmd[1]?"Quit: ":"", cmd[1]?cmd[1]:"Client Quit" );
    498                 g_io_channel_close( irc->io_channel );
    499                 return( 0 );
    500         }
    501        
    502         if( !irc->user || !irc->nick )
    503         {
    504                 irc_reply( irc, 451, ":Register first" );
    505                 return( 1 );
    506         }
    507        
    508         if( g_strcasecmp( cmd[0], "PING" ) == 0 )
    509         {
    510                 irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
    511         }
    512         else if( g_strcasecmp( cmd[0], "OPER" ) == 0 )
    513         {
    514                 if( !cmd[2] )
    515                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    516                 else if( strcmp( cmd[2], global.conf->oper_pass ) == 0 )
    517                         irc_umode_set( irc, "+o", 1 );
    518                 // else
    519                         /* FIXME/TODO: Find out which reply to send now. */
    520         }
    521         else if( g_strcasecmp( cmd[0], "MODE" ) == 0 )
    522         {
    523                 if( !cmd[1] )
    524                 {
    525                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    526                 }
    527                 else if( *cmd[1] == '#' || *cmd[1] == '&' )
    528                 {
    529                         if( cmd[2] )
    530                         {
    531                                 if( *cmd[2] == '+' || *cmd[2] == '-' )
    532                                         irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
    533                                 else if( *cmd[2] == 'b' )
    534                                         irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
    535                         }
    536                         else
    537                                 irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
    538                 }
    539                 else
    540                 {
    541                         if( nick_cmp( cmd[1], irc->nick ) == 0 )
    542                         {
    543                                 if( cmd[2] )
    544                                         irc_umode_set( irc, cmd[2], 0 );
    545                         }
    546                         else
    547                                 irc_reply( irc, 502, ":Don't touch their modes" );
    548                 }
    549         }
    550         else if( g_strcasecmp( cmd[0], "NAMES" ) == 0 )
    551         {
    552                 irc_names( irc, cmd[1]?cmd[1]:irc->channel );
    553         }
    554         else if( g_strcasecmp( cmd[0], "PART" ) == 0 )
    555         {
    556                 struct conversation *c;
    557                
    558                 if( !cmd[1] )
    559                 {
    560                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    561                 }
    562                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    563                 {
    564                         user_t *u = user_find( irc, irc->nick );
    565                        
    566                         /* Not allowed to leave control channel */
    567                         irc_part( irc, u, irc->channel );
    568                         irc_join( irc, u, irc->channel );
    569                 }
    570                 else if( ( c = conv_findchannel( cmd[1] ) ) )
    571                 {
    572                         user_t *u = user_find( irc, irc->nick );
    573                        
    574                         irc_part( irc, u, c->channel );
    575                        
    576                         if( c->gc && c->gc->prpl )
    577                         {
    578                                 c->joined = 0;
    579                                 c->gc->prpl->chat_leave( c->gc, c->id );
    580                         }
    581                 }
    582                 else
    583                 {
    584                         irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    585                 }
    586         }
    587         else if( g_strcasecmp( cmd[0], "JOIN" ) == 0 )
    588         {
    589                 if( !cmd[1] )
    590                 {
    591                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    592                 }
    593                 else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    594                         ; /* Dude, you're already there...
    595                              RFC doesn't have any reply for that though? */
    596                 else if( cmd[1] )
    597                 {
    598                         if( ( cmd[1][0] == '#' || cmd[1][0] == '&' ) && cmd[1][1] )
    599                         {
    600                                 user_t *u = user_find( irc, cmd[1] + 1 );
    601                                
    602                                 if( u && u->gc && u->gc->prpl && u->gc->prpl->chat_open )
    603                                 {
    604                                         irc_reply( irc, 403, "%s :Initializing groupchat in a different channel", cmd[1] );
    605                                        
    606                                         if( !u->gc->prpl->chat_open( u->gc, u->handle ) )
    607                                         {
    608                                                 irc_usermsg( irc, "Could not open a groupchat with %s, maybe you don't have a connection to him/her yet?", u->nick );
    609                                         }
    610                                 }
    611                                 else
    612                                 {
    613                                         irc_reply( irc, 403, "%s :Groupchats are not possible with %s", cmd[1], cmd[1]+1 );
    614                                 }
    615                         }
    616                         else
    617                         {
    618                                 irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    619                         }
    620                 }
    621         }
    622         else if( g_strcasecmp( cmd[0], "INVITE" ) == 0 )
    623         {
    624                 if( cmd[1] && cmd[2] )
    625                         irc_invite( irc, cmd[1], cmd[2] );
    626                 else
    627                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    628         }
    629         else if( g_strcasecmp( cmd[0], "PRIVMSG" ) == 0 || g_strcasecmp( cmd[0], "NOTICE" ) == 0 )
    630         {
    631                 if( !cmd[1] )
    632                 {
    633                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    634                 }
    635                 else if ( !cmd[2] )
    636                 {
    637                         irc_reply( irc, 412, ":No text to send" );
    638                 }
    639                 else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
    640                 {
    641                         irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
    642                 }
    643                 else
    644                 {
    645                         if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
    646                         {
    647                                 unsigned int i;
    648                                 char *t = set_getstr( irc, "default_target" );
    649                                
    650                                 if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
    651                                         cmd[1] = irc->last_target;
    652                                 else if( g_strcasecmp( t, "root" ) == 0 )
    653                                         cmd[1] = irc->mynick;
    654                                
    655                                 for( i = 0; i < strlen( cmd[2] ); i ++ )
    656                                 {
    657                                         if( cmd[2][i] == ' ' ) break;
    658                                         if( cmd[2][i] == ':' || cmd[2][i] == ',' )
    659                                         {
    660                                                 cmd[1] = cmd[2];
    661                                                 cmd[2] += i;
    662                                                 *cmd[2] = 0;
    663                                                 while( *(++cmd[2]) == ' ' );
    664                                                 break;
    665                                         }
    666                                 }
    667                                
    668                                 irc->is_private = 0;
    669                                
    670                                 if( cmd[1] != irc->last_target )
    671                                 {
    672                                         if( irc->last_target )
    673                                                 g_free( irc->last_target );
    674                                         irc->last_target = g_strdup( cmd[1] );
    675                                 }
    676                         }
    677                         else
    678                         {
    679                                 irc->is_private = 1;
    680                         }
    681                         irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? IM_FLAG_AWAY : 0 );
    682                 }
    683         }
    684         else if( g_strcasecmp( cmd[0], "WHO" ) == 0 )
    685         {
    686                 irc_who( irc, cmd[1] );
    687         }
    688         else if( g_strcasecmp( cmd[0], "USERHOST" ) == 0 )
    689         {
    690                 user_t *u;
    691                
    692                 if( !cmd[1] )
    693                 {
    694                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    695                 }
    696                 /* [TV] Usable USERHOST-implementation according to
    697                         RFC1459. Without this, mIRC shows an error
    698                         while connecting, and the used way of rejecting
    699                         breaks standards.
    700                 */
    701                
    702                 for( i = 1; cmd[i]; i ++ )
    703                         if( ( u = user_find( irc, cmd[i] ) ) )
    704                         {
    705                                 if( u->online && u->away )
    706                                         irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
    707                                 else
    708                                         irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
    709                         }
    710         }
    711         else if( g_strcasecmp( cmd[0], "ISON" ) == 0 )
    712         {
    713                 user_t *u;
    714                 char buff[IRC_MAX_LINE];
    715                 int lenleft;
    716                
    717                 buff[0] = '\0';
    718                
    719                 /* [SH] Leave room for : and \0 */
    720                 lenleft = IRC_MAX_LINE - 2;
    721                
    722                 for( i = 1; cmd[i]; i ++ )
    723                 {
    724                         if( ( u = user_find( irc, cmd[i] ) ) && u->online )
    725                         {
    726                                 /* [SH] Make sure we don't use too much buffer space. */
    727                                 lenleft -= strlen( u->nick ) + 1;
    728                                
    729                                 if( lenleft < 0 )
    730                                 {
    731                                         break;
    732                                 }
    733                                
    734                                 /* [SH] Add the nick to the buffer. Note
    735                                  * that an extra space is always added. Even
    736                                  * if it's the last nick in the list. Who
    737                                  * cares?
    738                                  */
    739                                
    740                                 strcat( buff, u->nick );
    741                                 strcat( buff, " " );
    742                         }
    743                 }
    744                
    745                 /* [WvG] Well, maybe someone cares, so why not remove it? */
    746                 if( strlen( buff ) > 0 )
    747                         buff[strlen(buff)-1] = '\0';
    748                
    749                 /* [SH] By the way, that really *was* WvG talking. */
    750                 /* [WvG] Really? */
    751                 /* [SH] Yeah... But *this* is WvG talking too. ;-P */
    752                 /* [WvG] *sigh* */
    753                
    754                 irc_reply( irc, 303, ":%s", buff );
    755         }
    756         else if( g_strcasecmp( cmd[0], "WATCH" ) == 0 )
    757         {
    758                 /* Obviously we could also mark a user structure as being
    759                    watched, but what if the WATCH command is sent right
    760                    after connecting? The user won't exist yet then... */
    761                 for( i = 1; cmd[i]; i ++ )
    762                 {
    763                         char *nick;
    764                         user_t *u;
    765                        
    766                         if( !cmd[i][0] || !cmd[i][1] )
    767                                 break;
    768                        
    769                         nick = g_strdup( cmd[i] + 1 );
    770                         nick_lc( nick );
    771                        
    772                         u = user_find( irc, nick );
    773                        
    774                         if( cmd[i][0] == '+' )
    775                         {
    776                                 if( !g_hash_table_lookup( irc->watches, nick ) )
    777                                         g_hash_table_insert( irc->watches, nick, nick );
    778                                
    779                                 if( u && u->online )
    780                                         irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" );
    781                                 else
    782                                         irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" );
    783                         }
    784                         else if( cmd[i][0] == '-' )
    785                         {
    786                                 gpointer okey, ovalue;
    787                                
    788                                 if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) )
    789                                 {
    790                                         g_free( okey );
    791                                         g_hash_table_remove( irc->watches, okey );
    792                                        
    793                                         irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    794                                 }
    795                         }
    796                 }
    797         }
    798         else if( g_strcasecmp( cmd[0], "TOPIC" ) == 0 )
    799         {
    800                 if( cmd[1] && cmd[2] )
    801                         irc_reply( irc, 482, "%s :Cannot change topic", cmd[1] );
    802                 else if( cmd[1] )
    803                         irc_topic( irc, cmd[1] );
    804                 else
    805                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    806         }
    807         else if( g_strcasecmp( cmd[0], "AWAY" ) == 0 )
    808         {
    809                 irc_away( irc, cmd[1] );
    810         }
    811         else if( g_strcasecmp( cmd[0], "WHOIS" ) == 0 )
    812         {
    813                 if( cmd[1] )
    814                 {
    815                         irc_whois( irc, cmd[1] );
    816                 }
    817                 else
    818                 {
    819                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    820                 }
    821         }
    822         else if( g_strcasecmp( cmd[0], "WHOWAS" ) == 0 )
    823         {
    824                 /* For some reason irssi tries a whowas when whois fails. We can
    825                    ignore this, but then the user never gets a "user not found"
    826                    message from irssi which is a bit annoying. So just respond
    827                    with not-found and irssi users will get better error messages */
    828                
    829                 if( cmd[1] )
    830                 {
    831                         irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
    832                         irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
    833                 }
    834                 else
    835                 {
    836                         irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    837                 }
    838         }
    839         else if( ( g_strcasecmp( cmd[0], "NICKSERV" ) == 0 ) || ( g_strcasecmp( cmd[0], "NS" ) == 0 ) )
    840         {
    841                 /* [SH] This aliases the NickServ command to PRIVMSG root */
    842                 /* [TV] This aliases the NS command to PRIVMSG root as well */
    843                 root_command( irc, cmd + 1 );
    844         }
    845         else if( g_strcasecmp( cmd[0], "MOTD" ) == 0 )
    846         {
    847                 irc_motd( irc );
    848         }
    849         else if( g_strcasecmp( cmd[0], "PONG" ) == 0 )
    850         {
    851                 /* We could check the value we get back from the user, but in
    852                    fact we don't care, we're just happy he's still alive. */
    853                 irc->last_pong = gettime();
    854                 irc->pinging = 0;
    855         }
    856         else if( g_strcasecmp( cmd[0], "COMPLETIONS" ) == 0 )
    857         {
    858                 user_t *u = user_find( irc, irc->mynick );
    859                 help_t *h;
    860                 set_t *s;
    861                 int i;
    862                
    863                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );
    864                
    865                 for( i = 0; commands[i].command; i ++ )
    866                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command );
    867                
    868                 for( h = global.help; h; h = h->next )
    869                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->string );
    870                
    871                 for( s = irc->set; s; s = s->next )
    872                         irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key );
    873                
    874                 irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
    875         }
    876         else if( g_strcasecmp( cmd[0], "DIE" ) == 0 )
    877         {
    878                 printf( "%d %d\n", global.listen_socket, write( global.listen_socket, "DIE\r\n", 5 ) );
    879         }
    880         else if( set_getint( irc, "debug" ) )
    881         {
    882                 irc_usermsg( irc, "\002--- Unknown command:" );
    883                 for( i = 0; cmd[i]; i ++ ) irc_usermsg( irc, "%s", cmd[i] );
    884                 irc_usermsg( irc, "\002--------------------" );
    885         }
    886        
    887         return( 1 );
     430                }
     431        }
     432       
     433        return cmd;
    888434}
    889435
     
    1044590}
    1045591
    1046 void irc_who( irc_t *irc, char *channel )
    1047 {
    1048         user_t *u = irc->users;
    1049         struct conversation *c;
    1050         GList *l;
    1051        
    1052         if( !channel || *channel == '0' || *channel == '*' || !*channel )
    1053                 while( u )
    1054                 {
    1055                         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 );
    1056                         u = u->next;
    1057                 }
    1058         else if( g_strcasecmp( channel, irc->channel ) == 0 )
    1059                 while( u )
    1060                 {
    1061                         if( u->online )
    1062                                 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 );
    1063                         u = u->next;
    1064                 }
    1065         else if( ( c = conv_findchannel( channel ) ) )
    1066                 for( l = c->in_room; l; l = l->next )
    1067                 {
    1068                         if( ( u = user_findhandle( c->gc, l->data ) ) )
    1069                                 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 );
    1070                 }
    1071         else if( ( u = user_find( irc, channel ) ) )
    1072                 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 );
    1073        
    1074         irc_reply( irc, 315, "%s :End of /WHO list.", channel?channel:"**" );
     592int irc_check_login( irc_t *irc )
     593{
     594        if( irc->user && irc->nick )
     595        {
     596                if( global.conf->authmode == AUTHMODE_CLOSED && irc->status < USTATUS_AUTHORIZED )
     597                {
     598                        irc_reply( irc, 464, ":This server is password-protected." );
     599                        return 0;
     600                }
     601                else
     602                {
     603                        irc_login( irc );
     604                        return 1;
     605                }
     606        }
     607        else
     608        {
     609                /* More information needed. */
     610                return 0;
     611        }
    1075612}
    1076613
     
    1184721}
    1185722
    1186 void irc_whois( irc_t *irc, char *nick )
    1187 {
    1188         user_t *u = user_find( irc, nick );
    1189        
    1190         if( u )
    1191         {
    1192                 irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
    1193                
    1194                 if( u->gc )
    1195                         irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->gc->user->username,
    1196                                    *u->gc->user->proto_opt[0] ? u->gc->user->proto_opt[0] : "", u->gc->prpl->name );
    1197                 else
    1198                         irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
    1199                
    1200                 if( !u->online )
    1201                         irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
    1202                 else if( u->away )
    1203                         irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    1204                
    1205                 irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
    1206         }
    1207         else
    1208         {
    1209                 irc_reply( irc, 401, "%s :Nick does not exist", nick );
    1210         }
    1211 }
    1212 
    1213 
    1214723void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    1215724{
     
    1241750}
    1242751
    1243 int irc_away( irc_t *irc, char *away )
    1244 {
    1245         user_t *u = user_find( irc, irc->nick );
    1246         GSList *c = get_connections();
    1247        
    1248         if( !u ) return( 0 );
    1249        
    1250         if( away && *away )
    1251         {
    1252                 int i, j;
    1253                
    1254                 /* Copy away string, but skip control chars. Mainly because
    1255                    Jabber really doesn't like them. */
    1256                 u->away = g_malloc( strlen( away ) + 1 );
    1257                 for( i = j = 0; away[i]; i ++ )
    1258                         if( ( u->away[j] = away[i] ) >= ' ' )
    1259                                 j ++;
    1260                 u->away[j] = 0;
    1261                
    1262                 irc_reply( irc, 306, ":You're now away: %s", u->away );
    1263                 /* irc_umode_set( irc, irc->myhost, "+a" ); */
    1264         }
    1265         else
    1266         {
    1267                 if( u->away ) g_free( u->away );
    1268                 u->away = NULL;
    1269                 /* irc_umode_set( irc, irc->myhost, "-a" ); */
    1270                 irc_reply( irc, 305, ":Welcome back" );
    1271         }
    1272        
    1273         while( c )
    1274         {
    1275                 if( ((struct gaim_connection *)c->data)->flags & OPT_LOGGED_IN )
    1276                         proto_away( c->data, u->away );
    1277                
    1278                 c = c->next;
    1279         }
    1280        
    1281         return( 1 );
    1282 }
    1283 
    1284752void irc_spawn( irc_t *irc, user_t *u )
    1285753{
     
    1333801        }
    1334802        g_free( nick );
    1335 }
    1336 
    1337 void irc_invite( irc_t *irc, char *nick, char *channel )
    1338 {
    1339         struct conversation *c = conv_findchannel( channel );
    1340         user_t *u = user_find( irc, nick );
    1341        
    1342         if( u && c && ( u->gc == c->gc ) )
    1343                 if( c->gc && c->gc->prpl && c->gc->prpl->chat_invite )
    1344                 {
    1345                         c->gc->prpl->chat_invite( c->gc, c->id, "", u->handle );
    1346                         irc_reply( irc, 341, "%s %s", nick, channel );
    1347                         return;
    1348                 }
    1349        
    1350         irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
    1351803}
    1352804
  • irc.h

    r9d6b229 r0431ea1  
    3333#define IRC_PING_STRING "PinglBee"
    3434
    35 #define UMODES "ias"
     35#define UMODES "iasw"
    3636#define UMODES_PRIV "Ro"
    3737#define CMODES "nt"
     
    108108int irc_exec( irc_t *irc, char **cmd );
    109109int irc_process( irc_t *irc );
    110 int irc_process_line( irc_t *irc, char *line );
     110char **irc_parse_line( char *line );
    111111
    112112void irc_vawrite( irc_t *irc, char *format, va_list params );
     
    118118
    119119void irc_login( irc_t *irc );
     120int irc_check_login( irc_t *irc );
    120121void irc_motd( irc_t *irc );
    121122void irc_names( irc_t *irc, char *channel );
Note: See TracChangeset for help on using the changeset viewer.