~ubuntu-branches/ubuntu/oneiric/eggdrop/oneiric

« back to all changes in this revision

Viewing changes to src/mod/server.mod/server.c

  • Committer: Bazaar Package Importer
  • Author(s): Guilherme de S. Pastore
  • Date: 2004-06-17 09:15:28 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040617091528-64rrw1sa33lkfhmh
Tags: 1.6.16-2
* Fixed typo on README.Debian
* Fixed hyphens in manual page
* Converted debian/rules to CDBS
* Set path to binary on example config file
* Changed LANGDIR on src/eggdrop.h (Closes: #254824)

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * server.c -- part of server.mod
3
3
 *   basic irc server support
4
4
 *
5
 
 * $Id: server.c,v 1.75 2002/01/02 03:46:40 guppy Exp $
 
5
 * $Id: server.c,v 1.116 2004/05/26 00:20:19 wcc Exp $
6
6
 */
7
7
/*
8
8
 * Copyright (C) 1997 Robey Pointer
9
 
 * Copyright (C) 1999, 2000, 2001, 2002 Eggheads Development Team
 
9
 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Eggheads Development Team
10
10
 *
11
11
 * This program is free software; you can redistribute it and/or
12
12
 * modify it under the terms of the GNU General Public License
31
31
static Function *global = NULL;
32
32
 
33
33
static int ctcp_mode;
34
 
static int serv;                /* sock # of server currently */
35
 
static int strict_host;         /* strict masking of hosts ? */
36
 
static char newserver[121];     /* new server? */
37
 
static int newserverport;       /* new server port? */
38
 
static char newserverpass[121]; /* new server password? */
39
 
static time_t trying_server;    /* trying to connect to a server right now? */
40
 
static int server_lag;          /* how lagged (in seconds) is the server? */
41
 
static char altnick[NICKLEN];   /* possible alternate nickname to use */
42
 
static char raltnick[NICKLEN];  /* random nick created from altnick */
43
 
static int curserv;             /* current position in server list: */
44
 
static int flud_thr;            /* msg flood threshold */
45
 
static int flud_time;           /* msg flood time */
46
 
static int flud_ctcp_thr;       /* ctcp flood threshold */
47
 
static int flud_ctcp_time;      /* ctcp flood time */
48
 
static char initserver[121];    /* what, if anything, to send to the
49
 
                                   server on connection */
50
 
static char botuserhost[121];   /* bot's user@host (refreshed whenever the
51
 
                                   bot joins a channel) */
52
 
                                /* may not be correct user@host BUT it's
53
 
                                   how the server sees it */
54
 
static int keepnick;            /* keep trying to regain my intended
55
 
                                   nickname? */
56
 
static int nick_juped = 0;      /* True if origbotname is juped(RPL437) (dw) */
57
 
static int check_stoned;        /* Check for a stoned server? */
58
 
static int serverror_quit;      /* Disconnect from server if ERROR
59
 
                                   messages received? */
60
 
static int quiet_reject;        /* Quietly reject dcc chat or sends from
61
 
                                   users without access? */
62
 
static int waiting_for_awake;   /* set when i unidle myself, cleared when
63
 
                                   i get the response */
64
 
static time_t server_online;    /* server connection time */
65
 
static time_t server_cycle_wait;        /* seconds to wait before
66
 
                                           re-beginning the server list */
67
 
static char botrealname[121];   /* realname of bot */
68
 
static int min_servs;           /* minimum number of servers to be around */
69
 
static int server_timeout;      /* server timeout for connecting */
70
 
static int never_give_up;       /* never give up when connecting to servers? */
71
 
static int strict_servernames;  /* don't update server list */
72
 
static struct server_list *serverlist;  /* old-style queue, still used by
73
 
                                           server list */
74
 
static int cycle_time;          /* cycle time till next server connect */
75
 
static int default_port;        /* default IRC port */
76
 
static char oldnick[NICKLEN];   /* previous nickname *before* rehash */
77
 
static int trigger_on_ignore;   /* trigger bindings if user is ignored ? */
78
 
static int answer_ctcp;         /* answer how many stacked ctcp's ? */
79
 
static int lowercase_ctcp;      /* answer lowercase CTCP's (non-standard) */
80
 
static int check_mode_r;        /* check for IRCNET +r modes */
 
34
static int serv;                /* sock # of server currently */
 
35
static char newserver[121];     /* new server? */
 
36
static int newserverport;       /* new server port? */
 
37
static char newserverpass[121]; /* new server password? */
 
38
static time_t trying_server;    /* trying to connect to a server right now? */
 
39
static int server_lag;          /* how lagged (in seconds) is the server? */
 
40
static char altnick[NICKLEN];   /* possible alternate nickname to use */
 
41
static char raltnick[NICKLEN];  /* random nick created from altnick */
 
42
static int curserv;             /* current position in server list: */
 
43
static int flud_thr;            /* msg flood threshold */
 
44
static int flud_time;           /* msg flood time */
 
45
static int flud_ctcp_thr;       /* ctcp flood threshold */
 
46
static int flud_ctcp_time;      /* ctcp flood time */
 
47
static char initserver[121];    /* what, if anything, to send to the
 
48
                                 * server on connection */
 
49
static char botuserhost[121];   /* bot's user@host (refreshed whenever the
 
50
                                 * bot joins a channel) */
 
51
                                /* may not be correct user@host BUT it's
 
52
                                 * how the server sees it */
 
53
static int keepnick;            /* keep trying to regain my intended
 
54
                                 * nickname? */
 
55
static int nick_juped = 0;      /* True if origbotname is juped(RPL437) (dw) */
 
56
static int check_stoned;        /* Check for a stoned server? */
 
57
static int serverror_quit;      /* Disconnect from server if ERROR
 
58
                                 * messages received? */
 
59
static int waiting_for_awake;   /* set when i unidle myself, cleared when
 
60
                                 * i get the response */
 
61
static time_t server_online;    /* server connection time */
 
62
static time_t server_cycle_wait;        /* seconds to wait before
 
63
                                         * re-beginning the server list */
 
64
static char botrealname[121];   /* realname of bot */
 
65
static int min_servs;           /* minimum number of servers to be around */
 
66
static int server_timeout;      /* server timeout for connecting */
 
67
static int never_give_up;       /* never give up when connecting to servers? */
 
68
static struct server_list *serverlist;  /* old-style queue, still used by
 
69
                                         * server list */
 
70
static int cycle_time;          /* cycle time till next server connect */
 
71
static int default_port;        /* default IRC port */
 
72
static char oldnick[NICKLEN];   /* previous nickname *before* rehash */
 
73
static int trigger_on_ignore;   /* trigger bindings if user is ignored ? */
 
74
static int answer_ctcp;         /* answer how many stacked ctcp's ? */
 
75
static int lowercase_ctcp;      /* answer lowercase CTCP's (non-standard) */
 
76
static int check_mode_r;        /* check for IRCnet +r modes */
81
77
static int net_type;
82
 
static char connectserver[121]; /* what, if anything, to do before connect
83
 
                                   to the server */
84
 
static int resolvserv;          /* in the process of resolving a server host */
85
 
static int double_mode;         /* allow a msgs to be twice in a queue? */
 
78
static char connectserver[121]; /* what, if anything, to do before connect
 
79
                                 * to the server */
 
80
static int resolvserv;          /* in the process of resolving a server host */
 
81
static int double_mode;         /* allow a msgs to be twice in a queue? */
86
82
static int double_server;
87
83
static int double_help;
88
84
static int double_warned;
89
 
static int lastpingtime;        /* IRCNet LAGmeter support -- drummer */
 
85
static int lastpingtime;        /* IRCnet LAGmeter support -- drummer */
90
86
static char stackablecmds[511];
91
87
static char stackable2cmds[511];
92
88
static time_t last_time;
93
89
static int use_penalties;
94
90
static int use_fastdeq;
95
 
static int nick_len;            /* Maximal nick length allowed on the
96
 
                                   network. */
 
91
static int nick_len;            /* Maximal nick length allowed on the
 
92
                                 * network. */
97
93
static int kick_method;
98
94
static int optimize_kicks;
99
95
 
100
96
 
101
 
static p_tcl_bind_list H_wall, H_raw, H_notc, H_msgm, H_msg, H_flud,
102
 
                       H_ctcr, H_ctcp;
 
97
static p_tcl_bind_list H_wall, H_raw, H_notc, H_msgm, H_msg, H_flud, H_ctcr,
 
98
                       H_ctcp;
103
99
 
104
100
static void empty_msgq(void);
105
101
static void next_server(int *, char *, unsigned int *, char *);
113
109
static void purge_kicks(struct msgq_head *);
114
110
static int deq_kick(int);
115
111
static void msgq_clear(struct msgq_head *qh);
 
112
static int stack_limit;
 
113
static char *realservername;
116
114
 
117
115
#include "servmsg.c"
118
116
 
159
157
      burst--;
160
158
    ok = 1;
161
159
  }
 
160
 
162
161
  if (serv < 0)
163
162
    return;
 
163
 
164
164
  /* Send upto 4 msgs to server if the *critical queue* has anything in it */
165
165
  if (modeq.head) {
166
166
    while (modeq.head && (burst < 4) && ((last_time - now) < MAXPENALTY)) {
174
174
        burst++;
175
175
        continue;
176
176
      }
177
 
      tputs(serv, modeq.head->msg, modeq.head->len);
178
 
      if (debug_output) {
179
 
        modeq.head->msg[strlen(modeq.head->msg) - 1] = 0; /* delete the "\n" */
180
 
        putlog(LOG_SRVOUT, "*", "[m->] %s", modeq.head->msg);
181
 
      }
 
177
      write_to_server(modeq.head->msg, modeq.head->len);
182
178
      modeq.tot--;
183
179
      last_time += calc_penalty(modeq.head->msg);
 
180
      if (raw_log)
 
181
        putlog(LOG_SRVOUT, "*", "[m->] %s", modeq.head->msg);
184
182
      q = modeq.head->next;
185
183
      nfree(modeq.head->msg);
186
184
      nfree(modeq.head);
191
189
      modeq.last = 0;
192
190
    return;
193
191
  }
 
192
 
194
193
  /* Send something from the normal msg q even if we're slightly bursting */
195
194
  if (burst > 1)
196
195
    return;
 
196
 
197
197
  if (mq.head) {
198
198
    burst++;
 
199
 
199
200
    if (deq_kick(DP_SERVER))
200
201
      return;
 
202
 
201
203
    if (fast_deq(DP_SERVER))
202
204
      return;
203
 
    tputs(serv, mq.head->msg, mq.head->len);
204
 
    if (debug_output) {
205
 
      mq.head->msg[strlen(mq.head->msg) - 1] = 0; /* delete the "\n" */
206
 
      putlog(LOG_SRVOUT, "*", "[s->] %s", mq.head->msg);
207
 
    }
 
205
 
 
206
    write_to_server(mq.head->msg, mq.head->len);
208
207
    mq.tot--;
209
208
    last_time += calc_penalty(mq.head->msg);
 
209
    if (raw_log)
 
210
      putlog(LOG_SRVOUT, "*", "[s->] %s", mq.head->msg);
210
211
    q = mq.head->next;
211
212
    nfree(mq.head->msg);
212
213
    nfree(mq.head);
215
216
      mq.last = NULL;
216
217
    return;
217
218
  }
 
219
 
218
220
  /* Never send anything from the help queue unless everything else is
219
221
   * finished.
220
222
   */
221
223
  if (!hq.head || burst || !ok)
222
224
    return;
 
225
 
223
226
  if (deq_kick(DP_HELP))
224
227
    return;
 
228
 
