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