irc-login.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001,2002 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. * Login and logout
  12. */
  13. #include "portab.h"
  14. static char UNUSED id[] = "$Id: irc-login.c,v 1.44 2005/06/04 12:32:09 fw Exp $";
  15. #include "imp.h"
  16. #include <assert.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <strings.h>
  21. #include "ngircd.h"
  22. #include "resolve.h"
  23. #include "conn-func.h"
  24. #include "conf.h"
  25. #include "client.h"
  26. #include "channel.h"
  27. #include "log.h"
  28. #include "messages.h"
  29. #include "parse.h"
  30. #include "irc.h"
  31. #include "irc-info.h"
  32. #include "irc-write.h"
  33. #include "cvs-version.h"
  34. #include "exp.h"
  35. #include "irc-login.h"
  36. LOCAL bool Hello_User PARAMS(( CLIENT *Client ));
  37. LOCAL void Kill_Nick PARAMS(( char *Nick, char *Reason ));
  38. GLOBAL bool
  39. IRC_PASS( CLIENT *Client, REQUEST *Req )
  40. {
  41. assert( Client != NULL );
  42. assert( Req != NULL );
  43. /* Fehler liefern, wenn kein lokaler Client */
  44. if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
  45. if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
  46. {
  47. /* noch nicht registrierte unbekannte Verbindung */
  48. Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
  49. /* Passwort speichern */
  50. Client_SetPassword( Client, Req->argv[0] );
  51. Client_SetType( Client, CLIENT_GOTPASS );
  52. return CONNECTED;
  53. }
  54. else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
  55. {
  56. char c2, c4, *type, *impl, *serverver, *flags, *ptr, *ircflags;
  57. int protohigh, protolow;
  58. /* noch nicht registrierte Server-Verbindung */
  59. Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
  60. /* Passwort speichern */
  61. Client_SetPassword( Client, Req->argv[0] );
  62. /* Protokollversion ermitteln */
  63. if( strlen( Req->argv[1] ) >= 4 )
  64. {
  65. c2 = Req->argv[1][2];
  66. c4 = Req->argv[1][4];
  67. Req->argv[1][4] = '\0';
  68. protolow = atoi( &Req->argv[1][2] );
  69. Req->argv[1][2] = '\0';
  70. protohigh = atoi( Req->argv[1] );
  71. Req->argv[1][2] = c2;
  72. Req->argv[1][4] = c4;
  73. }
  74. else protohigh = protolow = 0;
  75. /* Protokoll-Typ */
  76. if( strlen( Req->argv[1] ) > 4 ) type = &Req->argv[1][4];
  77. else type = NULL;
  78. /* IRC-Flags (nach RFC 2813) */
  79. if( Req->argc >= 4 ) ircflags = Req->argv[3];
  80. else ircflags = "";
  81. /* Implementation, Version und ngIRCd-Flags */
  82. impl = Req->argv[2];
  83. ptr = strchr( impl, '|' );
  84. if( ptr ) *ptr = '\0';
  85. if( type && ( strcmp( type, PROTOIRCPLUS ) == 0 ))
  86. {
  87. /* auf der anderen Seite laeuft ein Server, der
  88. * ebenfalls das IRC+-Protokoll versteht */
  89. serverver = ptr + 1;
  90. flags = strchr( serverver, ':' );
  91. if( flags )
  92. {
  93. *flags = '\0';
  94. flags++;
  95. }
  96. else flags = "";
  97. Log( LOG_INFO, "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", impl, serverver, protohigh, protolow, flags );
  98. }
  99. else
  100. {
  101. /* auf der anderen Seite laeuft ein Server, der
  102. * nur das Originalprotokoll unterstuetzt */
  103. serverver = "";
  104. if( strchr( ircflags, 'Z' )) flags = "Z";
  105. else flags = "";
  106. Log( LOG_INFO, "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").", impl, protohigh, protolow, flags );
  107. }
  108. Client_SetType( Client, CLIENT_GOTPASSSERVER );
  109. Client_SetFlags( Client, flags );
  110. return CONNECTED;
  111. }
  112. else if(( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
  113. {
  114. /* Falsche Anzahl Parameter? */
  115. return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  116. }
  117. else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
  118. } /* IRC_PASS */
  119. /**
  120. * IRC "NICK" command.
  121. * This function implements the IRC command "NICK" which is used to register
  122. * with the server, to change already registered nicknames and to introduce
  123. * new users which are connected to other servers.
  124. */
  125. GLOBAL bool
  126. IRC_NICK( CLIENT *Client, REQUEST *Req )
  127. {
  128. CLIENT *intr_c, *target, *c;
  129. char *modes;
  130. assert( Client != NULL );
  131. assert( Req != NULL );
  132. #ifndef STRICT_RFC
  133. /* Some IRC clients, for example BitchX, send the NICK and USER
  134. * commands in the wrong order ... */
  135. if( Client_Type( Client ) == CLIENT_UNKNOWN
  136. || Client_Type( Client ) == CLIENT_GOTPASS
  137. || Client_Type( Client ) == CLIENT_GOTNICK
  138. || Client_Type( Client ) == CLIENT_GOTUSER
  139. || Client_Type( Client ) == CLIENT_USER
  140. || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
  141. #else
  142. if( Client_Type( Client ) == CLIENT_UNKNOWN
  143. || Client_Type( Client ) == CLIENT_GOTPASS
  144. || Client_Type( Client ) == CLIENT_GOTNICK
  145. || Client_Type( Client ) == CLIENT_USER
  146. || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
  147. #endif
  148. {
  149. /* User registration or change of nickname */
  150. /* Wrong number of arguments? */
  151. if( Req->argc != 1 )
  152. return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
  153. Client_ID( Client ),
  154. Req->command );
  155. /* Search "target" client */
  156. if( Client_Type( Client ) == CLIENT_SERVER )
  157. {
  158. target = Client_Search( Req->prefix );
  159. if( ! target )
  160. return IRC_WriteStrClient( Client,
  161. ERR_NOSUCHNICK_MSG,
  162. Client_ID( Client ),
  163. Req->argv[0] );
  164. }
  165. else
  166. {
  167. /* Is this a restricted client? */
  168. if( Client_HasMode( Client, 'r' ))
  169. return IRC_WriteStrClient( Client,
  170. ERR_RESTRICTED_MSG,
  171. Client_ID( Client ));
  172. target = Client;
  173. }
  174. #ifndef STRICT_RFC
  175. /* If the clients tries to change to its own nickname we won't
  176. * do anything. This is how the original ircd behaves and some
  177. * clients (for example Snak) expect it to be like this.
  178. * But I doubt that this is "really the right thing" ... */
  179. if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 )
  180. return CONNECTED;
  181. #endif
  182. /* Check that the new nickname is available. Special case:
  183. * the client only changes from/to upper to lower case. */
  184. if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
  185. {
  186. if( ! Client_CheckNick( target, Req->argv[0] ))
  187. return CONNECTED;
  188. }
  189. if(( Client_Type( target ) != CLIENT_USER )
  190. && ( Client_Type( target ) != CLIENT_SERVER ))
  191. {
  192. /* New client */
  193. Log( LOG_DEBUG, "Connection %d: got valid NICK command ...",
  194. Client_Conn( Client ));
  195. /* Register new nickname of this client */
  196. Client_SetID( target, Req->argv[0] );
  197. /* If we received a valid USER command already then
  198. * register the new client! */
  199. if( Client_Type( Client ) == CLIENT_GOTUSER )
  200. return Hello_User( Client );
  201. else
  202. Client_SetType( Client, CLIENT_GOTNICK );
  203. }
  204. else
  205. {
  206. /* Nickname change */
  207. if( Client_Conn( target ) > NONE )
  208. {
  209. /* Local client */
  210. Log( LOG_INFO,
  211. "User \"%s\" changed nick (connection %d): \"%s\" -> \"%s\".",
  212. Client_Mask( target ), Client_Conn( target ),
  213. Client_ID( target ), Req->argv[0] );
  214. }
  215. else
  216. {
  217. /* Remote client */
  218. Log( LOG_DEBUG,
  219. "User \"%s\" changed nick: \"%s\" -> \"%s\".",
  220. Client_Mask( target ), Client_ID( target ),
  221. Req->argv[0] );
  222. }
  223. /* Inform all users and servers (which have to know)
  224. * of this nickname change */
  225. if( Client_Type( Client ) == CLIENT_USER )
  226. IRC_WriteStrClientPrefix( Client, Client,
  227. "NICK :%s",
  228. Req->argv[0] );
  229. IRC_WriteStrServersPrefix( Client, target,
  230. "NICK :%s", Req->argv[0] );
  231. IRC_WriteStrRelatedPrefix( target, target, false,
  232. "NICK :%s", Req->argv[0] );
  233. /* Register old nickname for WHOWAS queries */
  234. Client_RegisterWhowas( target );
  235. /* Save new nickname */
  236. Client_SetID( target, Req->argv[0] );
  237. IRC_SetPenalty( target, 2 );
  238. }
  239. return CONNECTED;
  240. }
  241. else if( Client_Type( Client ) == CLIENT_SERVER )
  242. {
  243. /* Server introduces new client */
  244. /* Falsche Anzahl Parameter? */
  245. if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  246. /* Nick ueberpruefen */
  247. c = Client_Search( Req->argv[0] );
  248. if( c )
  249. {
  250. /* Der neue Nick ist auf diesem Server bereits registriert:
  251. * sowohl der neue, als auch der alte Client muessen nun
  252. * disconnectiert werden. */
  253. Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
  254. Kill_Nick( Req->argv[0], "Nick collision" );
  255. return CONNECTED;
  256. }
  257. /* Server, zu dem der Client connectiert ist, suchen */
  258. intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
  259. if( ! intr_c )
  260. {
  261. Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
  262. Kill_Nick( Req->argv[0], "Unknown server" );
  263. return CONNECTED;
  264. }
  265. /* Neue Client-Struktur anlegen */
  266. c = Client_NewRemoteUser( intr_c, Req->argv[0], atoi( Req->argv[1] ), Req->argv[2], Req->argv[3], atoi( Req->argv[4] ), Req->argv[5] + 1, Req->argv[6], true);
  267. if( ! c )
  268. {
  269. /* Eine neue Client-Struktur konnte nicht angelegt werden.
  270. * Der Client muss disconnectiert werden, damit der Netz-
  271. * status konsistent bleibt. */
  272. Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
  273. Kill_Nick( Req->argv[0], "Server error" );
  274. return CONNECTED;
  275. }
  276. modes = Client_Modes( c );
  277. if( *modes ) Log( LOG_DEBUG, "User \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", Client_Mask( c ), modes, Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
  278. else Log( LOG_DEBUG, "User \"%s\" registered (via %s, on %s, %d hop%s).", Client_Mask( c ), Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
  279. /* Andere Server, ausser dem Introducer, informieren */
  280. IRC_WriteStrServersPrefix( Client, Client, "NICK %s %d %s %s %d %s :%s", Req->argv[0], atoi( Req->argv[1] ) + 1, Req->argv[2], Req->argv[3], Client_MyToken( intr_c ), Req->argv[5], Req->argv[6] );
  281. return CONNECTED;
  282. }
  283. else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
  284. } /* IRC_NICK */
  285. GLOBAL bool
  286. IRC_USER( CLIENT *Client, REQUEST *Req )
  287. {
  288. #ifdef IDENTAUTH
  289. char *ptr;
  290. #endif
  291. assert( Client != NULL );
  292. assert( Req != NULL );
  293. #ifndef STRICT_RFC
  294. if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_UNKNOWN )
  295. #else
  296. if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS )
  297. #endif
  298. {
  299. /* Wrong number of parameters? */
  300. if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  301. /* User name */
  302. #ifdef IDENTAUTH
  303. ptr = Client_User( Client );
  304. if( ! ptr || ! *ptr || *ptr == '~' ) Client_SetUser( Client, Req->argv[0], false );
  305. #else
  306. Client_SetUser( Client, Req->argv[0], false );
  307. #endif
  308. /* "Real name" or user info text: Don't set it to the empty string, the original ircd
  309. * can't deal with such "real names" (e. g. "USER user * * :") ... */
  310. if( *Req->argv[3] ) Client_SetInfo( Client, Req->argv[3] );
  311. else Client_SetInfo( Client, "-" );
  312. Log( LOG_DEBUG, "Connection %d: got valid USER command ...", Client_Conn( Client ));
  313. if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
  314. else Client_SetType( Client, CLIENT_GOTUSER );
  315. return CONNECTED;
  316. }
  317. else if( Client_Type( Client ) == CLIENT_USER || Client_Type( Client ) == CLIENT_SERVER || Client_Type( Client ) == CLIENT_SERVICE )
  318. {
  319. return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
  320. }
  321. else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
  322. } /* IRC_USER */
  323. GLOBAL bool
  324. IRC_QUIT( CLIENT *Client, REQUEST *Req )
  325. {
  326. CLIENT *target;
  327. char quitmsg[LINE_LEN];
  328. assert( Client != NULL );
  329. assert( Req != NULL );
  330. /* Wrong number of arguments? */
  331. if( Req->argc > 1 )
  332. return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  333. if (Req->argc == 1)
  334. strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
  335. if ( Client_Type( Client ) == CLIENT_SERVER )
  336. {
  337. /* Server */
  338. target = Client_Search( Req->prefix );
  339. if( ! target )
  340. {
  341. /* Den Client kennen wir nicht (mehr), also nichts zu tun. */
  342. Log( LOG_WARNING, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
  343. return CONNECTED;
  344. }
  345. Client_Destroy( target, "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
  346. return CONNECTED;
  347. }
  348. else
  349. {
  350. if (Req->argc == 1 && quitmsg[0] != '\"') {
  351. /* " " to avoid confusion */
  352. strlcpy(quitmsg, "\"", sizeof quitmsg);
  353. strlcat(quitmsg, Req->argv[0], sizeof quitmsg-1);
  354. strlcat(quitmsg, "\"", sizeof quitmsg );
  355. }
  356. /* User, Service, oder noch nicht registriert */
  357. Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
  358. return DISCONNECTED;
  359. }
  360. } /* IRC_QUIT */
  361. GLOBAL bool
  362. IRC_PING( CLIENT *Client, REQUEST *Req )
  363. {
  364. CLIENT *target, *from;
  365. assert( Client != NULL );
  366. assert( Req != NULL );
  367. /* Falsche Anzahl Parameter? */
  368. if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
  369. #ifdef STRICT_RFC
  370. if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  371. #endif
  372. if( Req->argc > 1 )
  373. {
  374. /* es wurde ein Ziel-Client angegeben */
  375. target = Client_Search( Req->argv[1] );
  376. if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
  377. if( target != Client_ThisServer( ))
  378. {
  379. /* ok, forwarden */
  380. if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
  381. else from = Client;
  382. if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
  383. return IRC_WriteStrClientPrefix( target, from, "PING %s :%s", Client_ID( from ), Req->argv[1] );
  384. }
  385. }
  386. Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
  387. return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
  388. } /* IRC_PING */
  389. GLOBAL bool
  390. IRC_PONG( CLIENT *Client, REQUEST *Req )
  391. {
  392. CLIENT *target, *from;
  393. assert( Client != NULL );
  394. assert( Req != NULL );
  395. /* Falsche Anzahl Parameter? */
  396. if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
  397. if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
  398. /* forwarden? */
  399. if( Req->argc == 2 )
  400. {
  401. target = Client_Search( Req->argv[1] );
  402. if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
  403. if( target != Client_ThisServer( ))
  404. {
  405. /* ok, forwarden */
  406. if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
  407. else from = Client;
  408. if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
  409. return IRC_WriteStrClientPrefix( target, from, "PONG %s :%s", Client_ID( from ), Req->argv[1] );
  410. }
  411. }
  412. /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
  413. * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
  414. if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %ld seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
  415. else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
  416. return CONNECTED;
  417. } /* IRC_PONG */
  418. LOCAL bool
  419. Hello_User( CLIENT *Client )
  420. {
  421. #ifdef CVSDATE
  422. char ver[12], vertxt[30];
  423. #endif
  424. assert( Client != NULL );
  425. /* Check password ... */
  426. if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
  427. {
  428. /* Bad password! */
  429. Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
  430. Conn_Close( Client_Conn( Client ), NULL, "Bad password", true);
  431. return DISCONNECTED;
  432. }
  433. Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
  434. /* Inform other servers */
  435. IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client ));
  436. /* Welcome :-) */
  437. if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return false;
  438. /* Version and system type */
  439. #ifdef CVSDATE
  440. strlcpy( ver, CVSDATE, sizeof( ver ));
  441. strncpy( ver + 4, ver + 5, 2 );
  442. strncpy( ver + 6, ver + 8, 3 );
  443. snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver );
  444. if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false;
  445. #else
  446. if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false;
  447. #endif
  448. if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return false;
  449. #ifdef CVSDATE
  450. if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, USERMODES, CHANMODES )) return false;
  451. #else
  452. if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, USERMODES, CHANMODES )) return false;
  453. #endif
  454. /* Features */
  455. if( ! IRC_WriteStrClient( Client, RPL_ISUPPORT_MSG, Client_ID( Client ), CLIENT_NICK_LEN - 1, CHANNEL_TOPIC_LEN - 1, CLIENT_AWAY_LEN - 1, Conf_MaxJoins )) return DISCONNECTED;
  456. Client_SetType( Client, CLIENT_USER );
  457. if( ! IRC_Send_LUSERS( Client )) return DISCONNECTED;
  458. if( ! IRC_Show_MOTD( Client )) return DISCONNECTED;
  459. /* Suspend the client for a second ... */
  460. IRC_SetPenalty( Client, 1 );
  461. return CONNECTED;
  462. } /* Hello_User */
  463. LOCAL void
  464. Kill_Nick( char *Nick, char *Reason )
  465. {
  466. REQUEST r;
  467. assert( Nick != NULL );
  468. assert( Reason != NULL );
  469. r.prefix = (char *)Client_ThisServer( );
  470. r.argv[0] = Nick;
  471. r.argv[1] = Reason;
  472. r.argc = 2;
  473. Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
  474. IRC_KILL( Client_ThisServer( ), &r );
  475. } /* Kill_Nick */
  476. /* -eof- */