225
229
  if (fast_deq(DP_HELP))
226
230
    return;
227
 
  tputs(serv, hq.head->msg, hq.head->len);
228
 
  if (debug_output) {
229
 
    hq.head->msg[strlen(hq.head->msg) - 1] = 0; /* delete the "\n" */
230
 
    putlog(LOG_SRVOUT, "*", "[h->] %s", hq.head->msg);
231
 
  }
 
231
 
 
232
  write_to_server(hq.head->msg, hq.head->len);
232
233
  hq.tot--;
233
234
  last_time += calc_penalty(hq.head->msg);
 
235
  if (raw_log)
 
236
    putlog(LOG_SRVOUT, "*", "[h->] %s", hq.head->msg);
234
237
  q = hq.head->next;
235
238
  nfree(hq.head->msg);
236
239
  nfree(hq.head);
239
242
    hq.last = NULL;
240
243
}
241
244
 
242
 
static int calc_penalty(char * msg)
 
245
static int calc_penalty(char *msg)
243
246
{
244
247
  char *cmd, *par1, *par2, *par3;
245
248
  register int penalty, i, ii;
246
249
 
247
 
  if (!use_penalties &&
248
 
      net_type != NETT_UNDERNET && net_type != NETT_HYBRID_EFNET)
 
250
  if (!use_penalties && net_type != NETT_UNDERNET &&
 
251
      net_type != NETT_HYBRID_EFNET)
249
252
    return 0;
250
 
  if (msg[strlen(msg) - 1] == '\n')
251
 
    msg[strlen(msg) - 1] = '\0';
 
253
 
252
254
  cmd = newsplit(&msg);
253
255
  if (msg)
254
256
    i = strlen(msg);
255
257
  else
256
258
    i = strlen(cmd);
257
 
  last_time -= 2; /* undo eggdrop standard flood prot */
 
259
  last_time -= 2;               /* undo eggdrop standard flood prot */
258
260
  if (net_type == NETT_UNDERNET || net_type == NETT_HYBRID_EFNET) {
259
261
    last_time += (2 + i / 120);
260
262
    return 0;
261
263
  }
262
264
  penalty = (1 + i / 100);
263
265
  if (!egg_strcasecmp(cmd, "KICK")) {
264
 
    par1 = newsplit(&msg); /* channel */
265
 
    par2 = newsplit(&msg); /* victim(s) */
 
266
    par1 = newsplit(&msg);      /* channel */
 
267
    par2 = newsplit(&msg);      /* victim(s) */
266
268
    par3 = splitnicks(&par2);
267
269
    penalty++;
268
270
    while (strlen(par3) > 0) {
277
279
    }
278
280
  } else if (!egg_strcasecmp(cmd, "MODE")) {
279
281
    i = 0;
280
 
    par1 = newsplit(&msg); /* channel */
281
 
    par2 = newsplit(&msg); /* mode(s) */
 
282
    par1 = newsplit(&msg);      /* channel */
 
283
    par2 = newsplit(&msg);      /* mode(s) */
282
284
    if (!strlen(par2))
283
285
      i++;
284
286
    while (strlen(par2) > 0) {
300
302
    penalty += (ii * i);
301
303
  } else if (!egg_strcasecmp(cmd, "TOPIC")) {
302
304
    penalty++;
303
 
    par1 = newsplit(&msg); /* channel */
304
 
    par2 = newsplit(&msg); /* topic */
305
 
    if (strlen(par2) > 0) {  /* topic manipulation => 2 penalty points */
 
305
    par1 = newsplit(&msg);      /* channel */
 
306
    par2 = newsplit(&msg);      /* topic */
 
307
    if (strlen(par2) > 0) {     /* topic manipulation => 2 penalty points */
306
308
      penalty += 2;
307
309
      par3 = splitnicks(&par1);
308
310
      while (strlen(par1) > 0) {
311
313
      }
312
314
    }
313
315
  } else if (!egg_strcasecmp(cmd, "PRIVMSG") ||
314
 
             !egg_strcasecmp(cmd, "NOTICE")) {
315
 
    par1 = newsplit(&msg); /* channel(s)/nick(s) */
 
316
             !egg_strcasecmp(cmd, "NOTICE")) {
 
317
    par1 = newsplit(&msg);      /* channel(s)/nick(s) */
316
318
    /* Add one sec penalty for each recipient */
317
319
    while (strlen(par1) > 0) {
318
320
      splitnicks(&par1);
319
321
      penalty++;
320
322
    }
321
323
  } else if (!egg_strcasecmp(cmd, "WHO")) {
322
 
    par1 = newsplit(&msg); /* masks */
 
324
    par1 = newsplit(&msg);      /* masks */
323
325
    par2 = par1;
324
326
    while (strlen(par1) > 0) {
325
327
      par2 = splitnicks(&par1);
326
 
      if (strlen(par2) > 4)   /* long WHO-masks receive less penalty */
 
328
      if (strlen(par2) > 4)     /* long WHO-masks receive less penalty */
327
329
        penalty += 3;
328
330
      else
329
331
        penalty += 5;
357
359
  } else if (!egg_strcasecmp(cmd, "DNS")) {
358
360
    penalty += 2;
359
361
  } else
360
 
    penalty++; /* just add standard-penalty */
 
362
    penalty++;                  /* just add standard-penalty */
361
363
  /* Shouldn't happen, but you never know... */
362
364
  if (penalty > 99)
363
365
    penalty = 99;
364
366
  if (penalty < 2) {
365
 
    putlog(LOG_SRVOUT, "*", "Penalty < 2sec, that's impossible!");
 
367
    putlog(LOG_SRVOUT, "*", "Penalty < 2sec; that's impossible!");
366
368
    penalty = 2;
367
369
  }
368
 
  if (debug_output && penalty != 0)
 
370
  if (raw_log && penalty != 0)
369
371
    putlog(LOG_SRVOUT, "*", "Adding penalty: %i", penalty);
370
372
  return penalty;
371
373
}
394
396
  struct msgq *m, *nm;
395
397
  char msgstr[511], nextmsgstr[511], tosend[511], victims[511], stackable[511],
396
398
       *msg, *nextmsg, *cmd, *nextcmd, *to, *nextto, *stckbl;
397
 
  int len, doit = 0, found = 0, who_count =0, stack_method = 1;
 
399
  int len, doit = 0, found = 0, cmd_count = 0, stack_method = 1;
398
400
 
399
401
  if (!use_fastdeq)
400
402
    return 0;
 
403
 
401
404
  switch (which) {
402
 
    case DP_MODE:
403
 
      h = &modeq;
404
 
      break;
405
 
    case DP_SERVER:
406
 
      h = &mq;
407
 
      break;
408
 
    case DP_HELP:
409
 
      h = &hq;
410
 
      break;
411
 
    default:
412
 
      return 0;
 
405
  case DP_MODE:
 
406
    h = &modeq;
 
407
    break;
 
408
  case DP_SERVER:
 
409
    h = &mq;
 
410
    break;
 
411
  case DP_HELP:
 
412
    h = &hq;
 
413
    break;
 
414
  default:
 
415
    return 0;
413
416
  }
 
417
 
414
418
  m = h->head;
415
419
  strncpyz(msgstr, m->msg, sizeof msgstr);
416
420
  msg = msgstr;
418
422
  if (use_fastdeq > 1) {
419
423
    strncpyz(stackable, stackablecmds, sizeof stackable);
420
424
    stckbl = stackable;
421
 
    while (strlen(stckbl) > 0)
 
425
    while (strlen(stckbl) > 0) {
422
426
      if (!egg_strcasecmp(newsplit(&stckbl), cmd)) {
423
427
        found = 1;
424
428
        break;
425
429
      }
 
430
    }
 
431
 
426
432
    /* If use_fastdeq is 2, only commands in the list should be stacked. */
427
433
    if (use_fastdeq == 2 && !found)
428
434
      return 0;
429
 
    /* If use_fastdeq is 3, only commands that are _not_ in the list
430
 
     * should be stacked.
431
 
     */
 
435
 
 
436
    /* If use_fastdeq is 3, only commands _not_ in the list should be stacked. */
432
437
    if (use_fastdeq == 3 && found)
433
438
      return 0;
 
439
 
434
440
    /* we check for the stacking method (default=1) */
435
441
    strncpyz(stackable, stackable2cmds, sizeof stackable);
436
442
    stckbl = stackable;
438
444
      if (!egg_strcasecmp(newsplit(&stckbl), cmd)) {
439
445
        stack_method = 2;
440
446
        break;
441
 
      }    
 
447
      }
442
448
  }
443
449
  to = newsplit(&msg);
444
450
  len = strlen(to);
445
 
  if (to[len - 1] == '\n')
446
 
    to[len -1] = 0;
447
451
  simple_sprintf(victims, "%s", to);
448
452
  while (m) {
449
453
    nm = m->next;
454
458
    nextcmd = newsplit(&nextmsg);
455
459
    nextto = newsplit(&nextmsg);
456
460
    len = strlen(nextto);
457
 
    if (nextto[len - 1] == '\n')
458
 
      nextto[len - 1] = 0;
459
 
    if ( strcmp(to, nextto) /* we don't stack to the same recipients */
460
 
        && !strcmp(cmd, nextcmd) && !strcmp(msg, nextmsg)
461
 
        && ((strlen(cmd) + strlen(victims) + strlen(nextto)
462
 
             + strlen(msg) + 2) < 510)
463
 
        && (egg_strcasecmp(cmd, "WHO") || who_count < MAXPENALTY - 1)) {
464
 
      if (!egg_strcasecmp(cmd, "WHO"))
465
 
        who_count++;
 
461
    if (strcmp(to, nextto) &&!strcmp(cmd, nextcmd) && !strcmp(msg, nextmsg) &&
 
462
        ((strlen(cmd) + strlen(victims) + strlen(nextto) + strlen(msg) + 2) <
 
463
        510) && (!stack_limit || cmd_count < stack_limit - 1)) {
 
464
      cmd_count++;
466
465
      if (stack_method == 1)
467
 
        simple_sprintf(victims, "%s,%s", victims, nextto);
 
466
        simple_sprintf(victims, "%s,%s", victims, nextto);
468
467
      else
469
 
        simple_sprintf(victims, "%s %s", victims, nextto);
 
468
        simple_sprintf(victims, "%s %s", victims, nextto);
470
469
      doit = 1;
471
470
      m->next = nm->next;
472
471
      if (!nm->next)
480
479
  if (doit) {
481
480
    simple_sprintf(tosend, "%s %s %s", cmd, victims, msg);
482
481
    len = strlen(tosend);
483
 
    tosend[len - 1] = '\n';
484
 
    tputs(serv, tosend, len);
 
482
    write_to_server(tosend, len);
485
483
    m = h->head->next;
486
484
    nfree(h->head->msg);
487
485
    nfree(h->head);
489
487
    if (!h->head)
490
488
      h->last = 0;
491
489
    h->tot--;
492
 
    if (debug_output) {
493
 
      tosend[len - 1] = 0;
494
 
      switch (which) {
495
 
        case DP_MODE:
496
 
          putlog(LOG_SRVOUT, "*", "[m=>] %s", tosend);
497
 
          break;
498
 
        case DP_SERVER:
499
 
          putlog(LOG_SRVOUT, "*", "[s=>] %s", tosend);
500
 
          break;
501
 
        case DP_HELP:
502
 
          putlog(LOG_SRVOUT, "*", "[h=>] %s", tosend);
503
 
          break;
504
 
      }
505
 
    }
506
490
    last_time += calc_penalty(tosend);
 
491
    if (raw_log) {
 
492
      switch (which) {
 
493
      case DP_MODE:
 
494
        putlog(LOG_SRVOUT, "*", "[m=>] %s", tosend);
 
495
        break;
 
496
      case DP_SERVER:
 
497
        putlog(LOG_SRVOUT, "*", "[s=>] %s", tosend);
 
498
        break;
 
499
      case DP_HELP:
 
500
        putlog(LOG_SRVOUT, "*", "[h=>] %s", tosend);
 
501
        break;
 
502
      }
 
503
    }
507
504
    return 1;
508
505
  }
509
506
  return 0;
511
508
 
512
509
static void check_queues(char *oldnick, char *newnick)
513
510
{
514
 
  if (optimize_kicks == 2) {
515
 
    if (modeq.head)
516
 
      parse_q(&modeq, oldnick, newnick);
517
 
    if (mq.head)
518
 
      parse_q(&mq, oldnick, newnick);
519
 
    if (hq.head)
520
 
      parse_q(&hq, oldnick, newnick);
521
 
  }
 
511
  if (optimize_kicks != 2)
 
512
    return;
 
513
  if (modeq.head)
 
514
    parse_q(&modeq, oldnick, newnick);
 
515
  if (mq.head)
 
516
    parse_q(&mq, oldnick, newnick);
 
517
  if (hq.head)
 
518
    parse_q(&hq, oldnick, newnick);
522
519
}
523
520
 
524
521
static void parse_q(struct msgq_head *q, char *oldnick, char *newnick)
532
529
    if (optimize_kicks == 2 && !egg_strncasecmp(m->msg, "KICK ", 5)) {
533
530
      newnicks[0] = 0;
534
531
      strncpyz(buf, m->msg, sizeof buf);
535
 
      if (buf[0] && (buf[strlen(buf)-1] == '\n'))
536
 
        buf[strlen(buf)-1] = '\0';
537
532
      msg = buf;
538
533
      newsplit(&msg);
539
534
      chan = newsplit(&msg);
549
544
        } else
550
545
          egg_snprintf(newnicks, sizeof newnicks, ",%s", nick);
551
546
      }
552
 
      egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan,
553
 
                   newnicks + 1, msg);
 
547
      egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s", chan,
 
548
                   newnicks + 1, msg);
554
549
    }
555
550
    if (changed) {
556
551
      if (newnicks[0] == 0) {
592
587
      newnicks[0] = 0;
593
588
      changed = 0;
594
589
      strncpyz(buf, m->msg, sizeof buf);
595
 
      if (buf[0] && (buf[strlen(buf)-1] == '\n'))
596
 
        buf[strlen(buf)-1] = '\0';
597
590
      reason = buf;
598
591
      newsplit(&reason);
599
592
      chan = newsplit(&reason);
614
607
        if (found)
615
608
          egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks, nick);
616
609
        else {
617
 
          putlog(LOG_SRVOUT, "*", "%s isn't on any target channel, removing "
618
 
                 "kick...", nick);
 
610
          putlog(LOG_SRVOUT, "*", "%s isn't on any target channel; removing "
 
611
                 "kick.", nick);
619
612
          changed = 1;
620
613
        }
621
614
      }
633
626
            q->last = 0;
634
627
        } else {
635
628
          nfree(m->msg);
636
 
          egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan,
637
 
                       newnicks + 1, reason);
 
