irc-write.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
  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. * Sending IRC commands over the network
  12. */
  13. #include "portab.h"
  14. static char UNUSED id[] = "$Id: irc-write.c,v 1.21 2006/08/12 11:56:24 fw Exp $";
  15. #include "imp.h"
  16. #include <assert.h>
  17. #ifdef PROTOTYPES
  18. # include <stdarg.h>
  19. #else
  20. # include <varargs.h>
  21. #endif
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include "defines.h"
  25. #include "conn-func.h"
  26. #include "client.h"
  27. #include "channel.h"
  28. #include "exp.h"
  29. #include "irc-write.h"
  30. #define SEND_TO_USER 1
  31. #define SEND_TO_SERVER 2
  32. static char *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client ));
  33. #ifdef PROTOTYPES
  34. GLOBAL bool
  35. IRC_WriteStrClient( CLIENT *Client, char *Format, ... )
  36. #else
  37. GLOBAL bool
  38. IRC_WriteStrClient( Client, Format, va_alist )
  39. CLIENT *Client;
  40. char *Format;
  41. va_dcl
  42. #endif
  43. {
  44. char buffer[1000];
  45. bool ok = CONNECTED;
  46. va_list ap;
  47. assert( Client != NULL );
  48. assert( Format != NULL );
  49. #ifdef PROTOTYPES
  50. va_start( ap, Format );
  51. #else
  52. va_start( ap );
  53. #endif
  54. vsnprintf( buffer, 1000, Format, ap );
  55. va_end( ap );
  56. /* an den Client selber */
  57. ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
  58. return ok;
  59. } /* IRC_WriteStrClient */
  60. #ifdef PROTOTYPES
  61. GLOBAL bool
  62. IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, char *Format, ... )
  63. #else
  64. GLOBAL bool
  65. IRC_WriteStrClientPrefix( Client, Prefix, Format, va_alist )
  66. CLIENT *Client;
  67. CLIENT *Prefix;
  68. char *Format;
  69. va_dcl
  70. #endif
  71. {
  72. /* Text an Clients, lokal bzw. remote, senden. */
  73. char buffer[1000];
  74. va_list ap;
  75. assert( Client != NULL );
  76. assert( Format != NULL );
  77. assert( Prefix != NULL );
  78. #ifdef PROTOTYPES
  79. va_start( ap, Format );
  80. #else
  81. va_start( ap );
  82. #endif
  83. vsnprintf( buffer, 1000, Format, ap );
  84. va_end( ap );
  85. return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
  86. } /* IRC_WriteStrClientPrefix */
  87. #ifdef PROTOTYPES
  88. GLOBAL bool
  89. IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, bool Remote, char *Format, ... )
  90. #else
  91. GLOBAL bool
  92. IRC_WriteStrChannel( Client, Chan, Remote, Format, va_alist )
  93. CLIENT *Client;
  94. CHANNEL *Chan;
  95. bool Remote;
  96. char *Format;
  97. va_dcl
  98. #endif
  99. {
  100. char buffer[1000];
  101. va_list ap;
  102. assert( Client != NULL );
  103. assert( Format != NULL );
  104. #ifdef PROTOTYPES
  105. va_start( ap, Format );
  106. #else
  107. va_start( ap );
  108. #endif
  109. vsnprintf( buffer, 1000, Format, ap );
  110. va_end( ap );
  111. return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
  112. } /* IRC_WriteStrChannel */
  113. #ifdef PROTOTYPES
  114. GLOBAL bool
  115. IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, bool Remote, char *Format, ... )
  116. #else
  117. GLOBAL bool
  118. IRC_WriteStrChannelPrefix( Client, Chan, Prefix, Remote, Format, va_alist )
  119. CLIENT *Client;
  120. CHANNEL *Chan;
  121. CLIENT *Prefix;
  122. bool Remote;
  123. char *Format;
  124. va_dcl
  125. #endif
  126. {
  127. bool ok = CONNECTED;
  128. char buffer[1000];
  129. CL2CHAN *cl2chan;
  130. CONN_ID conn;
  131. CLIENT *c;
  132. va_list ap;
  133. assert( Client != NULL );
  134. assert( Chan != NULL );
  135. assert( Prefix != NULL );
  136. assert( Format != NULL );
  137. #ifdef PROTOTYPES
  138. va_start( ap, Format );
  139. #else
  140. va_start( ap );
  141. #endif
  142. vsnprintf( buffer, 1000, Format, ap );
  143. va_end( ap );
  144. Conn_ClearFlags( );
  145. /* An alle Clients, die in den selben Channels sind.
  146. * Dabei aber nur einmal je Remote-Server */
  147. cl2chan = Channel_FirstMember( Chan );
  148. while( cl2chan )
  149. {
  150. c = Channel_GetClient( cl2chan );
  151. if( ! Remote )
  152. {
  153. if( Client_Conn( c ) <= NONE ) c = NULL;
  154. else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
  155. }
  156. if( c ) c = Client_NextHop( c );
  157. if( c && ( c != Client ))
  158. {
  159. /* Ok, anderer Client */
  160. conn = Client_Conn( c );
  161. if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
  162. else Conn_SetFlag( conn, SEND_TO_USER );
  163. }
  164. cl2chan = Channel_NextMember( Chan, cl2chan );
  165. }
  166. /* Senden: alle Verbindungen durchgehen ... */
  167. conn = Conn_First( );
  168. while( conn != NONE )
  169. {
  170. /* muessen Daten ueber diese Verbindung verschickt werden? */
  171. if( Conn_Flag( conn ) == SEND_TO_SERVER) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
  172. else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
  173. if( ! ok ) break;
  174. /* naechste Verbindung testen */
  175. conn = Conn_Next( conn );
  176. }
  177. return ok;
  178. } /* IRC_WriteStrChannelPrefix */
  179. #ifdef PROTOTYPES
  180. GLOBAL void
  181. IRC_WriteStrServers( CLIENT *ExceptOf, char *Format, ... )
  182. #else
  183. GLOBAL void
  184. IRC_WriteStrServers( ExceptOf, Format, va_alist )
  185. CLIENT *ExceptOf;
  186. char *Format;
  187. va_dcl
  188. #endif
  189. {
  190. char buffer[1000];
  191. va_list ap;
  192. assert( Format != NULL );
  193. #ifdef PROTOTYPES
  194. va_start( ap, Format );
  195. #else
  196. va_start( ap );
  197. #endif
  198. vsnprintf( buffer, 1000, Format, ap );
  199. va_end( ap );
  200. /* an den Client selber */
  201. IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
  202. } /* IRC_WriteStrServers */
  203. #ifdef PROTOTYPES
  204. GLOBAL void
  205. IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, char *Format, ... )
  206. #else
  207. GLOBAL void
  208. IRC_WriteStrServersPrefix( ExceptOf, Prefix, Format, va_alist )
  209. CLIENT *ExceptOf;
  210. CLIENT *Prefix;
  211. char *Format;
  212. va_dcl
  213. #endif
  214. {
  215. char buffer[1000];
  216. va_list ap;
  217. assert( Format != NULL );
  218. assert( Prefix != NULL );
  219. #ifdef PROTOTYPES
  220. va_start( ap, Format );
  221. #else
  222. va_start( ap );
  223. #endif
  224. vsnprintf( buffer, 1000, Format, ap );
  225. va_end( ap );
  226. IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
  227. } /* IRC_WriteStrServersPrefix */
  228. #ifdef PROTOTYPES
  229. GLOBAL void
  230. IRC_WriteStrServersPrefixFlag( CLIENT *ExceptOf, CLIENT *Prefix, char Flag, char *Format, ... )
  231. #else
  232. GLOBAL void
  233. IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, Flag, Format, va_alist )
  234. CLIENT *ExceptOf;
  235. CLIENT *Prefix;
  236. char Flag;
  237. char *Format;
  238. va_dcl
  239. #endif
  240. {
  241. char buffer[1000];
  242. CLIENT *c;
  243. va_list ap;
  244. assert( Format != NULL );
  245. assert( Prefix != NULL );
  246. #ifdef PROTOTYPES
  247. va_start( ap, Format );
  248. #else
  249. va_start( ap );
  250. #endif
  251. vsnprintf( buffer, 1000, Format, ap );
  252. va_end( ap );
  253. c = Client_First( );
  254. while( c )
  255. {
  256. if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
  257. {
  258. /* Ziel-Server gefunden. Nun noch pruefen, ob Flags stimmen */
  259. if(( Flag == '\0' ) || ( strchr( Client_Flags( c ), Flag ) != NULL )) IRC_WriteStrClientPrefix( c, Prefix, "%s", buffer );
  260. }
  261. c = Client_Next( c );
  262. }
  263. } /* IRC_WriteStrServersPrefixFlag */
  264. #ifdef PROTOTYPES
  265. GLOBAL bool
  266. IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, bool Remote, char *Format, ... )
  267. #else
  268. GLOBAL bool
  269. IRC_WriteStrRelatedPrefix( Client, Prefix, Remote, Format, va_alist )
  270. CLIENT *Client;
  271. CLIENT *Prefix;
  272. bool Remote;
  273. char *Format;
  274. va_dcl
  275. #endif
  276. {
  277. bool ok = CONNECTED;
  278. CL2CHAN *chan_cl2chan, *cl2chan;
  279. char buffer[1000];
  280. CHANNEL *chan;
  281. CONN_ID conn;
  282. va_list ap;
  283. CLIENT *c;
  284. assert( Client != NULL );
  285. assert( Prefix != NULL );
  286. assert( Format != NULL );
  287. #ifdef PROTOTYPES
  288. va_start( ap, Format );
  289. #else
  290. va_start( ap );
  291. #endif
  292. vsnprintf( buffer, 1000, Format, ap );
  293. va_end( ap );
  294. /* initialisieren */
  295. Conn_ClearFlags( );
  296. /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind,
  297. * den Text schicken. An Remote-Server aber jeweils nur einmal. */
  298. chan_cl2chan = Channel_FirstChannelOf( Client );
  299. while( chan_cl2chan )
  300. {
  301. /* Channel des Users durchsuchen */
  302. chan = Channel_GetChannel( chan_cl2chan );
  303. cl2chan = Channel_FirstMember( chan );
  304. while( cl2chan )
  305. {
  306. c = Channel_GetClient( cl2chan );
  307. if( ! Remote )
  308. {
  309. if( Client_Conn( c ) <= NONE ) c = NULL;
  310. else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
  311. }
  312. if( c ) c = Client_NextHop( c );
  313. if( c && ( c != Client ))
  314. {
  315. /* Ok, anderer Client */
  316. conn = Client_Conn( c );
  317. if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
  318. else Conn_SetFlag( conn, SEND_TO_USER );
  319. }
  320. cl2chan = Channel_NextMember( chan, cl2chan );
  321. }
  322. /* naechsten Channel */
  323. chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
  324. }
  325. /* Senden: alle Verbindungen durchgehen ... */
  326. conn = Conn_First( );
  327. while( conn != NONE )
  328. {
  329. /* muessen ueber diese Verbindung Daten gesendet werden? */
  330. if( Conn_Flag( conn ) == SEND_TO_SERVER ) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer );
  331. else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer );
  332. if( ! ok ) break;
  333. /* naechste Verbindung testen */
  334. conn = Conn_Next( conn );
  335. }
  336. return ok;
  337. } /* IRC_WriteStrRelatedPrefix */
  338. GLOBAL void
  339. IRC_SetPenalty( CLIENT *Client, time_t Seconds )
  340. {
  341. CONN_ID c;
  342. assert( Client != NULL );
  343. assert( Seconds > 0 );
  344. if( Client_Type( Client ) == CLIENT_SERVER ) return;
  345. c = Client_Conn( Client );
  346. if (c > NONE)
  347. Conn_SetPenalty(c, Seconds);
  348. } /* IRC_SetPenalty */
  349. static char *
  350. Get_Prefix( CLIENT *Target, CLIENT *Client )
  351. {
  352. assert( Target != NULL );
  353. assert( Client != NULL );
  354. if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
  355. else return Client_Mask( Client );
  356. } /* Get_Prefix */
  357. /* -eof- */