1 diff -r a662d02e9a76 include/handlers.h
2 --- a/include/handlers.h Sat Jan 24 21:39:56 2009 +0100
3 +++ b/include/handlers.h Sat Jan 24 22:38:10 2009 +0100
5 extern int m_version(struct Client*, struct Client*, int, char*[]);
6 extern int m_wallchops(struct Client*, struct Client*, int, char*[]);
7 extern int m_wallvoices(struct Client*, struct Client*, int, char*[]);
8 +extern int m_welcome(struct Client*, struct Client*, int, char*[]);
9 extern int m_who(struct Client*, struct Client*, int, char*[]);
10 extern int m_whois(struct Client*, struct Client*, int, char*[]);
11 extern int m_whowas(struct Client*, struct Client*, int, char*[]);
13 extern int mo_version(struct Client*, struct Client*, int, char*[]);
14 extern int mo_wallops(struct Client*, struct Client*, int, char*[]);
15 extern int mo_wallusers(struct Client*, struct Client*, int, char*[]);
16 +extern int mo_welcome(struct Client*, struct Client*, int, char*[]);
17 extern int mr_error(struct Client*, struct Client*, int, char*[]);
18 extern int mr_error(struct Client*, struct Client*, int, char*[]);
19 extern int mr_pong(struct Client*, struct Client*, int, char*[]);
21 extern int ms_wallops(struct Client*, struct Client*, int, char*[]);
22 extern int ms_wallusers(struct Client*, struct Client*, int, char*[]);
23 extern int ms_wallvoices(struct Client*, struct Client*, int, char*[]);
24 +extern int ms_welcome(struct Client*, struct Client*, int, char*[]);
25 extern int ms_whois(struct Client*, struct Client*, int, char*[]);
27 #endif /* INCLUDED_handlers_h */
28 diff -r a662d02e9a76 include/msg.h
29 --- a/include/msg.h Sat Jan 24 21:39:56 2009 +0100
30 +++ b/include/msg.h Sat Jan 24 22:38:10 2009 +0100
32 #define MSG_NOTICE "NOTICE" /* NOTI */
33 #define TOK_NOTICE "O"
34 #define CMD_NOTICE MSG_NOTICE, TOK_NOTICE
36 +#define MSG_WELCOME "WELCOME" /* WELC */
37 +#define TOK_WELCOME "WE"
38 +#define CMD_WELCOME MSG_WELCOME, TOK_WELCOME
40 #define MSG_WALLCHOPS "WALLCHOPS" /* WC */
41 #define TOK_WALLCHOPS "WC"
42 diff -r a662d02e9a76 include/welcome.h
43 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44 +++ b/include/welcome.h Sat Jan 24 22:38:10 2009 +0100
46 +#ifndef INCLUDED_welcome_h
47 +#define INCLUDED_welcome_h
49 + * IRC - Internet Relay Chat, include/welcome.h
50 + * Copyright (C) 1990 Jarkko Oikarinen and
51 + * University of Oulu, Computing Center
52 + * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
54 + * This program is free software; you can redistribute it and/or modify
55 + * it under the terms of the GNU General Public License as published by
56 + * the Free Software Foundation; either version 2, or (at your option)
57 + * any later version.
59 + * This program is distributed in the hope that it will be useful,
60 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
61 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62 + * GNU General Public License for more details.
64 + * You should have received a copy of the GNU General Public License
65 + * along with this program; if not, write to the Free Software
66 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
69 + * @brief Interface and declarations for welcome server handling.
70 + * @version $Id: jupe.h 1208 2004-10-03 14:12:35Z entrope $
72 +#ifndef INCLUDED_sys_types_h
73 +#include <sys/types.h>
74 +#define INCLUDED_sys_types_h
81 +extern int welcome_set(struct Client *cptr, struct Client *sptr,
82 + char *reason, time_t lastmod);
83 +extern void welcome_burst(struct Client *cptr);
84 +extern int welcome_resend(struct Client *cptr);
85 +extern int welcome_list(struct Client *sptr);
86 +extern int welcome_memory_count(size_t *ju_size);
88 +#endif /* INCLUDED_welcome_h */
89 \ No newline at end of file
90 diff -r a662d02e9a76 ircd/m_welcome.c
91 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92 +++ b/ircd/m_welcome.c Sat Jan 24 22:38:10 2009 +0100
95 + * IRC - Internet Relay Chat, ircd/m_welcome.c
96 + * Copyright (C) 1990 Jarkko Oikarinen and
97 + * University of Oulu, Computing Center
99 + * See file AUTHORS in IRC package for additional names of
102 + * This program is free software; you can redistribute it and/or modify
103 + * it under the terms of the GNU General Public License as published by
104 + * the Free Software Foundation; either version 1, or (at your option)
105 + * any later version.
107 + * This program is distributed in the hope that it will be useful,
108 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
109 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
110 + * GNU General Public License for more details.
112 + * You should have received a copy of the GNU General Public License
113 + * along with this program; if not, write to the Free Software
114 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
116 + * $Id: m_welcome.c 1903 2009-01-13 03:54:45Z entrope $
120 + * m_functions execute protocol messages on this server:
122 + * cptr is always NON-NULL, pointing to a *LOCAL* client
123 + * structure (with an open socket connected!). This
124 + * identifies the physical socket where the message
125 + * originated (or which caused the m_function to be
126 + * executed--some m_functions may call others...).
128 + * sptr is the source of the message, defined by the
129 + * prefix part of the message if present. If not
130 + * or prefix not found, then sptr==cptr.
132 + * (!IsServer(cptr)) => (cptr == sptr), because
133 + * prefixes are taken *only* from servers...
136 + * (sptr == cptr) => the message didn't
139 + * (sptr != cptr && IsServer(sptr) means
140 + * the prefix specified servername. (?)
142 + * (sptr != cptr && !IsServer(sptr) means
143 + * that message originated from a remote
144 + * user (not local).
148 + * (!IsServer(sptr)) means that, sptr can safely
149 + * taken as defining the target structure of the
150 + * message in this server.
152 + * *Always* true (if 'parse' and others are working correct):
154 + * 1) sptr->from == cptr (note: cptr->from == cptr)
156 + * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
157 + * *cannot* be a local connection, unless it's
158 + * actually cptr!). [MyConnect(x) should probably
159 + * be defined as (x == x->from) --msa ]
161 + * parc number of variable parameter strings (if zero,
162 + * parv is allowed to be NULL)
164 + * parv a NULL terminated list of parameter pointers,
166 + * parv[0], sender (prefix string), if not present
167 + * this points to an empty string.
168 + * parv[1]...parv[parc-1]
169 + * pointers to additional parameters
170 + * parv[parc] == NULL, *always*
172 + * note: it is guaranteed that parv[0]..parv[parc-1] are all
173 + * non-NULL pointers.
177 +#include "channel.h"
181 +#include "ircd_log.h"
182 +#include "ircd_reply.h"
183 +#include "ircd_string.h"
185 +#include "numeric.h"
186 +#include "numnicks.h"
190 +/* #include <assert.h> -- Now using assert in ircd_log.h */
193 + * m_welcome - local generic message handler
195 + * parv[0] = Send prefix
197 +int m_welcome(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
204 + * mo_welcome - oper message handler
207 + * parv[0] = Send prefix
210 + * parv[0] = Send prefix
213 + * set global or on remote server:
214 + * parv[0] = Send prefix
215 + * parv[1] = Target: server or * for global
218 +int mo_welcome(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
225 + * ms_welcome - server message handler
227 + * parv[0] = Send prefix
228 + * parv[1] = Target: server numeric or * for global
229 + * parv[2] = Timestamp
232 +int ms_welcome(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
236 diff -r a662d02e9a76 ircd/parse.c
237 --- a/ircd/parse.c Sat Jan 24 21:39:56 2009 +0100
238 +++ b/ircd/parse.c Sat Jan 24 22:38:10 2009 +0100
240 /* UNREG, CLIENT, SERVER, OPER, SERVICE */
241 { m_unregistered, m_not_oper, ms_opkick, mo_opkick, m_ignore }
244 + /* add command for WELCOME */
248 + 0, MAXPARA, MFLG_SLOW, 0, NULL,
249 + /* UNREG, CLIENT, SERVER, OPER, SERVICE */
250 + { m_unregistered, m_welcome, ms_welcome, mo_welcome, m_ignore }
253 /* This command is an alias for QUIT during the unregistered part of
254 * of the server. This is because someone jumping via a broken web
255 diff -r a662d02e9a76 ircd/welcome.c
256 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
257 +++ b/ircd/welcome.c Sat Jan 24 22:38:10 2009 +0100
260 + * IRC - Internet Relay Chat, ircd/jupe.c
261 + * Copyright (C) 1990 Jarkko Oikarinen and
262 + * University of Oulu, Finland
263 + * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
265 + * This program is free software; you can redistribute it and/or modify
266 + * it under the terms of the GNU General Public License as published by
267 + * the Free Software Foundation; either version 1, or (at your option)
268 + * any later version.
270 + * This program is distributed in the hope that it will be useful,
271 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
272 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
273 + * GNU General Public License for more details.
275 + * You should have received a copy of the GNU General Public License
276 + * along with this program; if not, write to the Free Software
277 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
280 + * @brief Implementation of juped server handling functions.
281 + * @version $Id: jupe.c 1633 2006-03-25 03:46:56Z entrope $
288 +#include "ircd_alloc.h"
289 +#include "ircd_features.h"
290 +#include "ircd_log.h"
291 +#include "ircd_reply.h"
292 +#include "ircd_string.h"
295 +#include "numeric.h"
296 +#include "numnicks.h"
301 +#include "sys.h" /* FALSE bleah */
302 +#include "welcome.h"
304 +/* #include <assert.h> -- Now using assert in ircd_log.h */
307 +/** List of jupes. */
308 +static struct Jupe *GlobalJupeList = 0;
310 +/** Allocate a new jupe with the given parameters.
311 + * @param[in] server Server name to jupe.
312 + * @param[in] reason Reason for jupe.
313 + * @param[in] expire Expiration time for jupe.
314 + * @param[in] lastmod Last modification time for jupe.
315 + * @param[in] flags Flags to set for the jupe.
317 +static struct Jupe *
318 +make_jupe(char *server, char *reason, time_t expire, time_t lastmod,
319 + unsigned int flags)
321 + struct Jupe *ajupe;
323 + ajupe = (struct Jupe*) MyMalloc(sizeof(struct Jupe)); /* alloc memory */
324 + assert(0 != ajupe);
326 + memset(ajupe, 0, sizeof(*ajupe));
327 + DupString(ajupe->ju_server, server); /* copy vital information */
328 + DupString(ajupe->ju_reason, reason);
329 + ajupe->ju_expire = expire;
330 + ajupe->ju_lastmod = lastmod;
331 + ajupe->ju_flags = flags & JUPE_MASK; /* set jupe flags */
333 + ajupe->ju_next = GlobalJupeList; /* link it into the list */
334 + ajupe->ju_prev_p = &GlobalJupeList;
335 + if (GlobalJupeList)
336 + GlobalJupeList->ju_prev_p = &ajupe->ju_next;
337 + GlobalJupeList = ajupe;
343 + * @param[in] cptr Local client that sent us the jupe.
344 + * @param[in] sptr Originator of the jupe.
345 + * @param[in] jupe Jupe to check.
348 +do_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
350 + struct Client *acptr;
352 + if (!JupeIsActive(jupe)) /* no action to be taken on inactive jupes */
355 + acptr = FindServer(jupe->ju_server);
357 + /* server isn't online or isn't local or is me */
358 + if (!acptr || !MyConnect(acptr) || IsMe(acptr))
361 + return exit_client_msg(cptr, acptr, &me, "Juped: %s", jupe->ju_reason);
364 +/** Forward a jupe to another server.
365 + * @param[in] cptr Local client that sent us the jupe.
366 + * @param[in] sptr Originator of the jupe.
367 + * @param[in] jupe Jupe to forward.
370 +propagate_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
372 + if (JupeIsLocal(jupe)) /* don't propagate local jupes */
375 + sendcmdto_serv_butone(sptr, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
376 + JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
377 + jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
381 +/** Add a new server jupe.
382 + * @param[in] cptr Local client that sent us the jupe.
383 + * @param[in] sptr Originator of the jupe.
384 + * @param[in] server Server name to jupe.
385 + * @param[in] reason Reason for the jupe.
386 + * @param[in] expire Jupe duration in seconds.
387 + * @param[in] lastmod Last modification timestamp (or NULL).
388 + * @param[in] flags Flags to set on jupe.
389 + * @return Zero, unless the jupe causes \a cptr to be SQUIT, in which
390 + * case CPTR_KILLED.
393 +jupe_add(struct Client *cptr, struct Client *sptr, char *server, char *reason,
394 + time_t expire, time_t lastmod, unsigned int flags)
396 + struct Jupe *ajupe;
398 + assert(0 != server);
399 + assert(0 != reason);
402 + * You cannot set a negative (or zero) expire time, nor can you set an
403 + * expiration time for greater than JUPE_MAX_EXPIRE.
405 + if (expire <= 0 || expire > JUPE_MAX_EXPIRE) {
406 + if (!IsServer(cptr) && MyConnect(cptr))
407 + send_reply(cptr, ERR_BADEXPIRE, expire);
411 + expire += CurrentTime; /* convert from lifetime to timestamp */
413 + /* Inform ops and log it */
414 + sendto_opmask_butone(0, SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
416 + (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
417 + get_client_name_and_opername(sptr) :
418 + cli_name((cli_user(sptr))->server),
419 + flags & JUPE_LOCAL ? "local " : "", server,
420 + expire + TSoffset, reason);
422 + log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
423 + "%#C adding %sJUPE for %s, expiring at %Tu: %s", sptr,
424 + flags & JUPE_LOCAL ? "local " : "", server, expire + TSoffset,
427 + /* local jupe set by remote user, inform oper of success */
428 + if ((flags & JUPE_LOCAL) && IsUser(sptr) && !MyUser(sptr))
429 + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s adding local JUPE for %s, expiring at %Tu: %s",
430 + sptr, cli_name(sptr), server, expire + TSoffset, reason);
432 + /* make the jupe */
433 + ajupe = make_jupe(server, reason, expire, lastmod, flags);
435 + propagate_jupe(cptr, sptr, ajupe);
437 + return do_jupe(cptr, sptr, ajupe); /* remove server if necessary */
440 +/** Activate a jupe, optionally changing its lastmod and flags.
441 + * @param[in] cptr Local client that sent us the jupe.
442 + * @param[in] sptr Originator of the jupe.
443 + * @param[in] jupe Jupe to activate.
444 + * @param[in] lastmod New timestamp for last modification of the jupe.
445 + * @param[in] flags Flags to set on the jupe.
446 + * @return Zero, unless the jupe causes \a cptr to be SQUIT, in which
447 + * case CPTR_KILLED.
450 +jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
451 + time_t lastmod, unsigned int flags)
453 + unsigned int saveflags = 0;
457 + saveflags = jupe->ju_flags;
459 + if (flags & JUPE_LOCAL)
460 + jupe->ju_flags &= ~JUPE_LDEACT;
462 + jupe->ju_flags |= JUPE_ACTIVE;
464 + if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
465 + jupe->ju_lastmod++;
467 + jupe->ju_lastmod = lastmod;
470 + if ((saveflags & JUPE_ACTMASK) == JUPE_ACTIVE)
471 + return 0; /* was active to begin with */
473 + /* Inform ops and log it */
474 + sendto_opmask_butone(0, SNO_NETWORK, "%s activating JUPE for %s, expiring "
476 + (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
477 + get_client_name_and_opername(sptr) :
478 + cli_name((cli_user(sptr))->server),
479 + jupe->ju_server, jupe->ju_expire + TSoffset,
482 + log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
483 + "%#C activating JUPE for %s, expiring at %Tu: %s",sptr,
484 + jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
486 + if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
487 + propagate_jupe(cptr, sptr, jupe);
489 + return do_jupe(cptr, sptr, jupe);
492 +/** Deactivate a jupe.
493 + * @param[in] cptr Local client that sent us the jupe.
494 + * @param[in] sptr Originator of the jupe.
495 + * @param[in] jupe Jupe to deactivate.
496 + * @param[in] lastmod New timestamp for last modification of the jupe.
497 + * @param[in] flags Flags to set on the jupe.
501 +jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
502 + time_t lastmod, unsigned int flags)
504 + unsigned int saveflags = 0;
508 + saveflags = jupe->ju_flags;
510 + if (!JupeIsLocal(jupe)) {
511 + if (flags & JUPE_LOCAL)
512 + jupe->ju_flags |= JUPE_LDEACT;
514 + jupe->ju_flags &= ~JUPE_ACTIVE;
516 + if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
517 + jupe->ju_lastmod++;
519 + jupe->ju_lastmod = lastmod;
522 + if ((saveflags & JUPE_ACTMASK) != JUPE_ACTIVE)
523 + return 0; /* was inactive to begin with */
526 + /* Inform ops and log it */
527 + sendto_opmask_butone(0, SNO_NETWORK, "%s %s JUPE for %s, expiring at %Tu: "
529 + (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
530 + get_client_name_and_opername(sptr) :
531 + cli_name((cli_user(sptr))->server),
532 + JupeIsLocal(jupe) ? "removing local" : "deactivating",
533 + jupe->ju_server, jupe->ju_expire + TSoffset,
536 + log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
537 + "%#C %s JUPE for %s, expiring at %Tu: %s", sptr,
538 + JupeIsLocal(jupe) ? "removing local" : "deactivating",
539 + jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
541 + /* local jupe removed by remote user, inform oper of success */
542 + if ((flags & JUPE_LOCAL) && IsUser(sptr) && !MyUser(sptr))
543 + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s removing local JUPE for %s, expiring at %Tu: %s",
544 + sptr, cli_name(sptr), jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
546 + if (JupeIsLocal(jupe))
548 + else if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
549 + propagate_jupe(cptr, sptr, jupe);
554 +/** Find a jupe by name.
555 + * @param[in] server %Jupe name to search for.
556 + * @return Matching jupe (or NULL if none match).
559 +jupe_find(char *server)
562 + struct Jupe* sjupe;
564 + for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
565 + sjupe = jupe->ju_next;
567 + if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
569 + else if (0 == ircd_strcmp(server, jupe->ju_server)) /* found it yet? */
576 +/** Unlink and free an unused jupe.
577 + * @param[in] jupe Server jupe to free.
580 +jupe_free(struct Jupe* jupe)
584 + *jupe->ju_prev_p = jupe->ju_next; /* squeeze this jupe out */
586 + jupe->ju_next->ju_prev_p = jupe->ju_prev_p;
588 + MyFree(jupe->ju_server); /* and free up the memory */
589 + MyFree(jupe->ju_reason);
593 +/** Send the full list of active global jupes to \a cptr.
594 + * @param[in] cptr Local server to send jupes to.
597 +jupe_burst(struct Client *cptr)
600 + struct Jupe *sjupe;
602 + for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
603 + sjupe = jupe->ju_next;
605 + if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
607 + else if (!JupeIsLocal(jupe)) /* forward global jupes */
608 + sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
609 + JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
610 + jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
615 +/** Forward a jupe to another server.
616 + * @param[in] cptr %Server to send jupe to.
617 + * @param[in] jupe Jupe to forward.
620 +jupe_resend(struct Client *cptr, struct Jupe *jupe)
622 + if (JupeIsLocal(jupe)) /* don't propagate local jupes */
625 + sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
626 + JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
627 + jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
633 +/** Send a jupe (or a list of jupes) to a server.
634 + * @param[in] sptr Client searching for jupes.
635 + * @param[in] server Name of jupe to search for (if NULL, list all).
639 +jupe_list(struct Client *sptr, char *server)
642 + struct Jupe *sjupe;
645 + if (!(jupe = jupe_find(server))) /* no such jupe */
646 + return send_reply(sptr, ERR_NOSUCHJUPE, server);
648 + /* send jupe information along */
649 + send_reply(sptr, RPL_JUPELIST, jupe->ju_server, jupe->ju_expire + TSoffset,
650 + JupeIsLocal(jupe) ? cli_name(&me) : "*",
651 + JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
653 + for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
654 + sjupe = jupe->ju_next;
656 + if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
658 + else /* send jupe information along */
659 + send_reply(sptr, RPL_JUPELIST, jupe->ju_server,
660 + jupe->ju_expire + TSoffset,
661 + JupeIsLocal(jupe) ? cli_name(&me) : "*",
662 + JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
666 + /* end of jupe information */
667 + return send_reply(sptr, RPL_ENDOFJUPELIST);
670 +/** Count welcome and memory used by it.
671 + * @param[out] we_size Receives total number of bytes allocated for welcome.
672 + * @return Number of welcomes currently allocated.
675 +welcome_memory_count(size_t *we_size)
678 + unsigned int ju = 0;
680 + for (jupe = GlobalJupeList; jupe; jupe = jupe->ju_next)
683 + *ju_size += sizeof(struct Jupe);
684 + *ju_size += jupe->ju_server ? (strlen(jupe->ju_server) + 1) : 0;
685 + *ju_size += jupe->ju_reason ? (strlen(jupe->ju_reason) + 1) : 0;
689 \ No newline at end of file