629
          egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s", chan,
 
630
                       newnicks + 1, reason);
638
631
          m->msg = nmalloc(strlen(newmsg) + 1);
639
632
          m->len = strlen(newmsg);
640
633
          strcpy(m->msg, newmsg);
659
652
 
660
653
  if (!optimize_kicks)
661
654
    return 0;
 
655
 
662
656
  newnicks[0] = 0;
663
657
  switch (which) {
664
 
    case DP_MODE:
665
 
      h = &modeq;
666
 
      break;
667
 
    case DP_SERVER:
668
 
      h = &mq;
669
 
      break;
670
 
    case DP_HELP:
671
 
      h = &hq;
672
 
      break;
673
 
    default:
674
 
      return 0;
 
658
  case DP_MODE:
 
659
    h = &modeq;
 
660
    break;
 
661
  case DP_SERVER:
 
662
    h = &mq;
 
663
    break;
 
664
  case DP_HELP:
 
665
    h = &hq;
 
666
    break;
 
667
  default:
 
668
    return 0;
675
669
  }
 
670
 
676
671
  if (egg_strncasecmp(h->head->msg, "KICK", 4))
677
672
    return 0;
 
673
 
678
674
  if (optimize_kicks == 2) {
679
675
    purge_kicks(h);
680
676
    if (!h->head)
681
677
      return 1;
682
678
  }
 
679
 
683
680
  if (egg_strncasecmp(h->head->msg, "KICK", 4))
684
681
    return 0;
 
682
 
685
683
  msg = h->head;
686
684
  strncpyz(buf, msg->msg, sizeof buf);
687
685
  reason = buf;
690
688
  nicks = newsplit(&reason);
691
689
  while (strlen(nicks) > 0) {
692
690
    egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks,
693
 
                 newsplit(&nicks));
 
691
                 newsplit(&nicks));
694
692
    nr++;
695
693
  }
696
694
  for (m = msg->next, lm = NULL; m && (nr < kick_method);) {
698
696
      changed = 0;
699
697
      newnicks2[0] = 0;
700
698
      strncpyz(buf2, m->msg, sizeof buf2);
701
 
      if (buf2[0] && (buf2[strlen(buf2)-1] == '\n'))
702
 
        buf2[strlen(buf2)-1] = '\0';
703
699
      reason2 = buf2;
704
700
      newsplit(&reason2);
705
701
      chan2 = newsplit(&reason2);
707
703
      if (!egg_strcasecmp(chan, chan2) && !egg_strcasecmp(reason, reason2)) {
708
704
        while (strlen(nicks) > 0) {
709
705
          nick = splitnicks(&nicks);
710
 
          if ((nr < kick_method) &&
711
 
             ((9 + strlen(chan) + strlen(newnicks) + strlen(nick) +
712
 
             strlen(reason)) < 510)) {
 
706
          if ((nr < kick_method) && ((9 + strlen(chan) + strlen(newnicks) +
 
707
              strlen(nick) + strlen(reason)) < 510)) {
713
708
            egg_snprintf(newnicks, sizeof newnicks, "%s,%s", newnicks, nick);
714
709
            nr++;
715
710
            changed = 1;
731
726
            h->last = 0;
732
727
        } else {
733
728
          nfree(m->msg);
734
 
          egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan2,
735
 
                       newnicks2 + 1, reason);
 
729
          egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s", chan2,
 
730
                       newnicks2 + 1, reason);
736
731
          m->msg = nmalloc(strlen(newmsg) + 1);
737
732
          m->len = strlen(newmsg);
738
733
          strcpy(m->msg, newmsg);
745
740
    else
746
741
      m = h->head->next;
747
742
  }
748
 
  egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s\n", chan, newnicks + 1,
749
 
               reason);
750
 
  tputs(serv, newmsg, strlen(newmsg));
751
 
  if (debug_output) {
752
 
    newmsg[strlen(newmsg) - 1] = 0;
753
 
    switch (which) {
754
 
      case DP_MODE:
755
 
        putlog(LOG_SRVOUT, "*", "[m->] %s", newmsg);
756
 
        break;
757
 
      case DP_SERVER:
758
 
        putlog(LOG_SRVOUT, "*", "[s->] %s", newmsg);
759
 
        break;
760
 
      case DP_HELP:
761
 
        putlog(LOG_SRVOUT, "*", "[h->] %s", newmsg);
762
 
        break;
763
 
    }
764
 
    debug3("Changed: %d, kick-method: %d, nr: %d", changed, kick_method, nr);
765
 
  }
 
743
  egg_snprintf(newmsg, sizeof newmsg, "KICK %s %s %s", chan, newnicks + 1,
 
744
               reason);
 
745
  write_to_server(newmsg, strlen(newmsg));
766
746
  h->tot--;
767
747
  last_time += calc_penalty(newmsg);
 
748
  if (raw_log) {
 
749
    switch (which) {
 
750
    case DP_MODE:
 
751
      putlog(LOG_SRVOUT, "*", "[m->] %s", newmsg);
 
752
      break;
 
753
    case DP_SERVER:
 
754
      putlog(LOG_SRVOUT, "*", "[s->] %s", newmsg);
 
755
      break;
 
756
    case DP_HELP:
 
757
      putlog(LOG_SRVOUT, "*", "[h->] %s", newmsg);
 
758
      break;
 
759
    }
 
760
    debug3("Changed: %d, kick-method: %d, nr: %d", changed, kick_method, nr);
 
761
  }
768
762
  m = h->head->next;
769
763
  nfree(h->head->msg);
770
764
  nfree(h->head);
784
778
  burst = 0;
785
779
}
786
780
 
787
 
/* Use when sending msgs... will spread them out so there's no flooding.
 
781
/* Queues outgoing messages so there's no flooding.
788
782
 */
789
783
static void queue_server(int which, char *buf, int len)
790
784
{
791
 
  struct msgq_head *h = NULL,
792
 
                    tempq;
793
 
  struct msgq      *q, *tq, *tqq;
794
 
  int               doublemsg = 0,
795
 
                    qnext = 0;
 
785
  struct msgq_head *h = NULL, tempq;
 
786
  struct msgq *q, *tq, *tqq;
 
787
  int doublemsg = 0, qnext = 0;
796
788
 
797
789
  /* Don't even BOTHER if there's no server online. */
798
790
  if (serv < 0)
799
791
    return;
 
792
 
 
793
  /* Remove \r\n. We will add these back when we send the text to the server.
 
794
   * - Wcc [01/09/2004]
 
795
   */
 
796
  remove_crlf(&buf);
 
797
  buf[510] = 0;
 
798
  len = strlen(buf);
 
799
 
800
800
  /* No queue for PING and PONG - drummer */
801
801
  if (!egg_strncasecmp(buf, "PING", 4) || !egg_strncasecmp(buf, "PONG", 4)) {
802
802
    if (buf[1] == 'I' || buf[1] == 'i')
803
 
      lastpingtime = now;       /* lagmeter */
804
 
    tputs(serv, buf, len);
 
803
      lastpingtime = now;
 
804
    write_to_server(buf, len);
 
805
    if (raw_log)
 
806
      putlog(LOG_SRVOUT, "*", "[m->] %s", buf);
805
807
    return;
806
808
  }
807
809
 
809
811
  case DP_MODE_NEXT:
810
812
    qnext = 1;
811
813
    /* Fallthrough */
 
814
 
812
815
  case DP_MODE:
813
816
    h = &modeq;
814
817
    tempq = modeq;
819
822
  case DP_SERVER_NEXT:
820
823
    qnext = 1;
821
824
    /* Fallthrough */
 
825
 
822
826
  case DP_SERVER:
823
827
    h = &mq;
824
828
    tempq = mq;
829
833
  case DP_HELP_NEXT:
830
834
    qnext = 1;
831
835
    /* Fallthrough */
 
836
 
832
837
  case DP_HELP:
833
838
    h = &hq;
834
839
    tempq = hq;
837
842
    break;
838
843
 
839
844
  default:
840
 
    putlog(LOG_MISC, "*", "!!! queuing unknown type to server!!");
 
845
    putlog(LOG_MISC, "*", "Warning: queuing unknown type to server!");
841
846
    return;
842
847
  }
843
848
 
