[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     ! 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