]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/m_xline.c
Add bandb IRCd APIs.
[irc/rqf/shadowircd.git] / modules / m_xline.c
CommitLineData
212380e3 1/* modules/m_xline.c
2 *
3 * Copyright (C) 2002-2003 Lee Hardy <lee@leeh.co.uk>
4 * Copyright (C) 2002-2005 ircd-ratbox development team
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * 1.Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2.Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3.The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
5366977b 30 * $Id: m_xline.c 3161 2007-01-25 07:23:01Z nenolod $
212380e3 31 */
32
33#include "stdinc.h"
212380e3 34#include "send.h"
35#include "channel.h"
36#include "client.h"
37#include "common.h"
38#include "config.h"
39#include "class.h"
40#include "ircd.h"
41#include "numeric.h"
d3455e2c 42#include "logger.h"
212380e3 43#include "s_serv.h"
44#include "whowas.h"
13ae2f4b 45#include "match.h"
212380e3 46#include "hash.h"
47#include "msg.h"
48#include "parse.h"
49#include "modules.h"
50#include "s_conf.h"
51#include "s_newconf.h"
35f6f850 52#include "reject.h"
212380e3 53
54static int mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
55static int ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
56static int me_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
57static int mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
58static int ms_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
59static int me_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
60
61struct Message xline_msgtab = {
62 "XLINE", 0, 0, 0, MFLG_SLOW,
63 {mg_unreg, mg_not_oper, {ms_xline, 5}, {ms_xline, 5}, {me_xline, 5}, {mo_xline, 3}}
64};
65struct Message unxline_msgtab = {
66 "UNXLINE", 0, 0, 0, MFLG_SLOW,
67 {mg_unreg, mg_not_oper, {ms_unxline, 3}, {ms_unxline, 3}, {me_unxline, 2}, {mo_unxline, 2}}
68};
69
70mapi_clist_av1 xline_clist[] = { &xline_msgtab, &unxline_msgtab, NULL };
5366977b 71DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision: 3161 $");
212380e3 72
cbd758d7 73static char *escape_perm_xline(const char *);
b6c85cc6 74static int valid_xline(struct Client *, const char *, const char *, int);
212380e3 75static void apply_xline(struct Client *client_p, const char *name,
76 const char *reason, int temp_time);
77static void write_xline(struct Client *source_p, struct ConfItem *aconf);
78static void propagate_xline(struct Client *source_p, const char *target,
79 int temp_time, const char *name,
80 const char *type, const char *reason);
81static void cluster_xline(struct Client *source_p, int temp_time,
82 const char *name, const char *reason);
83
84static void handle_remote_xline(struct Client *source_p, int temp_time,
85 const char *name, const char *reason);
86static void handle_remote_unxline(struct Client *source_p, const char *name);
87
60c96e64 88static void remove_xline(struct Client *source_p, const char *name);
5408b484 89static int remove_xline_from_file(struct Client *source_p, const char *gecos);
212380e3 90
91
92/* m_xline()
93 *
94 * parv[1] - thing to xline
95 * parv[2] - optional type/reason
96 * parv[3] - reason
97 */
98static int
99mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
100{
101 struct ConfItem *aconf;
102 const char *name;
cbd758d7 103 char *escapedname;
212380e3 104 const char *reason;
105 const char *target_server = NULL;
106 int temp_time;
107 int loc = 1;
108
109 if(!IsOperXline(source_p))
110 {
111 sendto_one(source_p, form_str(ERR_NOPRIVS),
112 me.name, source_p->name, "xline");
113 return 0;
114 }
115
116 if((temp_time = valid_temp_time(parv[loc])) >= 0)
117 loc++;
118 /* we just set temp_time to -1! */
119 else
120 temp_time = 0;
121
122 name = parv[loc];
123 loc++;
124
125 /* XLINE <gecos> ON <server> :<reason> */
126 if(parc >= loc+2 && !irccmp(parv[loc], "ON"))
127 {
128 if(!IsOperRemoteBan(source_p))
129 {
130 sendto_one(source_p, form_str(ERR_NOPRIVS),
131 me.name, source_p->name, "remoteban");
132 return 0;
133 }
134
135 target_server = parv[loc+1];
136 loc += 2;
137 }
138
139 if(parc <= loc || EmptyString(parv[loc]))
140 {
141 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
142 me.name, source_p->name, "XLINE");
143 return 0;
144 }
145
146 reason = parv[loc];
147
cbd758d7
JT
148 if (temp_time == 0)
149 {
150 escapedname = escape_perm_xline(name);
151 if (strcmp(escapedname, name))
152 sendto_one_notice(source_p, ":Changed xline from [%s] to [%s]",
153 name, escapedname);
154 }
155 else
156 escapedname = rb_strdup(name);
157
212380e3 158 if(target_server != NULL)
159 {
160 propagate_xline(source_p, target_server, temp_time,
cbd758d7 161 escapedname, "2", reason);
212380e3 162
163 if(!match(target_server, me.name))
cbd758d7
JT
164 {
165 rb_free(escapedname);
212380e3 166 return 0;
cbd758d7 167 }
212380e3 168 }
08d11e34 169 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
cbd758d7 170 cluster_xline(source_p, temp_time, escapedname, reason);
212380e3 171
cbd758d7 172 if((aconf = find_xline_mask(escapedname)) != NULL)
212380e3 173 {
174 sendto_one(source_p, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s",
cbd758d7
JT
175 me.name, source_p->name, escapedname, aconf->name, aconf->passwd);
176 rb_free(escapedname);
212380e3 177 return 0;
178 }
179
cbd758d7
JT
180 if(!valid_xline(source_p, escapedname, reason, temp_time))
181 {
182 rb_free(escapedname);
212380e3 183 return 0;
cbd758d7 184 }
212380e3 185
cbd758d7
JT
186 apply_xline(source_p, escapedname, reason, temp_time);
187 rb_free(escapedname);
212380e3 188
189 return 0;
190}
191
192/* ms_xline()
193 *
194 * handles a remote xline
195 */
196static int
197ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
198{
77f3c1f4
JT
199 /* source_p parv[1] parv[2] parv[3] parv[4]
200 * oper target serv xline type reason
212380e3 201 */
202 propagate_xline(source_p, parv[1], 0, parv[2], parv[3], parv[4]);
203
204 if(!IsPerson(source_p))
205 return 0;
206
207 /* destined for me? */
208 if(!match(parv[1], me.name))
209 return 0;
210
211 handle_remote_xline(source_p, 0, parv[2], parv[4]);
212 return 0;
213}
214
215static int
216me_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
217{
218 /* time name type :reason */
219 if(!IsPerson(source_p))
220 return 0;
221
222 handle_remote_xline(source_p, atoi(parv[1]), parv[2], parv[4]);
223 return 0;
224}
225
226static void
227handle_remote_xline(struct Client *source_p, int temp_time,
228 const char *name, const char *reason)
229{
230 struct ConfItem *aconf;
231
232 if(!find_shared_conf(source_p->username, source_p->host,
c88cdb00 233 source_p->servptr->name,
212380e3 234 (temp_time > 0) ? SHARED_TXLINE : SHARED_PXLINE))
235 return;
236
b6c85cc6 237 if(!valid_xline(source_p, name, reason, temp_time))
212380e3 238 return;
239
240 /* already xlined */
0fdb2570 241 if((aconf = find_xline_mask(name)) != NULL)
212380e3 242 {
5366977b 243 sendto_one_notice(source_p, ":[%s] already X-Lined by [%s] - %s", name, aconf->name, aconf->passwd);
212380e3 244 return;
245 }
246
247 apply_xline(source_p, name, reason, temp_time);
248}
249
cbd758d7
JT
250/* escape_perm_xline()
251 *
252 * inputs - gecos
253 * outputs - escaped gecos (allocated with rb_malloc())
254 * side effects - none
255 */
256static char *
257escape_perm_xline(const char *gecos)
258{
259 char *result;
260 int i, j;
261
262 result = rb_malloc(2 * strlen(gecos) + 1);
263 for (i = 0, j = 0; gecos[i] != '\0'; i++)
264 {
265 result[j++] = gecos[i];
266 if (gecos[i] == '"' && gecos[i + 1] == ',')
267 result[j++] = '\\';
268 }
269 result[j] = '\0';
270 return result;
271}
272
212380e3 273/* valid_xline()
274 *
b6c85cc6 275 * inputs - client xlining, gecos, reason and temp time
212380e3 276 * outputs -
277 * side effects - checks the xline for validity, erroring if needed
278 */
279static int
280valid_xline(struct Client *source_p, const char *gecos,
b6c85cc6 281 const char *reason, int temp_time)
212380e3 282{
283 if(EmptyString(reason))
284 {
285 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
286 get_id(&me, source_p),
287 get_id(source_p, source_p), "XLINE");
288 return 0;
289 }
290
b6c85cc6
JT
291 if(temp_time == 0 && strstr(gecos, "\",") != NULL)
292 {
293 sendto_one_notice(source_p,
294 ":Invalid character sequence '\",' in xline, please replace with '\"\\,'");
295 return 0;
296 }
297
212380e3 298 if(strchr(reason, ':') != NULL)
299 {
300 sendto_one_notice(source_p,
301 ":Invalid character ':' in comment");
302 return 0;
303 }
304
305 if(strchr(reason, '"'))
306 {
307 sendto_one_notice(source_p,
308 ":Invalid character '\"' in comment");
309 return 0;
310 }
311
312 if(!valid_wild_card_simple(gecos))
313 {
314 sendto_one_notice(source_p,
315 ":Please include at least %d non-wildcard "
316 "characters with the xline",
317 ConfigFileEntry.min_nonwildcard_simple);
318 return 0;
319 }
320
321 return 1;
322}
323
324void
325apply_xline(struct Client *source_p, const char *name, const char *reason,
326 int temp_time)
327{
328 struct ConfItem *aconf;
329
330 aconf = make_conf();
331 aconf->status = CONF_XLINE;
332
63860dd1 333 aconf->name = rb_strdup(name);
62d28946 334 aconf->passwd = rb_strdup(reason);
212380e3 335 collapse(aconf->name);
336
337 if(temp_time > 0)
338 {
9f6bbe3c 339 aconf->hold = rb_current_time() + temp_time;
212380e3 340
341 sendto_realops_snomask(SNO_GENERAL, L_ALL,
342 "%s added temporary %d min. X-Line for [%s] [%s]",
343 get_oper_name(source_p), temp_time / 60,
344 aconf->name, reason);
345 ilog(L_KLINE, "X %s %d %s %s",
346 get_oper_name(source_p), temp_time / 60,
347 name, reason);
348 sendto_one_notice(source_p, ":Added temporary %d min. X-Line [%s]",
349 temp_time / 60, aconf->name);
350 }
351 else
352 {
353 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added X-Line for [%s] [%s]",
354 get_oper_name(source_p),
355 aconf->name, aconf->passwd);
356 sendto_one_notice(source_p, ":Added X-Line for [%s] [%s]",
357 aconf->name, aconf->passwd);
358 write_xline(source_p, aconf);
359 ilog(L_KLINE, "X %s 0 %s %s",
360 get_oper_name(source_p), name, reason);
361 }
362
b96058d1 363 rb_dlinkAddAlloc(aconf, &xline_conf_list);
212380e3 364 check_xlines();
365}
366
367/* write_xline()
368 *
369 * inputs - gecos, reason, xline type
370 * outputs - writes an xline to the config
371 * side effects -
372 */
373static void
374write_xline(struct Client *source_p, struct ConfItem *aconf)
375{
376 char buffer[BUFSIZE * 2];
377 FILE *out;
378 const char *filename;
44bdc688
JT
379 char *mangle_gecos;
380
381 if(strstr(aconf->name, "\\s"))
382 {
383 char *tmp = LOCAL_COPY(aconf->name);
384 char *orig = tmp;
385 char *new = tmp;
386 while(*orig)
387 {
388 if(*orig == '\\' && *(orig + 1) != '\0')
389 {
390 if(*(orig + 1) == 's')
391 {
392 *new++ = ' ';
393 orig += 2;
394 }
395 /* otherwise skip that and the escaped
396 * character after it, so we dont mistake
397 * \\s as \s --fl
398 */
399 else
400 {
401 *new++ = *orig++;
402 *new++ = *orig++;
403 }
404 }
405 else
406 *new++ = *orig++;
407 }
408
409 *new = '\0';
410 mangle_gecos = tmp;
411 } else
412 mangle_gecos = aconf->name;
212380e3 413
414 filename = ConfigFileEntry.xlinefile;
415
416 if((out = fopen(filename, "a")) == NULL)
417 {
418 sendto_realops_snomask(SNO_GENERAL, L_ALL, "*** Problem opening %s ", filename);
419 sendto_one_notice(source_p, ":*** Problem opening file, xline added temporarily only");
420 return;
421 }
422
581fa5c4 423 rb_sprintf(buffer, "\"%s\",\"0\",\"%s\",\"%s\",%ld\n",
44bdc688 424 mangle_gecos, aconf->passwd,
7db0e309 425 get_oper_name(source_p), (long) rb_current_time());
212380e3 426
427 if(fputs(buffer, out) == -1)
428 {
429 sendto_realops_snomask(SNO_GENERAL, L_ALL, "*** Problem writing to %s", filename);
430 sendto_one_notice(source_p, ":*** Problem writing to file, xline added temporarily only");
431 fclose(out);
432 return;
433 }
434
435 if(fclose(out))
436 {
437 sendto_realops_snomask(SNO_GENERAL, L_ALL, "*** Problem writing to %s", filename);
438 sendto_one_notice(source_p, ":*** Problem writing to file, xline added temporarily only");
439 return;
440 }
441}
442
443static void
444propagate_xline(struct Client *source_p, const char *target,
445 int temp_time, const char *name, const char *type,
446 const char *reason)
447{
448 if(!temp_time)
449 {
450 sendto_match_servs(source_p, target, CAP_CLUSTER, NOCAPS,
451 "XLINE %s %s %s :%s",
452 target, name, type, reason);
453 sendto_match_servs(source_p, target, CAP_ENCAP, CAP_CLUSTER,
454 "ENCAP %s XLINE %d %s 2 :%s",
455 target, temp_time, name, reason);
456 }
457 else
458 sendto_match_servs(source_p, target, CAP_ENCAP, NOCAPS,
459 "ENCAP %s XLINE %d %s %s :%s",
460 target, temp_time, name, type, reason);
461}
462
463static void
464cluster_xline(struct Client *source_p, int temp_time, const char *name,
465 const char *reason)
466{
467 struct remote_conf *shared_p;
08d11e34 468 rb_dlink_node *ptr;
212380e3 469
08d11e34 470 RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
212380e3 471 {
472 shared_p = ptr->data;
473
474 /* old protocol cant handle temps, and we dont really want
475 * to convert them to perm.. --fl
476 */
477 if(!temp_time)
478 {
479 if(!(shared_p->flags & SHARED_PXLINE))
480 continue;
481
482 sendto_match_servs(source_p, shared_p->server, CAP_CLUSTER, NOCAPS,
483 "XLINE %s %s 2 :%s",
484 shared_p->server, name, reason);
485 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, CAP_CLUSTER,
486 "ENCAP %s XLINE 0 %s 2 :%s",
487 shared_p->server, name, reason);
488 }
489 else if(shared_p->flags & SHARED_TXLINE)
490 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, NOCAPS,
491 "ENCAP %s XLINE %d %s 2 :%s",
492 shared_p->server, temp_time, name, reason);
493 }
494}
495
496/* mo_unxline()
497 *
498 * parv[1] - thing to unxline
499 */
500static int
501mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
502{
503 if(!IsOperXline(source_p))
504 {
505 sendto_one(source_p, form_str(ERR_NOPRIVS),
506 me.name, source_p->name, "xline");
507 return 0;
508 }
509
510 if(parc == 4 && !(irccmp(parv[2], "ON")))
511 {
512 if(!IsOperRemoteBan(source_p))
513 {
514 sendto_one(source_p, form_str(ERR_NOPRIVS),
515 me.name, source_p->name, "remoteban");
516 return 0;
517 }
518
519 propagate_generic(source_p, "UNXLINE", parv[3], CAP_CLUSTER,
520 "%s", parv[1]);
521
522 if(match(parv[3], me.name) == 0)
523 return 0;
524 }
08d11e34 525 else if(rb_dlink_list_length(&cluster_conf_list))
212380e3 526 cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER,
527 "%s", parv[1]);
528
212380e3 529 remove_xline(source_p, parv[1]);
530
531 return 0;
532}
533
534/* ms_unxline()
535 *
536 * handles a remote unxline
537 */
538static int
539ms_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
540{
77f3c1f4
JT
541 /* source_p parv[1] parv[2]
542 * oper target server gecos
212380e3 543 */
544 propagate_generic(source_p, "UNXLINE", parv[1], CAP_CLUSTER,
545 "%s", parv[2]);
546
547 if(!match(parv[1], me.name))
548 return 0;
549
550 if(!IsPerson(source_p))
551 return 0;
552
553 handle_remote_unxline(source_p, parv[2]);
554 return 0;
555}
556
557static int
558me_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
559{
560 /* name */
561 if(!IsPerson(source_p))
562 return 0;
563
564 handle_remote_unxline(source_p, parv[1]);
565 return 0;
566}
567
568static void
569handle_remote_unxline(struct Client *source_p, const char *name)
570{
571 if(!find_shared_conf(source_p->username, source_p->host,
c88cdb00 572 source_p->servptr->name, SHARED_UNXLINE))
212380e3 573 return;
574
212380e3 575 remove_xline(source_p, name);
576
577 return;
578}
579
60c96e64 580static void
5408b484 581remove_xline(struct Client *source_p, const char *name)
212380e3 582{
583 struct ConfItem *aconf;
08d11e34 584 rb_dlink_node *ptr;
63860dd1
JT
585 char *encoded;
586
587 encoded = xline_encode_spaces(name);
212380e3 588
08d11e34 589 RB_DLINK_FOREACH(ptr, xline_conf_list.head)
212380e3 590 {
591 aconf = ptr->data;
592
63860dd1 593 if(!irccmp(aconf->name, encoded))
212380e3 594 {
5408b484
JT
595 if (!aconf->hold)
596 {
63860dd1 597 if (!remove_xline_from_file(source_p, encoded))
60c96e64 598 return;
5408b484
JT
599 }
600 else
601 {
602 sendto_one_notice(source_p,
603 ":X-Line for [%s] is removed",
63860dd1 604 encoded);
5408b484
JT
605 sendto_realops_snomask(SNO_GENERAL, L_ALL,
606 "%s has removed the temporary X-Line for: [%s]",
63860dd1 607 get_oper_name(source_p), encoded);
5408b484 608 ilog(L_KLINE, "UX %s %s",
63860dd1 609 get_oper_name(source_p), encoded);
5408b484 610 }
212380e3 611
35f6f850 612 remove_reject_mask(aconf->name, NULL);
212380e3 613 free_conf(aconf);
9f6c3353 614 rb_dlinkDestroy(ptr, &xline_conf_list);
63860dd1 615 rb_free(encoded);
60c96e64 616 return;
212380e3 617 }
618 }
619
63860dd1
JT
620 sendto_one_notice(source_p, ":No X-Line for %s", encoded);
621 rb_free(encoded);
5408b484 622
60c96e64 623 return;
212380e3 624}
625
60c96e64 626/* remove_xline_from_file()
212380e3 627 *
628 * inputs - gecos to remove
629 * outputs -
630 * side effects - removes xline from conf, if exists
5408b484 631 * - does not touch xline_conf_list
212380e3 632 */
5408b484
JT
633static int
634remove_xline_from_file(struct Client *source_p, const char *huntgecos)
212380e3 635{
636 FILE *in, *out;
637 char buf[BUFSIZE];
638 char buff[BUFSIZE];
639 char temppath[BUFSIZE];
640 const char *filename;
641 const char *gecos;
642 mode_t oldumask;
643 char *p;
63860dd1 644 char *encoded;
212380e3 645 int error_on_write = 0;
646 int found_xline = 0;
647
648 filename = ConfigFileEntry.xlinefile;
581fa5c4 649 rb_snprintf(temppath, sizeof(temppath),
212380e3 650 "%s.tmp", ConfigFileEntry.xlinefile);
651
652 if((in = fopen(filename, "r")) == NULL)
653 {
654 sendto_one_notice(source_p, ":Cannot open %s", filename);
5408b484 655 return 0;
212380e3 656 }
657
658 oldumask = umask(0);
659
660 if((out = fopen(temppath, "w")) == NULL)
661 {
662 sendto_one_notice(source_p, ":Cannot open %s", temppath);
663 fclose(in);
664 umask(oldumask);
5408b484 665 return 0;
212380e3 666 }
667
668 umask(oldumask);
669
670 while (fgets(buf, sizeof(buf), in))
671 {
672 if(error_on_write)
673 {
674 if(temppath != NULL)
675 (void) unlink(temppath);
676
677 break;
678 }
679
907468c4 680 rb_strlcpy(buff, buf, sizeof(buff));
212380e3 681
682 if((p = strchr(buff, '\n')) != NULL)
683 *p = '\0';
684
685 if((*buff == '\0') || (*buff == '#'))
686 {
687 error_on_write = (fputs(buf, out) < 0) ? YES : NO;
688 continue;
689 }
690
691 if((gecos = getfield(buff)) == NULL)
692 {
693 error_on_write = (fputs(buf, out) < 0) ? YES : NO;
694 continue;
695 }
696
697 /* matching.. */
63860dd1
JT
698 encoded = xline_encode_spaces(gecos);
699 if(irccmp(encoded, huntgecos) == 0)
212380e3 700 found_xline++;
701 else
702 error_on_write = (fputs(buf, out) < 0) ? YES : NO;
63860dd1 703 rb_free(encoded);
212380e3 704 }
705
706 fclose(in);
707 if (fclose(out))
708 error_on_write = YES;
709
710 if(error_on_write)
711 {
712 sendto_one_notice(source_p,
713 ":Couldn't write temp xline file, aborted");
5408b484 714 return 0;
212380e3 715 }
716 else if(found_xline == 0)
717 {
5408b484 718 sendto_one_notice(source_p, ":Cannot find X-Line for %s in file", huntgecos);
212380e3 719
720 if(temppath != NULL)
721 (void) unlink(temppath);
5408b484 722 return 0;
212380e3 723 }
724
725 if (rename(temppath, filename))
726 {
727 sendto_one_notice(source_p, ":Couldn't rename temp file, aborted");
5408b484 728 return 0;
212380e3 729 }
212380e3 730
731 sendto_one_notice(source_p, ":X-Line for [%s] is removed", huntgecos);
732 sendto_realops_snomask(SNO_GENERAL, L_ALL,
733 "%s has removed the X-Line for: [%s]",
734 get_oper_name(source_p), huntgecos);
735 ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), huntgecos);
5408b484
JT
736
737 return 1;
212380e3 738}