844
849
  if (h->tot < maxqmsg) {
845
850
    /* Don't queue msg if it's already queued?  */
846
 
    if (!doublemsg)
 
851
    if (!doublemsg) {
847
852
      for (tq = tempq.head; tq; tq = tqq) {
848
 
        tqq = tq->next;
849
 
        if (!egg_strcasecmp(tq->msg, buf)) {
850
 
          if (!double_warned) {
851
 
            if (buf[len - 1] == '\n')
852
 
              buf[len - 1] = 0;
853
 
            debug1("msg already queued. skipping: %s", buf);
854
 
            double_warned = 1;
855
 
          }
856
 
          return;
857
 
        }
 
853
        tqq = tq->next;
 
854
        if (!egg_strcasecmp(tq->msg, buf)) {
 
855
          if (!double_warned) {
 
856
            debug1("Message already queued; skipping: %s", buf);
 
857
            double_warned = 1;
 
858
          }
 
859
          return;
 
860
        }
858
861
      }
 
862
    }
859
863
 
860
864
    q = nmalloc(sizeof(struct msgq));
861
 
    if (qnext)
 
865
 
 
866
    /* Insert into queue. */
 
867
    if (qnext) {
862
868
      q->next = h->head;
863
 
    else
 
869
      h->head = q;
 
870
      if (!h->last)
 
871
        h->last = q;
 
872
    }
 
873
    else {
864
874
      q->next = NULL;
865
 
    if (h->head) {
866
 
      if (!qnext)
 
875
      if (h->last)
867
876
        h->last->next = q;
868
 
    } else
869
 
      h->head = q;
870
 
    if (qnext)
871
 
       h->head = q;
872
 
    h->last = q;
 
877
      else
 
878
        h->head = q;
 
879
      h->last = q;
 
880
    }
 
881
 
873
882
    q->len = len;
874
883
    q->msg = nmalloc(len + 1);
875
 
    strncpyz(q->msg, buf, len + 1);
 
884
    memcpy(q->msg, buf, len);
 
885
    q->msg[len] = 0;
876
886
    h->tot++;
877
887
    h->warned = 0;
878
888
    double_warned = 0;
 
889
 
 
890
    if (raw_log) {
 
891
      switch (which) {
 
892
      case DP_MODE:
 
893
        putlog(LOG_SRVOUT, "*", "[!m] %s", buf);
 
894
        break;
 
895
      case DP_SERVER:
 
896
        putlog(LOG_SRVOUT, "*", "[!s] %s", buf);
 
897
        break;
 
898
      case DP_HELP:
 
899
        putlog(LOG_SRVOUT, "*", "[!h] %s", buf);
 
900
        break;
 
901
      case DP_MODE_NEXT:
 
902
        putlog(LOG_SRVOUT, "*", "[!!m] %s", buf);
 
903
        break;
 
904
      case DP_SERVER_NEXT:
 
905
        putlog(LOG_SRVOUT, "*", "[!!s] %s", buf);
 
906
        break;
 
907
      case DP_HELP_NEXT:
 
908
        putlog(LOG_SRVOUT, "*", "[!!h] %s", buf);
 
909
        break;
 
910
      }
 
911
    }
879
912
  } else {
880
913
    if (!h->warned) {
881
 
      switch (which) {   
882
 
        case DP_MODE_NEXT:
883
 
        /* Fallthrough */
884
 
        case DP_MODE:
885
 
      putlog(LOG_MISC, "*", "!!! OVER MAXIMUM MODE QUEUE");
886
 
        break;
887
 
    
888
 
        case DP_SERVER_NEXT:
889
 
        /* Fallthrough */
890
 
        case DP_SERVER:
891
 
        putlog(LOG_MISC, "*", "!!! OVER MAXIMUM SERVER QUEUE");
892
 
        break;
893
 
            
894
 
        case DP_HELP_NEXT:
895
 
        /* Fallthrough */
896
 
        case DP_HELP:
897
 
        putlog(LOG_MISC, "*", "!!! OVER MAXIMUM HELP QUEUE");
898
 
        break;
 
914
      switch (which) {
 
915
      case DP_MODE_NEXT:
 
916
        /* Fallthrough */
 
917
      case DP_MODE:
 
918
        putlog(LOG_MISC, "*", "Warning: over maximum mode queue!");
 
919
        break;
 
920
 
 
921
      case DP_SERVER_NEXT:
 
922
        /* Fallthrough */
 
923
      case DP_SERVER:
 
924
        putlog(LOG_MISC, "*", "Warning: over maximum server queue!");
 
925
        break;
 
926
 
 
927
      case DP_HELP_NEXT:
 
928
        /* Fallthrough */
 
929
      case DP_HELP:
 
930
        putlog(LOG_MISC, "*", "Warning: over maximum help queue!");
 
931
        break;
899
932
      }
900
933
    }
901
934
    h->warned = 1;
902
935
  }
903
936
 
904
 
  if (debug_output) {
905
 
    if (buf[len - 1] == '\n')
906
 
      buf[len - 1] = 0;
907
 
    switch (which) {
908
 
    case DP_MODE:
909
 
      putlog(LOG_SRVOUT, "*", "[!m] %s", buf);
910
 
      break;
911
 
    case DP_SERVER:
912
 
      putlog(LOG_SRVOUT, "*", "[!s] %s", buf);
913
 
      break;
914
 
    case DP_HELP:
915
 
      putlog(LOG_SRVOUT, "*", "[!h] %s", buf);
916
 
      break;
917
 
    case DP_MODE_NEXT:
918
 
      putlog(LOG_SRVOUT, "*", "[!!m] %s", buf);
919
 
      break;
920
 
    case DP_SERVER_NEXT:
921
 
      putlog(LOG_SRVOUT, "*", "[!!s] %s", buf);
922
 
      break;
923
 
    case DP_HELP_NEXT:
924
 
      putlog(LOG_SRVOUT, "*", "[!!h] %s", buf);
925
 
      break;
926
 
    }
927
 
  }
928
 
 
929
937
  if (which == DP_MODE || which == DP_MODE_NEXT)
930
 
    deq_msg();          /* DP_MODE needs to be sent ASAP, flush if
931
 
                           possible. */
 
938
    deq_msg(); /* DP_MODE needs to be sent ASAP, flush if possible. */
932
939
}
933
940
 
934
941
/* Add a new server to the server_list.
947
954
 
948
955
    x->next = 0;
949
956
    x->realname = 0;
 
957
    x->port = 0;
950
958
    if (z)
951
959
      z->next = x;
952
960
    else
965
973
      ss = q;
966
974
      q = strchr(ss, ':');
967
975
      if (!q) {
968
 
        x->pass = 0;
 
976
        x->pass = 0;
969
977
      } else {
970
 
        *q++ = 0;
971
 
        x->pass = nmalloc(strlen(q) + 1);
972
 
        strcpy(x->pass, q);
 
978
        *q++ = 0;
 
979
        x->pass = nmalloc(strlen(q) + 1);
 
980
        strcpy(x->pass, q);
973
981
      }
974
982
      x->port = atoi(ss);
975
983
    }
977
985
  }
978
986
}
979
987
 
 
988
 
980
989
/* Clear out the given server_list.
981
990
 */
982
991
static void clearq(struct server_list *xx)
1008
1017
  if (x == NULL)
1009
1018
    return;
1010
1019
  /* -1  -->  Go to specified server */
1011
 
  if (*ptr == (-1)) {
 
1020
  if (*ptr == -1) {
1012
1021
    for (; x; x = x->next) {
1013
1022
      if (x->port == *port) {
1014
 
        if (!egg_strcasecmp(x->name, serv)) {
1015
 
          *ptr = i;
1016
 
          return;
1017
 
        } else if (x->realname && !egg_strcasecmp(x->realname, serv)) {
1018
 
          *ptr = i;
1019
 
          strncpyz(serv, x->realname, sizeof serv);
1020
 
          return;
1021
 
        }
 
1023
        if (!egg_strcasecmp(x->name, serv)) {
 
1024
          *ptr = i;
 
1025
          return;
 
1026
        } else if (x->realname && !egg_strcasecmp(x->realname, serv)) {
 
1027
          *ptr = i;
 
1028
          strncpyz(serv, x->realname, sizeof serv);
 
1029
          return;
 
1030
        }
1022
1031
      }
1023
1032
      i++;
1024
1033
    }
1048
1057
  if (x != NULL) {
1049
1058
    x = x->next;
1050
1059
    (*ptr)++;
1051
 
  }                             /* Go to next server */
 
1060
  }                             /* Go to next server */
1052
1061
  if (x == NULL) {
1053
1062
    x = serverlist;
1054
1063
    *ptr = 0;
1055
 
  }                             /* Start over at the beginning */
 
1064
  }                             /* Start over at the beginning */
1056
1065
  strcpy(serv, x->name);
1057
1066
  *port = x->port ? x->port : default_port;
1058
1067
  if (x->pass)
1066
1075
  Function F = (Function) cd;
1067
1076
  char x[20];
1068
1077
 
1069
 
  BADARGS(7, 7, " nick user@host handle desto/chan keyword/nick text");
 
1078
  BADARGS(7, 7, " nick user@host handle dest/chan keyword text");
 
1079
 
1070
1080
  CHECKVALIDITY(server_6char);
1071
1081
  egg_snprintf(x, sizeof x, "%d",
1072
 
               F(argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]));
 
1082
               F(argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]));
1073
1083
  Tcl_AppendResult(irp, x, NULL);
1074
1084
  return TCL_OK;
1075
1085
}
1078
1088
{
1079
1089
  Function F = (Function) cd;
1080
1090
 
1081
 
  BADARGS(6, 6, " nick user@host handle channel text");
 
1091
  BADARGS(6, 6, " nick user@host handle dest/channel text");
 
1092
 
1082
1093
  CHECKVALIDITY(server_5char);
1083
1094
  F(argv[1], argv[2], argv[3], argv[4], argv[5]);
1084
1095
  return TCL_OK;
1089
1100
  Function F = (Function) cd;
1090
1101
 
1091
1102
  BADARGS(3, 3, " nick msg");
 
1103
 
1092
1104
  CHECKVALIDITY(server_2char);
1093
1105
  F(argv[1], argv[2]);
1094
1106
  return TCL_OK;
1099
1111
  Function F = (Function) cd;
1100
1112
 
1101
1113
  BADARGS(5, 5, " nick uhost hand buffer");
 
1114
 
1102
1115
  CHECKVALIDITY(server_msg);
1103
1116
  F(argv[1], argv[2], get_user_by_handle(userlist, argv[3]), argv[4]);
1104
1117
  return TCL_OK;
1109
1122
  Function F = (Function) cd;
1110
1123
 
1111
1124
  BADARGS(4, 4, " from code args");
 
1125
 
1112
1126
  CHECKVALIDITY(server_raw);
1113
1127
  Tcl_AppendResult(irp, int_to_base10(F(argv[1], argv[3])), NULL);
1114
1128
  return TCL_OK;
1116
1130
 
1117
1131
/* Read/write normal string variable.
1118
1132
 */
1119
 
static char *nick_change(ClientData cdata, Tcl_Interp *irp, char *name1,
1120
 
                         char *name2, int flags)
 
1133
static char *nick_change(ClientData cdata, Tcl_Interp *irp,
 
1134
                         EGG_CONST char *name1,
 
1135
                         EGG_CONST char *name2, int flags)
1121
1136
{
1122
 
  char *new;
 
1137
  EGG_CONST char *new;
1123
1138
 
1124
1139
  if (flags & (TCL_TRACE_READS | TCL_TRACE_UNSETS)) {
1125
1140
    Tcl_SetVar2(interp, name1, name2, origbotname, TCL_GLOBAL_ONLY);
1126
1141
    if (flags & TCL_TRACE_UNSETS)
1127
1142
      Tcl_TraceVar(irp, name1, TCL_TRACE_READS | TCL_TRACE_WRITES |
1128
 
                   TCL_TRACE_UNSETS, nick_change, cdata);
1129
 
  } else {                      /* writes */
 
1143
                   TCL_TRACE_UNSETS, nick_change, cdata);
 
1144
  } else {                        /* writes */
1130
1145
    new = Tcl_GetVar2(interp, name1, name2, TCL_GLOBAL_ONLY);
1131
 
    if (rfc_casecmp(origbotname, new)) {
 
1146
    if (strcmp(origbotname, (char *) new)) {
1132
1147
      if (origbotname[0]) {
1133
 
        putlog(LOG_MISC, "*", "* IRC NICK CHANGE: %s -> %s",
1134
 
               origbotname, new);
 
1148
        putlog(LOG_MISC, "*", "* IRC NICK CHANGE: %s -> %s", origbotname, new);
1135
1149
        nick_juped = 0;
1136
1150
      }
1137
1151
      strncpyz(origbotname, new, NICKLEN);
1138
1152
      if (server_online)
1139
 
        dprintf(DP_SERVER, "NICK %s\n", origbotname);
 
1153
        dprintf(DP_SERVER, "NICK %s\n", origbotname);
1140
1154
    }
1141
1155
  }
1142
1156
  return NULL;
1149
1163
  register char *p = nick;
1150
1164
 
1151
1165
  while ((p = strchr(p, '?')) != NULL) {
1152
 
    *p = '0' + random() % 10;
 
1166
    *p = '0' + randint(10);
1153
1167
    p++;
1154
1168
  }
1155
1169
}
1169
1183
    return altnick;
1170
1184
}
1171
1185
 
