[BACK]Return to irc-write.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/irc-write.c, Revision 1.1.1.1

1.1       tomglok     1: /*
                      2:  * ngIRCd -- The Next Generation IRC Daemon
                      3:  * Copyright (c)2001-2018 Alexander Barton (alex@barton.de) and Contributors.
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify
                      6:  * it under the terms of the GNU General Public License as published by
                      7:  * the Free Software Foundation; either version 2 of the License, or
                      8:  * (at your option) any later version.
                      9:  * Please read the file COPYING, README and AUTHORS for more information.
                     10:  */
                     11:
                     12: #include "portab.h"
                     13:
                     14: /**
                     15:  * @file
                     16:  * Sending IRC commands over the network
                     17:  */
                     18:
                     19: #include <assert.h>
                     20: #ifdef PROTOTYPES
                     21: #      include <stdarg.h>
                     22: #else
                     23: #      include <varargs.h>
                     24: #endif
                     25: #include <stdio.h>
                     26:
                     27: #include "conn-func.h"
                     28: #include "channel.h"
                     29:
                     30: #include "irc-write.h"
                     31:
                     32: #define SEND_TO_USER 1
                     33: #define SEND_TO_SERVER 2
                     34:
                     35: static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client));
                     36: static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client,
                     37:                                         CLIENT *Prefix, void *Buffer));
                     38: static void Send_Marked_Connections PARAMS((CLIENT *Prefix, const char *Buffer));
                     39:
                     40: /**
                     41:  * Send an error message to a client and enforce a penalty time.
                     42:  *
                     43:  * @param Client The target client.
                     44:  * @param Format Format string.
                     45:  * @return CONNECTED or DISCONNECTED.
                     46:  */
                     47: #ifdef PROTOTYPES
                     48: GLOBAL bool
                     49: IRC_WriteErrClient( CLIENT *Client, const char *Format, ... )
                     50: #else
                     51: GLOBAL bool
                     52: IRC_WriteErrClient( Client, Format, va_alist )
                     53: CLIENT *Client;
                     54: const char *Format;
                     55: va_dcl
                     56: #endif
                     57: {
                     58:        char buffer[1000];
                     59:        va_list ap;
                     60:
                     61:        assert(Client != NULL);
                     62:        assert(Format != NULL);
                     63:
                     64: #ifdef PROTOTYPES
                     65:        va_start(ap, Format);
                     66: #else
                     67:        va_start(ap);
                     68: #endif
                     69:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                     70:        va_end(ap);
                     71:
                     72:        IRC_SetPenalty(Client, 2);
                     73:        return IRC_WriteStrClientPrefix(Client, Client_ThisServer(),
                     74:                                        "%s", buffer);
                     75: }
                     76:
                     77: /**
                     78:  * Send a message to a client.
                     79:  *
                     80:  * @param Client The target client.
                     81:  * @param Format Format string.
                     82:  * @return CONNECTED or DISCONNECTED.
                     83:  */
                     84: #ifdef PROTOTYPES
                     85: GLOBAL bool
                     86: IRC_WriteStrClient( CLIENT *Client, const char *Format, ... )
                     87: #else
                     88: GLOBAL bool
                     89: IRC_WriteStrClient( Client, Format, va_alist )
                     90: CLIENT *Client;
                     91: const char *Format;
                     92: va_dcl
                     93: #endif
                     94: {
                     95:        char buffer[1000];
                     96:        va_list ap;
                     97:
                     98:        assert(Client != NULL);
                     99:        assert(Format != NULL);
                    100:
                    101: #ifdef PROTOTYPES
                    102:        va_start(ap, Format);
                    103: #else
                    104:        va_start(ap);
                    105: #endif
                    106:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    107:        va_end(ap);
                    108:
                    109:        return IRC_WriteStrClientPrefix(Client, Client_ThisServer(),
                    110:                                        "%s", buffer);
                    111: }
                    112:
                    113: /**
                    114:  * Send a message to a client using a specific prefix.
                    115:  *
                    116:  * @param Client The target client.
                    117:  * @param Prefix The prefix to use.
                    118:  * @param Format Format string.
                    119:  * @return CONNECTED or DISCONNECTED.
                    120:  */
                    121: #ifdef PROTOTYPES
                    122: GLOBAL bool
                    123: IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...)
                    124: #else
                    125: GLOBAL bool
                    126: IRC_WriteStrClientPrefix(Client, Prefix, Format, va_alist)
                    127: CLIENT *Client;
                    128: CLIENT *Prefix;
                    129: const char *Format;
                    130: va_dcl
                    131: #endif
                    132: {
                    133:        /* send text to local and remote clients */
                    134:
                    135:        char buffer[1000];
                    136:        va_list ap;
                    137:
                    138:        assert( Client != NULL );
                    139:        assert( Format != NULL );
                    140:        assert( Prefix != NULL );
                    141:
                    142: #ifdef PROTOTYPES
                    143:        va_start( ap, Format );
                    144: #else
                    145:        va_start( ap );
                    146: #endif
                    147:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    148:        va_end( ap );
                    149:
                    150:        return Conn_WriteStr(Client_Conn(Client_NextHop(Client)), ":%s %s",
                    151:                        Get_Prefix(Client_NextHop(Client), Prefix), buffer);
                    152: }
                    153:
                    154: /**
                    155:  * Send a message to all client in a channel.
                    156:  *
                    157:  * The message is only sent once per remote server.
                    158:  *
                    159:  * @param Client The sending client, excluded while forwarding the message.
                    160:  * @param Channel The target channel.
                    161:  * @param Remote If not set, the message is sent to local clients only.
                    162:  * @param Format Format string.
                    163:  */
                    164: #ifdef PROTOTYPES
                    165: GLOBAL void
                    166: IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote,
                    167:                    const char *Format, ...)
                    168: #else
                    169: GLOBAL void
                    170: IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist)
                    171: CLIENT *Client;
                    172: CHANNEL *Chan;
                    173: bool Remote;
                    174: const char *Format;
                    175: va_dcl
                    176: #endif
                    177: {
                    178:        char buffer[1000];
                    179:        va_list ap;
                    180:
                    181:        assert( Client != NULL );
                    182:        assert( Format != NULL );
                    183:
                    184: #ifdef PROTOTYPES
                    185:        va_start( ap, Format );
                    186: #else
                    187:        va_start( ap );
                    188: #endif
                    189:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    190:        va_end( ap );
                    191:
                    192:        IRC_WriteStrChannelPrefix(Client, Chan, Client_ThisServer(),
                    193:                                  Remote, "%s", buffer);
                    194: }
                    195:
                    196: /**
                    197:  * Send a message to all client in a channel using a specific prefix.
                    198:  *
                    199:  * The message is only sent once per remote server.
                    200:  *
                    201:  * @param Client The sending client, excluded while forwarding the message.
                    202:  * @param Channel The target channel.
                    203:  * @param Prefix The prefix to use.
                    204:  * @param Remote If not set, the message is sent to local clients only.
                    205:  * @param Format Format string.
                    206:  */
                    207: #ifdef PROTOTYPES
                    208: GLOBAL void
                    209: IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix,
                    210:                          bool Remote, const char *Format, ...)
                    211: #else
                    212: GLOBAL void
                    213: IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist)
                    214: CLIENT *Client;
                    215: CHANNEL *Chan;
                    216: CLIENT *Prefix;
                    217: bool Remote;
                    218: const char *Format;
                    219: va_dcl
                    220: #endif
                    221: {
                    222:        char buffer[1000];
                    223:        CL2CHAN *cl2chan;
                    224:        CONN_ID conn;
                    225:        CLIENT *c;
                    226:        va_list ap;
                    227:
                    228:        assert( Client != NULL );
                    229:        assert( Chan != NULL );
                    230:        assert( Prefix != NULL );
                    231:        assert( Format != NULL );
                    232:
                    233: #ifdef PROTOTYPES
                    234:        va_start( ap, Format );
                    235: #else
                    236:        va_start( ap  );
                    237: #endif
                    238:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    239:        va_end( ap );
                    240:
                    241:        Conn_ClearFlags( );
                    242:
                    243:        cl2chan = Channel_FirstMember( Chan );
                    244:        while(cl2chan) {
                    245:                c = Channel_GetClient( cl2chan );
                    246:                if (!Remote) {
                    247:                        if (Client_Conn(c) <= NONE)
                    248:                                c = NULL;
                    249:                        else if(Client_Type(c) == CLIENT_SERVER)
                    250:                                c = NULL;
                    251:                }
                    252:                if(c)
                    253:                        c = Client_NextHop(c);
                    254:
                    255:                if(c && c != Client) {
                    256:                        /* Ok, another Client */
                    257:                        conn = Client_Conn(c);
                    258:                        if (Client_Type(c) == CLIENT_SERVER)
                    259:                                Conn_SetFlag(conn, SEND_TO_SERVER);
                    260:                        else
                    261:                                Conn_SetFlag(conn, SEND_TO_USER);
                    262:                }
                    263:                cl2chan = Channel_NextMember(Chan, cl2chan);
                    264:        }
                    265:        Send_Marked_Connections(Prefix, buffer);
                    266: }
                    267:
                    268: /**
                    269:  * Send a message to all the servers in the network.
                    270:  *
                    271:  * @param Client The sending client, excluded while forwarding the message.
                    272:  * @param Format Format string.
                    273:  */
                    274: #ifdef PROTOTYPES
                    275: GLOBAL void
                    276: IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...)
                    277: #else
                    278: GLOBAL void
                    279: IRC_WriteStrServers(ExceptOf, Format, va_alist)
                    280: CLIENT *ExceptOf;
                    281: const char *Format;
                    282: va_dcl
                    283: #endif
                    284: {
                    285:        char buffer[1000];
                    286:        va_list ap;
                    287:
                    288:        assert( Format != NULL );
                    289:
                    290: #ifdef PROTOTYPES
                    291:        va_start( ap, Format );
                    292: #else
                    293:        va_start( ap );
                    294: #endif
                    295:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    296:        va_end( ap );
                    297:
                    298:        IRC_WriteStrServersPrefix(ExceptOf, Client_ThisServer(), "%s", buffer);
                    299: }
                    300:
                    301: /**
                    302:  * Send a message to all the servers in the network using a specific prefix.
                    303:  *
                    304:  * @param Client The sending client, excluded while forwarding the message.
                    305:  * @param Prefix The prefix to use.
                    306:  * @param Format Format string.
                    307:  */
                    308: #ifdef PROTOTYPES
                    309: GLOBAL void
                    310: IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix,
                    311:                          const char *Format, ...)
                    312: #else
                    313: GLOBAL void
                    314: IRC_WriteStrServersPrefix(ExceptOf, Prefix, Format, va_alist)
                    315: CLIENT *ExceptOf;
                    316: CLIENT *Prefix;
                    317: const char *Format;
                    318: va_dcl
                    319: #endif
                    320: {
                    321:        char buffer[1000];
                    322:        va_list ap;
                    323:
                    324:        assert( Format != NULL );
                    325:        assert( Prefix != NULL );
                    326:
                    327: #ifdef PROTOTYPES
                    328:        va_start( ap, Format );
                    329: #else
                    330:        va_start( ap );
                    331: #endif
                    332:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    333:        va_end( ap );
                    334:
                    335:        IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
                    336: }
                    337:
                    338: /**
                    339:  * Send a message to all the servers in the network using a specific prefix
                    340:  * and matching a "client flag".
                    341:  *
                    342:  * @param Client The sending client, excluded while forwarding the message.
                    343:  * @param Prefix The prefix to use.
                    344:  * @param Flag Client flag that must be set on the target.
                    345:  * @param Format Format string.
                    346:  */
                    347: #ifdef PROTOTYPES
                    348: GLOBAL void
                    349: IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
                    350:                              const char *Format, ...)
                    351: #else
                    352: GLOBAL void
                    353: IRC_WriteStrServersPrefixFlag(ExceptOf, Prefix, Flag, Format, va_alist)
                    354: CLIENT *ExceptOf;
                    355: CLIENT *Prefix;
                    356: char Flag;
                    357: const char *Format;
                    358: va_dcl
                    359: #endif
                    360: {
                    361:        char buffer[1000];
                    362:        va_list ap;
                    363:
                    364:        assert( Format != NULL );
                    365:        assert( Prefix != NULL );
                    366:
                    367: #ifdef PROTOTYPES
                    368:        va_start( ap, Format );
                    369: #else
                    370:        va_start( ap );
                    371: #endif
                    372:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    373:        va_end( ap );
                    374:
                    375:        IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag,
                    376:                                         cb_writeStrServersPrefixFlag, buffer);
                    377: }
                    378:
                    379: /**
                    380:  * Send a message to all the servers in the network using a specific prefix
                    381:  * and matching a "client flag" using a callback function.
                    382:  *
                    383:  * @param ExceptOf The sending client, excluded while forwarding the message.
                    384:  * @param Prefix The prefix to use.
                    385:  * @param Flag Client flag that must be set on the target.
                    386:  * @param callback Callback function.
                    387:  */
                    388: GLOBAL void
                    389: IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
                    390:                void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)
                    391: {
                    392:        CLIENT *c;
                    393:
                    394:        c = Client_First();
                    395:        while(c) {
                    396:                if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE &&
                    397:                    c != Client_ThisServer() && c != ExceptOf) {
                    398:                        /* Found a target server, do the flags match? */
                    399:                        if (Flag == '\0' || Client_HasFlag(c, Flag))
                    400:                                callback(c, Prefix, cb_data);
                    401:                }
                    402:                c = Client_Next(c);
                    403:        }
                    404: }
                    405:
                    406: /**
                    407:  * Send a message to all "related" clients.
                    408:  *
                    409:  * Related clients are the one that share one ore more channels with the client
                    410:  * sending this message.
                    411:  *
                    412:  * The message is only sent once per remote server.
                    413:  *
                    414:  * @param Client The sending client, excluded while forwarding the message.
                    415:  * @param Prefix The prefix to use.
                    416:  * @param Remote If not set, the message is sent to local clients only.
                    417:  * @param Format Format string.
                    418:  */
                    419: #ifdef PROTOTYPES
                    420: GLOBAL void
                    421: IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote,
                    422:                          const char *Format, ...)
                    423: #else
                    424: GLOBAL void
                    425: IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist)
                    426: CLIENT *Client;
                    427: CLIENT *Prefix;
                    428: bool Remote;
                    429: const char *Format;
                    430: va_dcl
                    431: #endif
                    432: {
                    433:        CL2CHAN *chan_cl2chan, *cl2chan;
                    434:        char buffer[1000];
                    435:        CHANNEL *chan;
                    436:        CONN_ID conn;
                    437:        va_list ap;
                    438:        CLIENT *c;
                    439:
                    440:        assert( Client != NULL );
                    441:        assert( Prefix != NULL );
                    442:        assert( Format != NULL );
                    443:
                    444: #ifdef PROTOTYPES
                    445:        va_start( ap, Format );
                    446: #else
                    447:        va_start( ap );
                    448: #endif
                    449:        vsnprintf(buffer, sizeof(buffer), Format, ap);
                    450:        va_end( ap );
                    451:
                    452:        Conn_ClearFlags( );
                    453:
                    454:        chan_cl2chan = Channel_FirstChannelOf( Client );
                    455:        while( chan_cl2chan )
                    456:        {
                    457:                chan = Channel_GetChannel( chan_cl2chan );
                    458:                cl2chan = Channel_FirstMember( chan );
                    459:                while( cl2chan )
                    460:                {
                    461:                        c = Channel_GetClient( cl2chan );
                    462:                        if( ! Remote )
                    463:                        {
                    464:                                if( Client_Conn( c ) <= NONE ) c = NULL;
                    465:                                else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
                    466:                        }
                    467:                        if( c ) c = Client_NextHop( c );
                    468:
                    469:                        if( c && ( c != Client ))
                    470:                        {
                    471:                                conn = Client_Conn( c );
                    472:                                if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
                    473:                                else Conn_SetFlag( conn, SEND_TO_USER );
                    474:                        }
                    475:                        cl2chan = Channel_NextMember( chan, cl2chan );
                    476:                }
                    477:
                    478:                chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
                    479:        }
                    480:        Send_Marked_Connections(Prefix, buffer);
                    481: } /* IRC_WriteStrRelatedPrefix */
                    482:
                    483: /**
                    484:  * Send WALLOPS message.
                    485:  *
                    486:  * @param Client The sending client, excluded while forwarding the message.
                    487:  * @param From The (remote) sender of the message.
                    488:  * @param Format Format string.
                    489: */
                    490: #ifdef PROTOTYPES
                    491: GLOBAL void
                    492: IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...)
                    493: #else
                    494: GLOBAL void
                    495: IRC_SendWallops(Client, From, Format, va_alist )
                    496: CLIENT *Client;
                    497: CLIENT *From;
                    498: const char *Format;
                    499: va_dcl
                    500: #endif
                    501: {
                    502:        va_list ap;
                    503:        char msg[1000];
                    504:        CLIENT *to;
                    505:
                    506: #ifdef PROTOTYPES
                    507:        va_start(ap, Format);
                    508: #else
                    509:        va_start(ap);
                    510: #endif
                    511:        vsnprintf(msg, sizeof(msg), Format, ap);
                    512:        va_end(ap);
                    513:
                    514:        for (to=Client_First(); to != NULL; to=Client_Next(to)) {
                    515:                if (Client_Conn(to) == NONE) /* no local connection */
                    516:                        continue;
                    517:
                    518:                switch (Client_Type(to)) {
                    519:                case CLIENT_USER:
                    520:                        if (Client_HasMode(to, 'w'))
                    521:                                IRC_WriteStrClientPrefix(to, From,
                    522:                                                         "WALLOPS :%s", msg);
                    523:                        break;
                    524:                case CLIENT_SERVER:
                    525:                        if (to != Client)
                    526:                                IRC_WriteStrClientPrefix(to, From,
                    527:                                                         "WALLOPS :%s", msg);
                    528:                        break;
                    529:                }
                    530:        }
                    531: } /* IRC_SendWallops */
                    532:
                    533: /**
                    534:  * Set a "penalty time" for an IRC client.
                    535:  *
                    536:  * Note: penalty times are never set for server links or remote clients!
                    537:  *
                    538:  * @param Client The client.
                    539:  * @param Seconds The additional "penalty time" to enforce.
                    540:  */
                    541: GLOBAL void
                    542: IRC_SetPenalty(CLIENT *Client, time_t Seconds)
                    543: {
                    544:        CONN_ID c;
                    545:
                    546:        assert(Client != NULL);
                    547:        assert(Seconds > 0);
                    548:
                    549:        if (Client_Type(Client) == CLIENT_SERVER)
                    550:                return;
                    551:
                    552:        c = Client_Conn(Client);
                    553:        if (c <= NONE)
                    554:                return;
                    555:
                    556:        Conn_SetPenalty(c, Seconds);
                    557: } /* IRC_SetPenalty */
                    558:
                    559: static const char *
                    560: Get_Prefix(CLIENT *Target, CLIENT *Client)
                    561: {
                    562:        assert (Target != NULL);
                    563:        assert (Client != NULL);
                    564:
                    565:        if (Client_Type(Target) == CLIENT_SERVER)
                    566:                return Client_ID(Client);
                    567:        else
                    568:                return Client_MaskCloaked(Client);
                    569: } /* Get_Prefix */
                    570:
                    571: static void
                    572: cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer)
                    573: {
                    574:        IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer);
                    575: } /* cb_writeStrServersPrefixFlag */
                    576:
                    577: /**
                    578:  * Send a message to all marked connections using a specific prefix.
                    579:  *
                    580:  * @param Prefix The prefix to use.
                    581:  * @param Buffer The message to send.
                    582:  */
                    583: static void
                    584: Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
                    585: {
                    586:        CONN_ID conn;
                    587:
                    588:        assert(Prefix != NULL);
                    589:        assert(Buffer != NULL);
                    590:
                    591:        conn = Conn_First();
                    592:        while (conn != NONE) {
                    593:                if (Conn_Flag(conn) == SEND_TO_SERVER)
                    594:                        Conn_WriteStr(conn, ":%s %s",
                    595:                                      Client_ID(Prefix), Buffer);
                    596:                else if (Conn_Flag(conn) == SEND_TO_USER)
                    597:                        Conn_WriteStr(conn, ":%s %s",
                    598:                                      Client_MaskCloaked(Prefix), Buffer);
                    599:                conn = Conn_Next(conn);
                    600:        }
                    601: }
                    602:
                    603: /* -eof- */

CVSweb