/[cvs]/eggdrop1.8/src/chanprog.c
ViewVC logotype

Annotation of /eggdrop1.8/src/chanprog.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7.2.1 - (hide annotations) (download) (as text)
Wed Nov 10 13:39:19 2010 UTC (8 years, 11 months ago) by pseudo
Branch: gettext
Changes since 1.7: +60 -63 lines
File MIME type: text/x-chdr
Converted remaining lang #defines in the core to english strings from core.english.lang. Gettextified most of the hardcoded strings.

1 simple 1.1 /*
2     * chanprog.c -- handles:
3     * rmspace()
4     * maintaining the server list
5     * revenge punishment
6     * timers, utimers
7     * telling the current programmed settings
8     * initializing a lot of stuff and loading the tcl scripts
9     *
10 pseudo 1.7.2.1 * $Id: chanprog.c,v 1.7.2.1 2010/11/10 13:39:19 pseudo Exp $
11 simple 1.1 */
12     /*
13     * Copyright (C) 1997 Robey Pointer
14     * Copyright (C) 1999 - 2010 Eggheads Development Team
15     *
16     * This program is free software; you can redistribute it and/or
17     * modify it under the terms of the GNU General Public License
18     * as published by the Free Software Foundation; either version 2
19     * of the License, or (at your option) any later version.
20     *
21     * This program is distributed in the hope that it will be useful,
22     * but WITHOUT ANY WARRANTY; without even the implied warranty of
23     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24     * GNU General Public License for more details.
25     *
26     * You should have received a copy of the GNU General Public License
27     * along with this program; if not, write to the Free Software
28     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29     */
30    
31     #include "main.h"
32    
33     #ifdef HAVE_GETRUSAGE
34     # include <sys/resource.h>
35     # ifdef HAVE_SYS_RUSAGE_H
36     # include <sys/rusage.h>
37     # endif
38     #endif
39    
40     #ifdef HAVE_UNAME
41     # include <sys/utsname.h>
42     #endif
43    
44     #include "modules.h"
45    
46     extern struct userrec *userlist;
47     extern log_t *logs;
48     extern Tcl_Interp *interp;
49     extern char ver[], botnetnick[], firewall[], motdfile[], userfile[], helpdir[],
50     tempdir[], moddir[], notify_new[], owner[], configfile[];
51     extern time_t now, online_since;
52     extern int backgrd, term_z, con_chan, cache_hit, cache_miss, firewallport,
53     default_flags, max_logs, conmask, protect_readonly, make_userfile,
54     noshare, ignore_time, max_socks;
55 pseudo 1.4 #ifdef TLS
56     extern SSL_CTX *ssl_ctx;
57     #endif
58 simple 1.1
59     tcl_timer_t *timer = NULL; /* Minutely timer */
60     tcl_timer_t *utimer = NULL; /* Secondly timer */
61     unsigned long timer_id = 1; /* Next timer of any sort will
62     * have this number */
63     struct chanset_t *chanset = NULL; /* Channel list */
64     char admin[121] = ""; /* Admin info */
65     char origbotname[NICKLEN + 1];
66     char botname[NICKLEN + 1]; /* Primary botname */
67    
68    
69     /* Remove leading and trailing whitespaces.
70     */
71     void rmspace(char *s)
72     {
73     register char *p = NULL, *q = NULL;
74    
75     if (!s || !*s)
76     return;
77    
78     /* Remove trailing whitespaces. */
79     for (q = s + strlen(s) - 1; q >= s && egg_isspace(*q); q--);
80     *(q + 1) = 0;
81    
82     /* Remove leading whitespaces. */
83     for (p = s; egg_isspace(*p); p++);
84    
85     if (p != s)
86     memmove(s, p, q - p + 2);
87     }
88    
89    
90     /* Returns memberfields if the nick is in the member list.
91     */
92     memberlist *ismember(struct chanset_t *chan, char *nick)
93     {
94     register memberlist *x;
95    
96     for (x = chan->channel.member; x && x->nick[0]; x = x->next)
97     if (!rfc_casecmp(x->nick, nick))
98     return x;
99     return NULL;
100     }
101    
102     /* Find a chanset by channel name as the server knows it (ie !ABCDEchannel)
103     */
104     struct chanset_t *findchan(const char *name)
105     {
106     register struct chanset_t *chan;
107    
108     for (chan = chanset; chan; chan = chan->next)
109     if (!rfc_casecmp(chan->name, name))
110     return chan;
111     return NULL;
112     }
113    
114     /* Find a chanset by display name (ie !channel)
115     */
116     struct chanset_t *findchan_by_dname(const char *name)
117     {
118     register struct chanset_t *chan;
119    
120     for (chan = chanset; chan; chan = chan->next)
121     if (!rfc_casecmp(chan->dname, name))
122     return chan;
123     return NULL;
124     }
125    
126    
127     /*
128     * "caching" functions
129     */
130    
131     /* Shortcut for get_user_by_host -- might have user record in one
132     * of the channel caches.
133     */
134     struct userrec *check_chanlist(const char *host)
135     {
136     char *nick, *uhost, buf[UHOSTLEN];
137     register memberlist *m;
138     register struct chanset_t *chan;
139    
140     strncpyz(buf, host, sizeof buf);
141     uhost = buf;
142     nick = splitnick(&uhost);
143     for (chan = chanset; chan; chan = chan->next)
144     for (m = chan->channel.member; m && m->nick[0]; m = m->next)
145     if (!rfc_casecmp(nick, m->nick) && !egg_strcasecmp(uhost, m->userhost))
146     return m->user;
147     return NULL;
148     }
149    
150     /* Shortcut for get_user_by_handle -- might have user record in channels
151     */
152     struct userrec *check_chanlist_hand(const char *hand)
153     {
154     register struct chanset_t *chan;
155     register memberlist *m;
156    
157     for (chan = chanset; chan; chan = chan->next)
158     for (m = chan->channel.member; m && m->nick[0]; m = m->next)
159     if (m->user && !egg_strcasecmp(m->user->handle, hand))
160     return m->user;
161     return NULL;
162     }
163    
164     /* Clear the user pointers in the chanlists.
165     *
166     * Necessary when a hostmask is added/removed, a user is added or a new
167     * userfile is loaded.
168     */
169     void clear_chanlist(void)
170     {
171     register memberlist *m;
172     register struct chanset_t *chan;
173    
174     for (chan = chanset; chan; chan = chan->next)
175     for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
176     m->user = NULL;
177     m->tried_getuser = 0;
178     }
179     }
180    
181     /* Clear the user pointer of a specific nick in the chanlists.
182     *
183     * Necessary when a hostmask is added/removed, a nick changes, etc.
184     * Does not completely invalidate the channel cache like clear_chanlist().
185     */
186     void clear_chanlist_member(const char *nick)
187     {
188     register memberlist *m;
189     register struct chanset_t *chan;
190    
191     for (chan = chanset; chan; chan = chan->next)
192     for (m = chan->channel.member; m && m->nick[0]; m = m->next)
193     if (!rfc_casecmp(m->nick, nick)) {
194     m->user = NULL;
195     m->tried_getuser = 0;
196     break;
197     }
198     }
199    
200     /* If this user@host is in a channel, set it (it was null)
201     */
202     void set_chanlist(const char *host, struct userrec *rec)
203     {
204     char *nick, *uhost, buf[UHOSTLEN];
205     register memberlist *m;
206     register struct chanset_t *chan;
207    
208     strncpyz(buf, host, sizeof buf);
209     uhost = buf;
210     nick = splitnick(&uhost);
211     for (chan = chanset; chan; chan = chan->next)
212     for (m = chan->channel.member; m && m->nick[0]; m = m->next)
213     if (!rfc_casecmp(nick, m->nick) && !egg_strcasecmp(uhost, m->userhost))
214     m->user = rec;
215     }
216    
217     /* Calculate the memory we should be using
218     */
219     int expmem_chanprog()
220     {
221     register int tot = 0;
222     register tcl_timer_t *t;
223    
224     for (t = timer; t; t = t->next)
225     tot += sizeof(tcl_timer_t) + strlen(t->cmd) + 1;
226     for (t = utimer; t; t = t->next)
227     tot += sizeof(tcl_timer_t) + strlen(t->cmd) + 1;
228     return tot;
229     }
230    
231 pseudo 1.2 float getcputime()
232     {
233     #ifdef HAVE_GETRUSAGE
234     float stime, utime;
235     struct rusage ru;
236    
237     getrusage(RUSAGE_SELF, &ru);
238     utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 1000000.00);
239     stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 1000000.00);
240     return (utime + stime);
241     #else
242     # ifdef HAVE_CLOCK
243     return (clock() / (CLOCKS_PER_SEC * 1.00));
244     # else
245     return -1.00;
246     # endif
247     #endif
248     }
249    
250 simple 1.1 /* Dump uptime info out to dcc (guppy 9Jan99)
251     */
252     void tell_verbose_uptime(int idx)
253     {
254     char s[256], s1[121];
255     time_t now2, hr, min;
256    
257     now2 = now - online_since;
258     s[0] = 0;
259     if (now2 > 86400) {
260     /* days */
261     sprintf(s, "%d day", (int) (now2 / 86400));
262     if ((int) (now2 / 86400) >= 2)
263     strcat(s, "s");
264     strcat(s, ", ");
265     now2 -= (((int) (now2 / 86400)) * 86400);
266     }
267     hr = (time_t) ((int) now2 / 3600);
268     now2 -= (hr * 3600);
269     min = (time_t) ((int) now2 / 60);
270     sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
271     s1[0] = 0;
272     if (backgrd)
273 pseudo 1.7.2.1 strcpy(s1, _("background mode"));
274 simple 1.1 else {
275     if (term_z)
276 pseudo 1.7.2.1 strcpy(s1, _("terminal mode"));
277 simple 1.1 else if (con_chan)
278 pseudo 1.7.2.1 strcpy(s1, _("status mode"));
279 simple 1.1 else
280 pseudo 1.7.2.1 strcpy(s1, _("log dump mode"));
281 simple 1.1 }
282 pseudo 1.7.2.1 dprintf(idx, _("Online for %s (%s)\n"), s, s1);
283 simple 1.1 }
284    
285     /* Dump status info out to dcc
286     */
287     void tell_verbose_status(int idx)
288     {
289     char s[256], s1[121], s2[81];
290     char *vers_t, *uni_t;
291     int i;
292     time_t now2 = now - online_since, hr, min;
293 pseudo 1.2 float cputime;
294 simple 1.1 #ifdef HAVE_UNAME
295     struct utsname un;
296    
297 pseudo 1.5 if (uname(&un) < 0) {
298 simple 1.1 #endif
299     vers_t = " ";
300 pseudo 1.7.2.1 uni_t = _("*Unknown*");
301 simple 1.1 #ifdef HAVE_UNAME
302     } else {
303     vers_t = un.release;
304     uni_t = un.sysname;
305     }
306     #endif
307    
308     i = count_users(userlist);
309 pseudo 1.7.2.1 dprintf(idx, P_("I am %s, running %s: %d user (mem: %uk).\n",
310     "I am %s, running %s: %d users (mem: %uk).\n", i),
311     botnetnick, ver, i, (int) (expected_memory() / 1024));
312 simple 1.1
313     s[0] = 0;
314     if (now2 > 86400) {
315     /* days */
316     sprintf(s, "%d day", (int) (now2 / 86400));
317     if ((int) (now2 / 86400) >= 2)
318     strcat(s, "s");
319     strcat(s, ", ");
320     now2 -= (((int) (now2 / 86400)) * 86400);
321     }
322     hr = (time_t) ((int) now2 / 3600);
323     now2 -= (hr * 3600);
324     min = (time_t) ((int) now2 / 60);
325     sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
326     s1[0] = 0;
327     if (backgrd)
328 pseudo 1.7.2.1 strcpy(s1, _("background"));
329 simple 1.1 else {
330     if (term_z)
331 pseudo 1.7.2.1 strcpy(s1, _("terminal mode"));
332 simple 1.1 else if (con_chan)
333 pseudo 1.7.2.1 strcpy(s1, _("status mode"));
334 simple 1.1 else
335 pseudo 1.7.2.1 strcpy(s1, _("log dump mode"));
336 simple 1.1 }
337 pseudo 1.2 cputime = getcputime();
338     if (cputime < 0)
339 pseudo 1.7.2.1 sprintf(s2, _("CPU: unknown"));
340 pseudo 1.2 else {
341     hr = cputime / 60;
342     cputime -= hr * 60;
343 pseudo 1.7.2.1 sprintf(s2, _("CPU: %02d:%05.2f"), (int) hr, cputime); /* min/sec */
344 pseudo 1.2 }
345 pseudo 1.7.2.1 dprintf(idx, _("Online for %s (%s) - %s - Cache hit: %4.1f%%\n"), s, s1, s2,
346 simple 1.1 100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
347    
348 pseudo 1.7.2.1 dprintf(idx, _("Configured with: %s\n"), EGG_AC_ARGS);
349 simple 1.1 if (admin[0])
350 pseudo 1.7.2.1 dprintf(idx, _("Admin: %s\n"), admin);
351 simple 1.1
352 pseudo 1.7.2.1 dprintf(idx, _("Config file: %s\n"), configfile);
353     dprintf(idx, _("OS: %s %s\n"), uni_t, vers_t);
354     dprintf(idx, _("Process ID: %d (parent %d)\n"), getpid(), getppid());
355 simple 1.1
356     /* info library */
357 pseudo 1.7.2.1 dprintf(idx, _("Tcl library: %s\n"),
358 simple 1.1 ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
359 pseudo 1.7.2.1 tcl_resultstring() : _("*unknown*"));
360 simple 1.1
361     /* info tclversion/patchlevel */
362 pseudo 1.7.2.1 dprintf(idx, _("Tcl version: %s (%s %s)\n"),
363 simple 1.1 ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
364     tcl_resultstring() : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
365 pseudo 1.7.2.1 tcl_resultstring() : _("*unknown*"), _("header version"),
366     TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL : _("*unknown*"));
367 simple 1.1
368     if (tcl_threaded())
369 pseudo 1.7.2.1 dprintf(idx, _("Tcl is threaded.\n"));
370 pseudo 1.4 #ifdef TLS
371 pseudo 1.7.2.1 dprintf(idx, _("TLS support is enabled.\n"));
372     dprintf(idx, _("TLS library: %s\n"), SSLeay_version(SSLEAY_VERSION));
373 pseudo 1.4 #else
374 pseudo 1.7.2.1 dprintf(idx, _("TLS support is not available.\n"));
375 pseudo 1.4 #endif
376     #ifdef IPV6
377 pseudo 1.7.2.1 dprintf(idx, _("IPv6 support is enabled.\n"));
378 pseudo 1.4 #else
379 pseudo 1.7.2.1 dprintf(idx, _("IPv6 support is not available.\n"));
380 pseudo 1.4 #endif
381 pseudo 1.7.2.1 dprintf(idx, _("Socket table: %d/%d\n"), threaddata()->MAXSOCKS, max_socks);
382 simple 1.1 }
383    
384     /* Show all internal state variables
385     */
386     void tell_settings(int idx)
387     {
388     char s[1024];
389     int i;
390     struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 };
391    
392 pseudo 1.7.2.1 dprintf(idx, _("Botnet nickname: %s\n"), botnetnick);
393 simple 1.1 if (firewall[0])
394 pseudo 1.7.2.1 dprintf(idx, _("Firewall: %s:%d\n"), firewall, firewallport);
395     dprintf(idx, _("Userfile: %s\n"), userfile);
396     dprintf(idx, _("Motd: %s\n"), motdfile);
397     dprintf(idx, _("Directories:\n"));
398     dprintf(idx, _(" Help : %s\n"), helpdir);
399     dprintf(idx, _(" Temp : %s\n"), tempdir);
400     #ifdef STATIC
401     dprintf(idx, _(" Modules: %s\n"), moddir);
402 simple 1.1 #endif
403     fr.global = default_flags;
404    
405     build_flags(s, &fr, NULL);
406 pseudo 1.7.2.1 dprintf(idx, _("New users get flags [%s], notify: %s\n"), s, notify_new);
407 simple 1.1 if (owner[0])
408 pseudo 1.7.2.1 dprintf(idx, _("Permanent owner(s): %s\n"), owner);
409 simple 1.1 for (i = 0; i < max_logs; i++)
410     if (logs[i].filename != NULL) {
411 pseudo 1.7.2.1 dprintf(idx, _("Logfile #%d: %s on %s (%s: %s)\n"), i + 1,
412 simple 1.1 logs[i].filename, logs[i].chname,
413     masktype(logs[i].mask), maskname(logs[i].mask));
414     }
415 pseudo 1.7.2.1 dprintf(idx, _("Ignores last %d minute%s.\n"), ignore_time,
416 simple 1.1 (ignore_time != 1) ? "s" : "");
417     }
418    
419     void reaffirm_owners()
420     {
421     char *p, *q, s[121];
422     struct userrec *u;
423    
424     /* Please stop breaking this function. */
425     if (owner[0]) {
426     q = owner;
427     p = strchr(q, ',');
428     while (p) {
429     strncpyz(s, q, (p - q) + 1);
430     rmspace(s);
431     u = get_user_by_handle(userlist, s);
432     if (u)
433     u->flags = sanity_check(u->flags | USER_OWNER);
434     q = p + 1;
435     p = strchr(q, ',');
436     }
437     strcpy(s, q);
438     rmspace(s);
439     u = get_user_by_handle(userlist, s);
440     if (u)
441     u->flags = sanity_check(u->flags | USER_OWNER);
442     }
443     }
444    
445     void chanprog()
446     {
447     int i;
448     FILE *f;
449     char s[161], rands[8];
450    
451     admin[0] = 0;
452     helpdir[0] = 0;
453     tempdir[0] = 0;
454     conmask = 0;
455    
456     for (i = 0; i < max_logs; i++)
457     logs[i].flags |= LF_EXPIRING;
458    
459     /* Turn off read-only variables (make them write-able) for rehash */
460     protect_readonly = 0;
461    
462     /* Now read it */
463     if (!readtclprog(configfile))
464 pseudo 1.7.2.1 fatal(_("CONFIG FILE NOT LOADED (NOT FOUND, OR ERROR)"), 0);
465 simple 1.1
466     for (i = 0; i < max_logs; i++) {
467     if (logs[i].flags & LF_EXPIRING) {
468     if (logs[i].filename != NULL) {
469     nfree(logs[i].filename);
470     logs[i].filename = NULL;
471     }
472     if (logs[i].chname != NULL) {
473     nfree(logs[i].chname);
474     logs[i].chname = NULL;
475     }
476     if (logs[i].f != NULL) {
477     fclose(logs[i].f);
478     logs[i].f = NULL;
479     }
480     logs[i].mask = 0;
481     logs[i].flags = 0;
482     }
483     }
484    
485     /* We should be safe now */
486     call_hook(HOOK_REHASH);
487     protect_readonly = 1;
488    
489     if (!botnetnick[0])
490     strncpyz(botnetnick, origbotname, HANDLEN + 1);
491    
492     if (!botnetnick[0])
493 pseudo 1.7.2.1 fatal(_("I don't have a botnet nick!!\n"), 0);
494 simple 1.1
495     if (!userfile[0])
496 pseudo 1.7.2.1 fatal(_("USER FILE NOT FOUND! (try './eggdrop -m %s' to make one)\n"), 0);
497 simple 1.1
498     if (!readuserfile(userfile, &userlist)) {
499     if (!make_userfile) {
500     char tmp[178];
501    
502 pseudo 1.7.2.1 egg_snprintf(tmp, sizeof tmp, _("USER FILE NOT FOUND! "
503     "(try './eggdrop -m %s' to make one)\n"), configfile);
504 simple 1.1 fatal(tmp, 0);
505     }
506 pseudo 1.7.2.1 printf(_("STARTING BOT IN USERFILE CREATION MODE.\n"
507     "Telnet to the bot and enter 'NEW' as your nickname."));
508 simple 1.1 if (module_find("server", 0, 0))
509 pseudo 1.7.2.1 printf(_("OR go to IRC and type: /msg %s hello\n"), origbotname);
510     printf("This will make the bot recognize you as the master.\n");
511 simple 1.1 } else if (make_userfile) {
512     make_userfile = 0;
513 pseudo 1.7.2.1 printf("%s\n", _("USERFILE ALREADY EXISTS (drop the '-m')"));
514 simple 1.1 }
515    
516     if (helpdir[0])
517     if (helpdir[strlen(helpdir) - 1] != '/')
518     strcat(helpdir, "/");
519    
520     if (tempdir[0])
521     if (tempdir[strlen(tempdir) - 1] != '/')
522     strcat(tempdir, "/");
523    
524     /* Test tempdir: it's vital. */
525    
526     /* Possible file race condition solved by using a random string
527     * and the process id in the filename.
528     * FIXME: This race is only partitially fixed. We could still be
529     * overwriting an existing file / following a malicious
530     * link.
531     */
532     make_rand_str(rands, 7); /* create random string */
533     sprintf(s, "%s.test-%u-%s", tempdir, getpid(), rands);
534     f = fopen(s, "w");
535     if (f == NULL)
536 pseudo 1.7.2.1 fatal(_("CAN'T WRITE TO TEMP DIR"), 0);
537 simple 1.1 fclose(f);
538     unlink(s);
539     reaffirm_owners();
540     check_tcl_event("userfile-loaded");
541     }
542    
543     /* Reload the user file from disk
544     */
545     void reload()
546     {
547     if (!file_readable(userfile)) {
548 pseudo 1.7.2.1 putlog(LOG_MISC, "*", _("Can't reload user file!"));
549 simple 1.1 return;
550     }
551    
552     noshare = 1;
553     clear_userlist(userlist);
554     noshare = 0;
555     userlist = NULL;
556     if (!readuserfile(userfile, &userlist))
557 pseudo 1.7.2.1 fatal(_("User file is missing!"), 0);
558 simple 1.1 reaffirm_owners();
559     check_tcl_event("userfile-loaded");
560     call_hook(HOOK_READ_USERFILE);
561     }
562    
563     void rehash()
564     {
565     call_hook(HOOK_PRE_REHASH);
566     noshare = 1;
567     clear_userlist(userlist);
568     noshare = 0;
569     userlist = NULL;
570     chanprog();
571     }
572    
573     /*
574     * Brief venture into timers
575     */
576    
577     /* Add a timer
578     */
579 pseudo 1.6 unsigned long add_timer(tcl_timer_t ** stack, int elapse, int count,
580     char *cmd, unsigned long prev_id)
581 simple 1.1 {
582     tcl_timer_t *old = (*stack);
583    
584     *stack = nmalloc(sizeof **stack);
585     (*stack)->next = old;
586 pseudo 1.6 (*stack)->mins = (*stack)->interval = elapse;
587     (*stack)->count = count;
588 simple 1.1 (*stack)->cmd = nmalloc(strlen(cmd) + 1);
589     strcpy((*stack)->cmd, cmd);
590     /* If it's just being added back and already had an id,
591     * don't create a new one.
592     */
593     if (prev_id > 0)
594     (*stack)->id = prev_id;
595     else
596     (*stack)->id = timer_id++;
597     return (*stack)->id;
598     }
599    
600     /* Remove a timer, by id
601     */
602     int remove_timer(tcl_timer_t ** stack, unsigned long id)
603     {
604     tcl_timer_t *old;
605     int ok = 0;
606    
607     while (*stack) {
608     if ((*stack)->id == id) {
609     ok++;
610     old = *stack;
611     *stack = ((*stack)->next);
612     nfree(old->cmd);
613     nfree(old);
614     } else
615     stack = &((*stack)->next);
616     }
617     return ok;
618     }
619    
620     /* Check timers, execute the ones that have expired.
621     */
622     void do_check_timers(tcl_timer_t ** stack)
623     {
624     tcl_timer_t *mark = *stack, *old = NULL;
625     char x[16];
626    
627     /* New timers could be added by a Tcl script inside a current timer
628     * so i'll just clear out the timer list completely, and add any
629     * unexpired timers back on.
630     */
631     *stack = NULL;
632     while (mark) {
633     if (mark->mins > 0)
634     mark->mins--;
635     old = mark;
636     mark = mark->next;
637     if (!old->mins) {
638     egg_snprintf(x, sizeof x, "timer%lu", old->id);
639     do_tcl(x, old->cmd);
640 pseudo 1.6 if (old->count == 1) {
641     nfree(old->cmd);
642     nfree(old);
643     continue;
644     } else {
645     old->mins = old->interval;
646     if (old->count > 1)
647     old->count--;
648     }
649 simple 1.1 }
650 pseudo 1.6 old->next = *stack;
651     *stack = old;
652 simple 1.1 }
653     }
654    
655     /* Wipe all timers.
656     */
657     void wipe_timers(Tcl_Interp *irp, tcl_timer_t **stack)
658     {
659     tcl_timer_t *mark = *stack, *old;
660    
661     while (mark) {
662     old = mark;
663     mark = mark->next;
664     nfree(old->cmd);
665     nfree(old);
666     }
667     *stack = NULL;
668     }
669    
670     /* Return list of timers
671     */
672     void list_timers(Tcl_Interp *irp, tcl_timer_t *stack)
673     {
674 pseudo 1.6 char mins[10], count[10], id[16], *x;
675     EGG_CONST char *argv[4];
676 simple 1.1 tcl_timer_t *mark;
677    
678     for (mark = stack; mark; mark = mark->next) {
679     egg_snprintf(mins, sizeof mins, "%u", mark->mins);
680     egg_snprintf(id, sizeof id, "timer%lu", mark->id);
681 pseudo 1.6 egg_snprintf(count, sizeof count, "%u", mark->count);
682 simple 1.1 argv[0] = mins;
683     argv[1] = mark->cmd;
684     argv[2] = id;
685 pseudo 1.6 argv[3] = count;
686 thommey 1.7 x = Tcl_Merge(sizeof(argv)/sizeof(*argv), argv);
687 simple 1.1 Tcl_AppendElement(irp, x);
688     Tcl_Free((char *) x);
689     }
690     }
691    
692     /* Oddly enough, written by Sup (former(?) Eggdrop coder)
693     */
694     int isowner(char *name)
695     {
696     register char *ptr = NULL, *s = NULL, *n = NULL;
697    
698     if (!name)
699     return 0;
700    
701     ptr = owner - 1;
702    
703     do {
704     ptr++;
705     if (*ptr && !egg_isspace(*ptr) && *ptr != ',') {
706     if (!s)
707     s = ptr;
708     } else if (s) {
709     for (n = name; *n && *s && s < ptr &&
710     tolower((unsigned) *n) == tolower((unsigned) *s); n++, s++);
711    
712     if (s == ptr && !*n)
713     return 1;
714    
715     s = NULL;
716     }
717     } while (*ptr);
718    
719     return 0;
720     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23