1172
 
static char *altnick_change(ClientData cdata, Tcl_Interp *irp, char *name1,
1173
 
                            char *name2, int flags)
 
1186
static char *altnick_change(ClientData cdata, Tcl_Interp *irp,
 
1187
                            EGG_CONST char *name1,
 
1188
                            EGG_CONST char *name2, int flags)
1174
1189
{
1175
1190
  /* Always unset raltnick. Will be regenerated when needed. */
1176
1191
  raltnick[0] = 0;
1177
1192
  return NULL;
1178
1193
}
1179
1194
 
1180
 
static char *traced_server(ClientData cdata, Tcl_Interp *irp, char *name1,
1181
 
                           char *name2, int flags)
 
1195
static char *traced_serveraddress(ClientData cdata, Tcl_Interp *irp,
 
1196
                                  EGG_CONST char *name1,
 
1197
                                  EGG_CONST char *name2, int flags)
1182
1198
{
1183
1199
  char s[1024];
1184
1200
 
1191
1207
  Tcl_SetVar2(interp, name1, name2, s, TCL_GLOBAL_ONLY);
1192
1208
  if (flags & TCL_TRACE_UNSETS)
1193
1209
    Tcl_TraceVar(irp, name1, TCL_TRACE_READS | TCL_TRACE_WRITES |
1194
 
                 TCL_TRACE_UNSETS, traced_server, cdata);
1195
 
  return NULL;
1196
 
}
1197
 
 
1198
 
static char *traced_botname(ClientData cdata, Tcl_Interp *irp, char *name1,
1199
 
                            char *name2, int flags)
1200
 
{
1201
 
  char s[1024];
1202
 
 
1203
 
  simple_sprintf(s, "%s%s%s", botname, 
1204
 
                 botuserhost[0] ? "!" : "", botuserhost[0] ? botuserhost : "");
1205
 
  Tcl_SetVar2(interp, name1, name2, s, TCL_GLOBAL_ONLY);
1206
 
  if (flags & TCL_TRACE_UNSETS)
1207
 
    Tcl_TraceVar(irp, name1, TCL_TRACE_READS | TCL_TRACE_WRITES |
1208
 
                 TCL_TRACE_UNSETS, traced_botname, cdata);
 
1210
                 TCL_TRACE_UNSETS, traced_serveraddress, cdata);
 
1211
  return NULL;
 
1212
}
 
1213
 
 
1214
static char *traced_server(ClientData cdata, Tcl_Interp *irp,
 
1215
                           EGG_CONST char *name1,
 
1216
                           EGG_CONST char *name2, int flags)
 
1217
{
 
1218
  char s[1024];
 
1219
 
 
1220
  if (server_online && realservername) {
 
1221
    int servidx = findanyidx(serv);
 
1222
 
 
1223
    /* return real server name */
 
1224
    simple_sprintf(s, "%s:%u", realservername, dcc[servidx].port);
 
1225
  } else
 
1226
    s[0] = 0;
 
1227
  Tcl_SetVar2(interp, name1, name2, s, TCL_GLOBAL_ONLY);
 
1228
  if (flags & TCL_TRACE_UNSETS)
 
1229
    Tcl_TraceVar(irp, name1, TCL_TRACE_READS | TCL_TRACE_WRITES |
 
1230
                 TCL_TRACE_UNSETS, traced_server, cdata);
 
1231
  return NULL;
 
1232
}
 
1233
 
 
1234
static char *traced_botname(ClientData cdata, Tcl_Interp *irp,
 
1235
                            EGG_CONST char *name1,
 
1236
                            EGG_CONST char *name2, int flags)
 
1237
{
 
1238
  char s[1024];
 
1239
 
 
1240
  simple_sprintf(s, "%s%s%s", botname,
 
1241
                 botuserhost[0] ? "!" : "", botuserhost[0] ? botuserhost : "");
 
1242
  Tcl_SetVar2(interp, name1, name2, s, TCL_GLOBAL_ONLY);
 
1243
  if (flags & TCL_TRACE_UNSETS)
 
1244
    Tcl_TraceVar(irp, name1, TCL_TRACE_READS | TCL_TRACE_WRITES |
 
1245
                 TCL_TRACE_UNSETS, traced_botname, cdata);
1209
1246
  return NULL;
1210
1247
}
1211
1248
 
1227
1264
  case NETT_UNDERNET:
1228
1265
    check_mode_r = 0;
1229
1266
    use_fastdeq = 2;
1230
 
    nick_len = 9;
1231
 
    simple_sprintf(stackablecmds, "PRIVMSG NOTICE TOPIC PART WHOIS USERHOST USERIP ISON");
 
1267
    nick_len = 12;
 
1268
    simple_sprintf(stackablecmds,
 
1269
                   "PRIVMSG NOTICE TOPIC PART WHOIS USERHOST USERIP ISON");
1232
1270
    simple_sprintf(stackable2cmds, "USERHOST USERIP ISON");
1233
1271
    break;
1234
1272
  case NETT_DALNET:
1235
1273
    check_mode_r = 0;
1236
1274
    use_fastdeq = 2;
1237
1275
    nick_len = 32;
1238
 
    simple_sprintf(stackablecmds, "PRIVMSG NOTICE PART WHOIS WHOWAS USERHOST ISON WATCH DCCALLOW");
 
1276
    simple_sprintf(stackablecmds,
 
1277
                   "PRIVMSG NOTICE PART WHOIS WHOWAS USERHOST ISON WATCH DCCALLOW");
1239
1278
    simple_sprintf(stackable2cmds, "USERHOST ISON WATCH");
1240
1279
    break;
1241
1280
  case NETT_HYBRID_EFNET:
1245
1284
  }
1246
1285
}
1247
1286
 
1248
 
static char *traced_nettype(ClientData cdata, Tcl_Interp *irp, char *name1,
1249
 
                            char *name2, int flags)
 
1287
static char *traced_nettype(ClientData cdata, Tcl_Interp *irp,
 
1288
                            EGG_CONST char *name1,
 
1289
                            EGG_CONST char *name2, int flags)
1250
1290
{
1251
1291
  do_nettype();
1252
1292
  return NULL;
1253
1293
}
1254
1294
 
1255
 
static char *traced_nicklen(ClientData cdata, Tcl_Interp *irp, char *name1,
1256
 
                            char *name2, int flags)
 
1295
static char *traced_nicklen(ClientData cdata, Tcl_Interp *irp,
 
1296
                            EGG_CONST char *name1,
 
1297
                            EGG_CONST char *name2, int flags)
1257
1298
{
1258
1299
  if (flags & (TCL_TRACE_READS | TCL_TRACE_UNSETS)) {
1259
1300
    char s[40];
1262
1303
    Tcl_SetVar2(interp, name1, name2, s, TCL_GLOBAL_ONLY);
1263
1304
    if (flags & TCL_TRACE_UNSETS)
1264
1305
      Tcl_TraceVar(irp, name1, TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1265
 
                   traced_nicklen, cdata);
 
1306
                   traced_nicklen, cdata);
1266
1307
  } else {
1267
 
    char *cval = Tcl_GetVar2(interp, name1, name2, TCL_GLOBAL_ONLY);
 
1308
    EGG_CONST char *cval = Tcl_GetVar2(interp, name1, name2, TCL_GLOBAL_ONLY);
1268
1309
    long lval = 0;
1269
1310
 
1270
1311
    if (cval && Tcl_ExprLong(interp, cval, &lval) != TCL_ERROR) {
1271
1312
      if (lval > NICKMAX)
1272
 
        lval = NICKMAX;
 
1313
        lval = NICKMAX;
1273
1314
      nick_len = (int) lval;
1274
1315
    }
1275
1316
  }
1276
1317
  return NULL;
1277
1318
}
1278
1319
 
1279
 
static tcl_strings my_tcl_strings[] =
1280
 
{
1281
 
  {"botnick",                   NULL,           0,              STR_PROTECT},
1282
 
  {"altnick",                   altnick,        NICKMAX,        0},
1283
 
  {"realname",                  botrealname,    80,             0},
1284
 
  {"init-server",               initserver,     120,            0},
1285
 
  {"connect-server",            connectserver,  120,            0},
1286
 
  {"stackable-commands",        stackablecmds,  510,            0},
1287
 
  {"stackable2-commands",       stackable2cmds, 510,            0},
1288
 
  {NULL,                        NULL,           0,              0}
1289
 
};
1290
 
 
1291
 
static tcl_coups my_tcl_coups[] =
1292
 
{
1293
 
  {"flood-msg",         &flud_thr,              &flud_time},
1294
 
  {"flood-ctcp",        &flud_ctcp_thr,         &flud_ctcp_time},
1295
 
  {NULL,                NULL,                   NULL}
1296
 
};
1297
 
 
1298
 
static tcl_ints my_tcl_ints[] =
1299
 
{
1300
 
  {"use-console-r",             NULL,                           1},
1301
 
  {"servlimit",                 &min_servs,                     0},
1302
 
  {"server-timeout",            &server_timeout,                0},
1303
 
  {"lowercase-ctcp",            &lowercase_ctcp,                0},
1304
 
  {"server-online",             (int *) &server_online,         2},
1305
 
  {"never-give-up",             &never_give_up,                 0},
1306
 
  {"keep-nick",                 &keepnick,                      0},
1307
 
  {"strict-servernames",        &strict_servernames,            0},
1308
 
  {"check-stoned",              &check_stoned,                  0},
1309
 
  {"serverror-quit",            &serverror_quit,                0},
1310
 
  {"quiet-reject",              &quiet_reject,                  0},
1311
 
  {"max-queue-msg",             &maxqmsg,                       0},
1312
 
  {"trigger-on-ignore",         &trigger_on_ignore,             0},
1313
 
  {"answer-ctcp",               &answer_ctcp,                   0},
1314
 
  {"server-cycle-wait",         (int *) &server_cycle_wait,     0},
1315
 
  {"default-port",              &default_port,                  0},
1316
 
  {"check-mode-r",              &check_mode_r,                  0},
1317
 
  {"net-type",                  &net_type,                      0},
1318
 
  {"ctcp-mode",                 &ctcp_mode,                     0},
1319
 
  {"double-mode",               &double_mode,                   0},/* G`Quann */
1320
 
  {"double-server",             &double_server,                 0},
1321
 
  {"double-help",               &double_help,                   0},
1322
 
  {"use-penalties",             &use_penalties,                 0},
1323
 
  {"use-fastdeq",               &use_fastdeq,                   0},
1324
 
  {"nicklen",                   &nick_len,                      0},
1325
 
  {"nick-len",                  &nick_len,                      0},
1326
 
  {"optimize-kicks",            &optimize_kicks,                0},
1327
 
  {"isjuped",                   &nick_juped,                    0},
1328
 
  {NULL,                        NULL,                           0}
 
1320
static tcl_strings my_tcl_strings[] = {
 
1321
  {"botnick",             NULL,           0,       STR_PROTECT},
 
1322
  {"altnick",             altnick,        NICKMAX,           0},
 
1323
  {"realname",            botrealname,    80,                0},
 
1324
  {"init-server",         initserver,     120,               0},
 
1325
  {"connect-server",      connectserver,  120,               0},
 
1326
  {"stackable-commands",  stackablecmds,  510,               0},
 
1327
  {"stackable2-commands", stackable2cmds, 510,               0},
 
1328
  {NULL,                  NULL,           0,                 0}
 
1329
};
 
1330
 
 
1331
static tcl_coups my_tcl_coups[] = {
 
1332
  {"flood-ctcp", &flud_ctcp_thr, &flud_ctcp_time},
 
1333
  {"flood-msg",  &flud_thr,           &flud_time},
 
1334
  {NULL,         NULL,                      NULL}
 
1335
};
 
1336
 
 
1337
static tcl_ints my_tcl_ints[] = {
 
1338
  {"servlimit",         &min_servs,                 0},
 
1339
  {"server-timeout",    &server_timeout,            0},
 
1340
  {"lowercase-ctcp",    &lowercase_ctcp,            0},
 
1341
  {"server-online",     (int *) &server_online,     2},
 
1342
  {"never-give-up",     &never_give_up,             0},
 
1343
  {"keep-nick",         &keepnick,                  0},
 
1344
  {"check-stoned",      &check_stoned,              0},
 
1345
  {"serverror-quit",    &serverror_quit,            0},
 
1346
  {"max-queue-msg",     &maxqmsg,                   0},
 
1347
  {"trigger-on-ignore", &trigger_on_ignore,         0},
 
1348
  {"answer-ctcp",       &answer_ctcp,               0},
 
1349
  {"server-cycle-wait", (int *) &server_cycle_wait, 0},
 
1350
  {"default-port",      &default_port,              0},
 
1351
  {"check-mode-r",      &check_mode_r,              0},
 
1352
  {"net-type",          &net_type,                  0},
 
1353
  {"ctcp-mode",         &ctcp_mode,                 0},
 
1354
  {"double-mode",       &double_mode,               0},
 
1355
  {"double-server",     &double_server,             0},
 
1356
  {"double-help",       &double_help,               0},
 
1357
  {"use-penalties",     &use_penalties,             0},
 
1358
  {"use-fastdeq",       &use_fastdeq,               0},
 
1359
  {"nicklen",           &nick_len,                  0},
 
1360
  {"nick-len",          &nick_len,                  0},
 
1361
  {"optimize-kicks",    &optimize_kicks,            0},
 
1362
  {"isjuped",           &nick_juped,                0},
 
1363
  {"stack-limit",       &stack_limit,               0},
 
1364
  {NULL,                NULL,                       0}
1329
1365
};
1330
1366
 
1331
1367
 
1335
1371
 
1336
1372
/* Read or write the server list.
1337
1373
 */
1338
 
static char *tcl_eggserver(ClientData cdata, Tcl_Interp *irp, char *name1,
1339
 
                           char *name2, int flags)
 
1374
 
 
1375
static char *tcl_eggserver(ClientData cdata, Tcl_Interp *irp,
 
1376
                           EGG_CONST char *name1,
 
1377
                           EGG_CONST char *name2, int flags)
1340
1378
{
 
1379
  int lc, code, i;
 
1380
  char x[1024];
 
1381
  EGG_CONST char **list, *slist;
 
1382
  struct server_list *q;
1341
1383
  Tcl_DString ds;
1342
 
  char *slist, **list, x[1024];
1343
 
  struct server_list *q;
1344
 
  int lc, code, i;
1345
1384
 
1346
1385
  if (flags & (TCL_TRACE_READS | TCL_TRACE_UNSETS)) {
1347
1386
    /* Create server list */
1348
1387
    Tcl_DStringInit(&ds);
1349
1388
    for (q = serverlist; q; q = q->next) {
1350
1389
      egg_snprintf(x, sizeof x, "%s:%d%s%s %s", q->name,
1351
 
                   q->port ? q->port : default_port, q->pass ? ":" : "",
1352
 
                   q->pass ? q->pass : "", q->realname ? q->realname : "");
 
1390
                   q->port ? q->port : default_port, q->pass ? ":" : "",
 
1391
                   q->pass ? q->pass : "", q->realname ? q->realname : "");
1353
1392
      Tcl_DStringAppendElement(&ds, x);
1354
1393
    }
1355
1394
    slist = Tcl_DStringValue(&ds);
1356
1395
    Tcl_SetVar2(interp, name1, name2, slist, TCL_GLOBAL_ONLY);
1357
1396
    Tcl_DStringFree(&ds);
1358
 
  } else {              /* TCL_TRACE_WRITES */
 
1397
  } else {                        /* TCL_TRACE_WRITES */
1359
1398
    if (serverlist) {
1360
1399
      clearq(serverlist);
1361
1400
      serverlist = NULL;
1364
1403
    if (slist != NULL) {
1365
1404
      code = Tcl_SplitList(interp, slist, &lc, &list);
1366
1405
      if (code == TCL_ERROR)
1367
 
        return interp->result;
 
1406
        return interp->result;
1368
1407
      for (i = 0; i < lc && i < 50; i++)
1369
 
        add_server(list[i]);
 
1408
        add_server((char *) list[i]);
1370
1409
 
1371
1410
      /* Tricky way to make the bot reset its server pointers
1372
1411
       * perform part of a '.jump <current-server>':
1373
1412
       */
1374
1413
      if (server_online) {
1375
 
        int servidx = findanyidx(serv);
 
1414
        int servidx = findanyidx(serv);
1376
1415
 
1377
 
        curserv = (-1);
1378
 
        next_server(&curserv, dcc[servidx].host, &dcc[servidx].port, "");
 
1416
        curserv = -1;
 
1417
        next_server(&curserv, dcc[servidx].host, &dcc[servidx].port, "");
1379
1418
      }
1380
1419
      Tcl_Free((char *) list);
1381
1420
    }
1384
1423
}
1385
1424
 
1386
1425
/* Trace the servers */
1387
 
#define tcl_traceserver(name, ptr) \
1388
 
  Tcl_TraceVar(interp, name, TCL_TRACE_READS | TCL_TRACE_WRITES |       \
1389
 
               TCL_TRACE_UNSETS, tcl_eggserver, (ClientData) ptr)
 
1426
#define tcl_traceserver(name, ptr)                                      \
 
1427
  Tcl_TraceVar(interp, name, TCL_TRACE_READS | TCL_TRACE_WRITES |       \
 
1428
               TCL_TRACE_UNSETS, tcl_eggserver, (ClientData) ptr)
1390
1429
 
1391
 
#define tcl_untraceserver(name, ptr) \
1392
 
  Tcl_UntraceVar(interp, name, TCL_TRACE_READS | TCL_TRACE_WRITES |     \
1393
 
                 TCL_TRACE_UNSETS, tcl_eggserver, (ClientData) ptr)
 
1430
#define tcl_untraceserver(name, ptr)                                    \
 
1431
  Tcl_UntraceVar(interp, name, TCL_TRACE_READS | TCL_TRACE_WRITES |     \
 
1432
                 TCL_TRACE_UNSETS, tcl_eggserver, (ClientData) ptr)
1394
1433
 
1395
1434
 
1396
1435
/*
1402
1441
/* This only handles CHAT requests, otherwise it's handled in filesys.
1403
1442
 */
1404
1443
static int ctcp_DCC_CHAT(char *nick, char *from, char *handle,
1405
 
                         char *object, char *keyword, char *text)
 
1444
                         char *object, char *keyword, char *text)
1406
1445
{
1407
1446
  char *action, *param, *ip, *prt, buf[512], *msg = buf;
1408
1447
  int i;
1409
1448
  struct userrec *u = get_user_by_handle(userlist, handle);
1410
 
  struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
 
1449
  struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1411
1450
 
1412
1451
  strcpy(msg, text);
1413
1452
  action = newsplit(&msg);
1423
1462
    putlog(LOG_MISC, "*", DCC_TOOMANYDCCS2, "CHAT", param, nick, from);
1424
1463
  } else if (!(glob_party(fr) || (!require_p && chan_op(fr)))) {
1425
1464
    if (glob_xfer(fr))
1426
 
      return 0;                 /* Allow filesys to pick up the chat */
 
1465
      return 0;                 /* Allow filesys to pick up the chat */
1427
1466
    if (!quiet_reject)
1428
1467
      dprintf(DP_HELP, "NOTICE %s :%s\n", nick, DCC_REFUSED2);
1429
1468
    putlog(LOG_MISC, "*", "%s: %s!%s", DCC_REFUSED, nick, from);
1435
1474
    /* Invalid port */
1436
1475
    if (!quiet_reject)
1437
1476
      dprintf(DP_HELP, "NOTICE %s :%s (invalid port)\n", nick,
1438
 
              DCC_CONNECTFAILED1);
1439
 
    putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED3,
1440
 
           nick, from);
 
1477
              DCC_CONNECTFAILED1);
 
1478
    putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED3, nick, from);
1441
1479
  } else {
1442
1480
    if (!sanitycheck_dcc(nick, from, ip, prt))
1443
1481
      return 1;
1453
1491
    strcpy(dcc[i].host, from);
1454
1492
    dcc[i].timeval = now;
1455
1493
    dcc[i].user = u;
 
1494
    dcc[i].addr = my_atoul(ip);
1456
1495
    dcc[i].u.dns->ip = dcc[i].addr;
1457
1496
    dcc[i].u.dns->dns_type = RES_HOSTBYIP;
1458
1497
    dcc[i].u.dns->dns_success = dcc_chat_hostresolved;
1466
1505
static void dcc_chat_hostresolved(int i)
1467
1506
{
1468
1507
  char buf[512], ip[512];
1469
 
  struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
 
1508
  struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1470
1509
 
1471
1510
  egg_snprintf(buf, sizeof buf, "%d", dcc[i].port);
1472
1511
  if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].host, dcc[i].addr,
1473
 
                           dcc[i].u.dns->host, buf)) {
 
1512
                           dcc[i].u.dns->host, buf)) {
1474
1513
    lostdcc(i);
1475
1514
    return;
1476
1515
  }
1478
1517
  dcc[i].sock = getsock(0);
1479
1518
  if (dcc[i].sock < 0 || open_telnet_dcc(dcc[i].sock, ip, buf) < 0) {
1480
1519
    neterror(buf);
1481
 
    if(!quiet_reject)
 
1520
    if (!quiet_reject)
1482
1521
      dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[i].nick,
1483
 
              DCC_CONNECTFAILED1, buf);
 
1522
              DCC_CONNECTFAILED1, buf);
1484
1523
    putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED2,
1485
 
           dcc[i].nick, dcc[i].host);
 
1524
           dcc[i].nick, dcc[i].host);
1486
1525
    putlog(LOG_MISC, "*", "    (%s)", buf);
1487
1526
    killsock(dcc[i].sock);
1488
1527
    lostdcc(i);
1496
1535
    dcc[i].timeval = now;
1497
1536
    /* Ok, we're satisfied with them now: attempt the connect */
1498
1537
    putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick,
1499
 
           dcc[i].host);
 
1538
           dcc[i].host);
1500
1539
    dprintf(i, "%s\n", DCC_ENTERPASS);
1501
1540
  }
1502
1541
  return;
1518
1557
 
1519
1558
static void server_5minutely()
1520
1559
{
1521
 
  if (check_stoned) {
 
1560
  if (check_stoned && server_online) {
1522
1561
    if (waiting_for_awake) {
1523
1562
      /* Uh oh!  Never got pong from last time, five minutes ago!
1524
1563
       * Server is probably stoned.
1548
1587
    fatal("NO BOT NAME.", 0);
1549
1588
  if (serverlist == NULL)
1550
1589
    fatal("NO SERVER.", 0);
1551
 
    if (oldnick[0] && !rfc_casecmp(oldnick, botname)
1552
 
       && !rfc_casecmp(oldnick, get_altbotnick())) {
 
1590
  if (oldnick[0] && !rfc_casecmp(oldnick, botname) &&
 
1591
      !rfc_casecmp(oldnick, get_altbotnick())) {
1553
1592
    /* Change botname back, don't be premature. */
1554
1593
    strcpy(botname, oldnick);
1555
1594
    dprintf(DP_SERVER, "NICK %s\n", origbotname);
1557
1596
  /* Change botname back incase we were using altnick previous to rehash. */
1558
1597
  else if (oldnick[0])
1559
1598
    strcpy(botname, oldnick);
1560
 
  if (initserver[0])
1561
 
    do_tcl("init-server", initserver);
1562
1599
}
1563
1600
 
1564
1601
static void server_die()
1566
1603
  cycle_time = 100;
1567
1604
  if (server_online) {
1568
1605
    dprintf(-serv, "QUIT :%s\n", quit_msg[0] ? quit_msg : "");
1569
 
    sleep(3); /* Give the server time to understand */
 
1606
    sleep(3);                   /* Give the server time to understand */
1570
1607
  }
1571
1608
  nuke_server(NULL);
1572
1609
}
1573
1610
 
1574
 
/* A report on the module status.
1575
 
 */
 
1611
 
 
1612
static void msgq_clear(struct msgq_head *qh)
 
1613
{
 
1614
  register struct msgq *q, *qq;
 
1615
 
 
1616
  for (q = qh->head; q; q = qq) {
 
1617
    qq = q->next;
 
1618
    nfree(q->msg);
 
1619
    nfree(q);
 
1620
  }
 
1621
  qh->head = qh->last = NULL;
 
1622
  qh->tot = qh->warned = 0;
 
1623
}
 
1624
 
 
1625
static int msgq_expmem(struct msgq_head *qh)
 
1626
{
 
1627
  register int tot = 0;
 
1628
  register struct msgq *m;
 
1629
 
 
1630
  for (m = qh->head; m; m = m->next) {
 
1631
    tot += m->len + 1;
 
1632
    tot += sizeof(struct msgq);
 
1633
  }
 
1634
  return tot;
 
1635
}
 
1636
 
 
1637
static int server_expmem()
 
1638
{
 
1639
  int tot = 0;
 
1640
  struct server_list *s = serverlist;
 
1641
 
 
1642
  for (; s; s = s->next) {
 
1643
    if (s->name)
 
1644
      tot += strlen(s->name) + 1;
 
1645
    if (s->pass)
 
1646
      tot += strlen(s->pass) + 1;
 
1647
    if (s->realname)
 
1648
      tot += strlen(s->realname) + 1;
 
1649
    tot += sizeof(struct server_list);
 
1650
  }
 
1651
 
 
1652
  if (realservername)
 
1653
    tot += strlen(realservername) + 1;
 
1654
  tot += msgq_expmem(&mq) + msgq_expmem(&hq) + msgq_expmem(&modeq);
 
1655
 
 
1656
  return tot;
 
1657
}
 
1658
 
1576
1659
static void server_report(int idx, int details)
1577
1660
{
1578
1661
  char s1[64], s[128];
1579
1662
  int servidx;
1580
1663
 
1581
1664
  if (server_online) {
1582
 
    dprintf(idx, "    Online as: %s%s%s (%s)\n", botname,
1583
 
            botuserhost[0] ? "!" : "", botuserhost[0] ? botuserhost : "",
1584
 
            botrealname);
 
1665
    dprintf(idx, "    Online as: %s%s%s (%s)\n", botname, botuserhost[0] ?
 
1666
            "!" : "", botuserhost[0] ? botuserhost : "", botrealname);
1585
1667
    if (nick_juped)
1586
 
      dprintf(idx, "    NICK IS JUPED: %s %s\n", origbotname,
1587
 
              keepnick ? "(trying)" : "");
1588
 
    nick_juped = 0; /* WHY?? -- drummer */
 
1668
      dprintf(idx, "    NICK IS JUPED: %s%s\n", origbotname,
 
1669
              keepnick ? " (trying)" : "");
1589
1670
    daysdur(now, server_online, s1);
1590
1671
    egg_snprintf(s, sizeof s, "(connected %s)", s1);
1591
1672
    if (server_lag && !waiting_for_awake) {
1592
 
      if (server_lag == (-1))
1593
 
        egg_snprintf(s1, sizeof s1, " (bad pong replies)");
 
1673
      if (server_lag == -1)
 
1674
        egg_snprintf(s1, sizeof s1, " (bad pong replies)");
1594
1675
      else
1595
 
        egg_snprintf(s1, sizeof s1, " (lag: %ds)", server_lag);
 
1676
        egg_snprintf(s1, sizeof s1, " (lag: %ds)", server_lag);
1596
1677
      strcat(s, s1);
1597
1678
    }
1598
1679
  }
 
1680
 
1599
1681
  if ((trying_server || server_online) &&
1600
 
        ((servidx = findanyidx(serv)) != (-1))) {
 
1682
      ((servidx = findanyidx(serv)) != -1)) {
1601
1683
    dprintf(idx, "    Server %s:%d %s\n", dcc[servidx].host, dcc[servidx].port,
1602
 
            trying_server ? "(trying)" : s);
 
1684
            trying_server ? "(trying)" : s);
1603
1685
  } else
1604
1686
    dprintf(idx, "    %s\n", IRC_NOSERVER);
 
1687
 
1605
1688
  if (modeq.tot)
1606
 
    dprintf(idx, "    %s %d%%, %d msgs\n", IRC_MODEQUEUE,
 
1689
    dprintf(idx, "    %s %d%% (%d msgs)\n", IRC_MODEQUEUE,
1607
1690
            (int) ((float) (modeq.tot * 100.0) / (float) maxqmsg),
1608
 
            (int) modeq.tot);
 
1691
            (int) modeq.tot);
1609
1692
  if (mq.tot)
1610
 
    dprintf(idx, "    %s %d%%, %d msgs\n", IRC_SERVERQUEUE,
1611
 
           (int) ((float) (mq.tot * 100.0) / (float) maxqmsg), (int) mq.tot);
 
1693
    dprintf(idx, "    %s %d%% (%d msgs)\n", IRC_SERVERQUEUE,
 
1694
            (int) ((float) (mq.tot * 100.0) / (float) maxqmsg), (int) mq.tot);
1612
1695
  if (hq.tot)
1613
 
    dprintf(idx, "    %s %d%%, %d msgs\n", IRC_HELPQUEUE,
1614
 
           (int) ((float) (hq.tot * 100.0) / (float) maxqmsg), (int) hq.tot);
 
1696
    dprintf(idx, "    %s %d%% (%d msgs)\n", IRC_HELPQUEUE,
 
1697
            (int) ((float) (hq.tot * 100.0) / (float) maxqmsg), (int) hq.tot);
 
1698
 
1615
1699
  if (details) {
 
1700
    int size = server_expmem();
 
1701
 
1616
1702
    if (min_servs)
1617
 
      dprintf(idx, "    Requiring a net of at least %d server(s)\n", min_servs);
 
1703
      dprintf(idx, "    Requiring a network with at least %d server%s\n",
 
1704
              min_servs, (min_servs != 1) ? "s" : "");
1618
1705
    if (initserver[0])
1619
1706
      dprintf(idx, "    On connect, I do: %s\n", initserver);
1620
1707
    if (connectserver[0])
1621
1708
      dprintf(idx, "    Before connect, I do: %s\n", connectserver);
1622
 
    dprintf(idx, "    Flood is: %d msg/%ds, %d ctcp/%ds\n",
1623
 
            flud_thr, flud_time, flud_ctcp_thr, flud_ctcp_time);
1624
 
  }
1625
 
}
1626
 
 
1627
 
static void msgq_clear(struct msgq_head *qh)
1628
 
{
1629
 
  register struct msgq  *q, *qq;
1630
 
 
1631
 
  for (q = qh->head; q; q = qq) {
1632
 
    qq = q->next;
1633
 
    nfree(q->msg);
1634
 
    nfree(q);
1635
 
  }
1636
 
  qh->head = qh->last = NULL;
1637
 
  qh->tot = qh->warned = 0;
1638
 
}
1639
 
 
1640
 
static int msgq_expmem(struct msgq_head *qh)
1641
 
{
1642
 
  register int           tot = 0;
1643
 
  register struct msgq  *m;
1644
 
 
1645
 
  for (m = qh->head; m; m = m->next) {
1646
 
    tot += m->len + 1;
1647
 
    tot += sizeof(struct msgq);
1648
 
  }
1649
 
  return tot;
1650
 
}
1651
 
 
1652
 
static int server_expmem()
1653
 
{
1654
 
  int                    tot = 0;
1655
 
  struct server_list    *s = serverlist;
1656
 
 
1657
 
  for (; s; s = s->next) {
1658
 
    if (s->name)
1659
 
      tot += strlen(s->name) + 1;
1660
 
    if (s->pass)
1661
 
      tot += strlen(s->pass) + 1;
1662
 
    if (s->realname)
1663
 
      tot += strlen(s->realname) + 1;
1664
 
    tot += sizeof(struct server_list);
1665
 
  }
1666
 
 
1667
 
  tot += msgq_expmem(&mq) + msgq_expmem(&hq) + msgq_expmem(&modeq);
1668
 
 
1669
 
  return tot;
1670
 
}
1671
 
 
1672
 
static cmd_t my_ctcps[] =
1673
 
{
1674
 
  {"DCC",       "",     ctcp_DCC_CHAT,          "server:DCC"},
1675
 
  {NULL,        NULL,   NULL,                   NULL}
 
1709
    dprintf(idx, "    Msg flood: %d msg%s/%d second%s\n", flud_thr,
 
1710
            (flud_thr != 1) ? "s" : "", flud_time,
 
1711
            (flud_time != 1) ? "s" : "");
 
1712
    dprintf(idx, "    CTCP flood: %d msg%s/%d second%s\n", flud_ctcp_thr,
 
1713
            (flud_ctcp_thr != 1) ? "s" : "", flud_ctcp_time,
 
1714
            (flud_ctcp_time != 1) ? "s" : "");
 
1715
    dprintf(idx, "    Using %d byte%s of memory\n", size,
 
1716
            (size != 1) ? "s" : "");
 
1717
  }
 
1718
}
 
1719
 
 
1720
static cmd_t my_ctcps[] = {
 
1721
  {"DCC", "",   ctcp_DCC_CHAT, "server:DCC"},
 
1722
  {NULL,  NULL, NULL,                  NULL}
1676
1723
};
1677
1724
 
1678
1725
static char *server_close()
1698
1745
  rem_help_reference("server.help");
1699
1746
  rem_tcl_commands(my_tcl_cmds);
1700
1747
  Tcl_UntraceVar(interp, "nick",
1701
 
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1702
 
                 nick_change, NULL);
 
1748
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1749
                 nick_change, NULL);
1703
1750
  Tcl_UntraceVar(interp, "altnick",
1704
 
                 TCL_TRACE_WRITES | TCL_TRACE_UNSETS, altnick_change, NULL);
 
1751
                 TCL_TRACE_WRITES | TCL_TRACE_UNSETS, altnick_change, NULL);
1705
1752
  Tcl_UntraceVar(interp, "botname",
1706
 
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1707
 
                 traced_botname, NULL);
 
1753
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1754
                 traced_botname, NULL);
1708
1755
  Tcl_UntraceVar(interp, "server",
1709
 
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1710
 
                 traced_server, NULL);
 
1756
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1757
                 traced_server, NULL);
 
1758
  Tcl_UntraceVar(interp, "serveraddress",
 
1759
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1760
                 traced_serveraddress, NULL);
1711
1761
  Tcl_UntraceVar(interp, "net-type",
1712
 
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1713
 
                 traced_nettype, NULL);
 
1762
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1763
                 traced_nettype, NULL);
1714
1764
  Tcl_UntraceVar(interp, "nick-len",
1715
 
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1716
 
                 traced_nicklen, NULL);
 
1765
                 TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1766
                 traced_nicklen, NULL);
1717
1767
  tcl_untraceserver("servers", NULL);
1718
1768
  empty_msgq();
1719
1769
  del_hook(HOOK_SECONDLY, (Function) server_secondly);
1729
1779
 
1730
1780
EXPORT_SCOPE char *server_start();
1731
1781
 
1732
 
static Function server_table[] =
1733
 
{
 
1782
static Function server_table[] = {
1734
1783
  (Function) server_start,
1735
1784
  (Function) server_close,
1736
1785
  (Function) server_expmem,
1737
1786
  (Function) server_report,
1738
1787
  /* 4 - 7 */
1739
 
  (Function) NULL,              /* char * (points to botname later on)  */
1740
 
  (Function) botuserhost,       /* char *                               */
1741
 
  (Function) & quiet_reject,    /* int                                  */
1742
 
  (Function) & serv,            /* int                                  */
 
1788
  (Function) NULL,              /* char * (points to botname later on)  */
 
1789
  (Function) botuserhost,       /* char *                               */
 
1790
  (Function) NULL,              /* Was quiet_reject <Wcc[01/21/03]>.    */
 
1791
  (Function) & serv,            /* int                                  */
1743
1792
  /* 8 - 11 */
1744
 
  (Function) & flud_thr,        /* int                                  */
1745
 
  (Function) & flud_time,       /* int                                  */
1746
 
  (Function) & flud_ctcp_thr,   /* int                                  */
1747
 
  (Function) & flud_ctcp_time,  /* int                                  */
 
1793
  (Function) & flud_thr,        /* int                                  */
 
1794
  (Function) & flud_time,       /* int                                  */
 
1795
  (Function) & flud_ctcp_thr,   /* int                                  */
 
1796
  (Function) & flud_ctcp_time,  /* int                                  */
1748
1797
  /* 12 - 15 */
1749
1798
  (Function) match_my_nick,
1750
1799
  (Function) check_tcl_flud,
1751
 
  (Function) NULL,              /* fixfrom - moved to the core (drummer) */
1752
 
  (Function) & answer_ctcp,     /* int                                  */
 
1800
  (Function) NULL,              /* fixfrom - moved to core (drummer)    */
 
1801
  (Function) & answer_ctcp,     /* int                                  */
1753
1802
  /* 16 - 19 */
1754
 
  (Function) & trigger_on_ignore, /* int                                */
 
1803
  (Function) & trigger_on_ignore, /* int                                */
1755
1804
  (Function) check_tcl_ctcpr,
1756
1805
  (Function) detect_avalanche,
1757
1806
  (Function) nuke_server,
1758
1807
  /* 20 - 23 */
1759
 
  (Function) newserver,         /* char *                               */
1760
 
  (Function) & newserverport,   /* int                                  */
1761
 
  (Function) newserverpass,     /* char *                               */
 
1808
  (Function) newserver,         /* char *                               */
 
1809
  (Function) & newserverport,   /* int                                  */
 
1810
  (Function) newserverpass,     /* char *                               */
 
1811
  (Function) & cycle_time,      /* int                                  */
1762
1812
  /* 24 - 27 */
1763
 
  (Function) & cycle_time,      /* int                                  */
1764
 
  (Function) & default_port,    /* int                                  */
1765
 
  (Function) & server_online,   /* int                                  */
1766
 
  (Function) & min_servs,       /* int                                  */
 
1813
  (Function) & default_port,    /* int                                  */
 
1814
  (Function) & server_online,   /* int                                  */
 
1815
  (Function) & min_servs,       /* int                                  */
 
1816
  (Function) & H_raw,           /* p_tcl_bind_list                      */
1767
1817
  /* 28 - 31 */
1768
 
  (Function) & H_raw,           /* p_tcl_bind_list                      */
1769
 
  (Function) & H_wall,          /* p_tcl_bind_list                      */
1770
 
  (Function) & H_msg,           /* p_tcl_bind_list                      */
1771
 
  (Function) & H_msgm,          /* p_tcl_bind_list                      */
 
1818
  (Function) & H_wall,          /* p_tcl_bind_list                      */
 
1819
  (Function) & H_msg,           /* p_tcl_bind_list                      */
 
1820
  (Function) & H_msgm,          /* p_tcl_bind_list                      */
 
1821
  (Function) & H_notc,          /* p_tcl_bind_list                      */
1772
1822
  /* 32 - 35 */
1773
 
  (Function) & H_notc,          /* p_tcl_bind_list                      */
1774
 
  (Function) & H_flud,          /* p_tcl_bind_list                      */
1775
 
  (Function) & H_ctcp,          /* p_tcl_bind_list                      */
1776
 
  (Function) & H_ctcr,          /* p_tcl_bind_list                      */
1777
 
  /* 36 - 39 */
 
1823
  (Function) & H_flud,          /* p_tcl_bind_list                      */
 
1824
  (Function) & H_ctcp,          /* p_tcl_bind_list                      */
 
1825
  (Function) & H_ctcr,          /* p_tcl_bind_list                      */
1778
1826
  (Function) ctcp_reply,
1779
 
  (Function) get_altbotnick,    /* char *                               */
1780
 
  (Function) & nick_len,        /* int                                  */
 
1827
  /* 36 - 38 */
 
1828
  (Function) get_altbotnick,    /* char *                               */
 
1829
  (Function) & nick_len,        /* int                                  */
1781
1830
  (Function) check_tcl_notc
1782
1831
};
1783
1832
 
1784
1833
char *server_start(Function *global_funcs)
1785
1834
{
1786
 
  char *s;
 
1835
  EGG_CONST char *s;
1787
1836
 
1788
1837
  global = global_funcs;
1789
1838
 
1792
1841
   * globally.
1793
1842
   */
1794
1843
  serv = -1;
1795
 
  strict_host = 1;
1796
1844
  botname[0] = 0;
1797
1845
  trying_server = 0L;
1798
1846
  server_lag = 0;
1804
1852
  flud_ctcp_thr = 3;
1805
1853
  flud_ctcp_time = 60;
1806
1854
  initserver[0] = 0;
1807
 
  connectserver[0] = 0;         /* drummer */
 
1855
  connectserver[0] = 0;         /* drummer */
1808
1856
  botuserhost[0] = 0;
1809
1857
  keepnick = 1;
1810
1858
  check_stoned = 1;
1811
1859
  serverror_quit = 1;
1812
 
  quiet_reject = 1;
1813
1860
  waiting_for_awake = 0;
1814
1861
  server_online = 0;
1815
1862
  server_cycle_wait = 60;
1817
1864
  min_servs = 0;
1818
1865
  server_timeout = 60;
1819
1866
  never_give_up = 0;
1820
 
  strict_servernames = 0;
1821
1867
  serverlist = NULL;
1822
1868
  cycle_time = 0;
1823
1869
  default_port = 6667;
1842
1888
  nick_len = 9;
1843
1889
  kick_method = 1;
1844
1890
  optimize_kicks = 0;
 
1891
  stack_limit = 4;
 
1892
  realservername = 0;
1845
1893
 
1846
1894
  server_table[4] = (Function) botname;
1847
1895
  module_register(MODULE_NAME, server_table, 1, 2);
1848
1896
  if (!module_depend(MODULE_NAME, "eggdrop", 106, 7)) {
1849
1897
    module_undepend(MODULE_NAME);
1850
 
    return "This module requires eggdrop1.6.7 or later";
 
1898
    return "This module requires Eggdrop 1.6.7 or later.";
1851
1899
  }
1852
1900
 
1853
1901
  /* Fool bot in reading the values. */
1857
1905
  if (s)
1858
1906
    strncpyz(origbotname, s, NICKLEN);
1859
1907
  Tcl_TraceVar(interp, "nick",
1860
 
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1861
 
               nick_change, NULL);
 
1908
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1909
               nick_change, NULL);
1862
1910
  Tcl_TraceVar(interp, "altnick",
1863
 
               TCL_TRACE_WRITES | TCL_TRACE_UNSETS, altnick_change, NULL);
 
1911
               TCL_TRACE_WRITES | TCL_TRACE_UNSETS, altnick_change, NULL);
1864
1912
  Tcl_TraceVar(interp, "botname",
1865
 
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1866
 
               traced_botname, NULL);
 
1913
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1914
               traced_botname, NULL);
1867
1915
  Tcl_TraceVar(interp, "server",
1868
 
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1869
 
               traced_server, NULL);
 
1916
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1917
               traced_server, NULL);
 
1918
  Tcl_TraceVar(interp, "serveraddress",
 
1919
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1920
               traced_serveraddress, NULL);
1870
1921
  Tcl_TraceVar(interp, "net-type",
1871
 
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1872
 
               traced_nettype, NULL);
 
1922
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1923
               traced_nettype, NULL);
1873
1924
  Tcl_TraceVar(interp, "nick-len",
1874
 
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
1875
 
               traced_nicklen, NULL);
 
1925
               TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
 
1926
               traced_nicklen, NULL);
1876
1927
 
1877
1928
  H_wall = add_bind_table("wall", HT_STACKABLE, server_2char);
1878
1929
  H_raw = add_bind_table("raw", HT_STACKABLE, server_raw);
1879
 
  H_notc = add_bind_table("notc", HT_STACKABLE, server_6char);
 
1930
  H_notc = add_bind_table("notc", HT_STACKABLE, server_5char);
1880
1931
  H_msgm = add_bind_table("msgm", HT_STACKABLE, server_msg);
1881
1932
  H_msg = add_bind_table("msg", 0, server_msg);
1882
1933
  H_flud = add_bind_table("flud", HT_STACKABLE, server_5char);
1888
1939
  add_help_reference("server.help");
1889
1940
  my_tcl_strings[0].buf = botname;
1890
1941
  add_tcl_strings(my_tcl_strings);
1891
 
  my_tcl_ints[0].val = &use_console_r;
1892
1942
  add_tcl_ints(my_tcl_ints);
1893
1943
  add_tcl_commands(my_tcl_cmds);
1894
1944
  add_tcl_coups(my_tcl_coups);