/[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 - (hide annotations) (download) (as text)
Thu Nov 4 17:54:04 2010 UTC (8 years, 7 months ago) by thommey
Branch: MAIN
CVS Tags: HEAD
Branch point for: gettext
Changes since 1.6: +2 -2 lines
File MIME type: text/x-chdr
Fixed a bug in (u)timers which could lead to invalid memory access.

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 thommey 1.7 * $Id: chanprog.c,v 1.6 2010/10/27 20:47:26 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     strcpy(s1, MISC_BACKGROUND);
274     else {
275     if (term_z)
276     strcpy(s1, MISC_TERMMODE);
277     else if (con_chan)
278     strcpy(s1, MISC_STATMODE);
279     else
280     strcpy(s1, MISC_LOGMODE);
281     }
282     dprintf(idx, "%s %s (%s)\n", MISC_ONLINEFOR, s, s1);
283     }
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     uni_t = "*unknown*";
301     #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     dprintf(idx, "I am %s, running %s: %d user%s (mem: %uk).\n",
310     botnetnick, ver, i, i == 1 ? "" : "s",
311     (int) (expected_memory() / 1024));
312    
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     strcpy(s1, MISC_BACKGROUND);
329     else {
330     if (term_z)
331     strcpy(s1, MISC_TERMMODE);
332     else if (con_chan)
333     strcpy(s1, MISC_STATMODE);
334     else
335     strcpy(s1, MISC_LOGMODE);
336     }
337 pseudo 1.2 cputime = getcputime();
338     if (cputime < 0)
339     sprintf(s2, "CPU: unknown");
340     else {
341     hr = cputime / 60;
342     cputime -= hr * 60;
343     sprintf(s2, "CPU: %02d:%05.2f", (int) hr, cputime); /* Actally min/sec */
344     }
345 simple 1.1 dprintf(idx, "%s %s (%s) - %s - %s: %4.1f%%\n", MISC_ONLINEFOR,
346     s, s1, s2, MISC_CACHEHIT,
347     100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
348    
349 pseudo 1.3 dprintf(idx, "Configured with: " EGG_AC_ARGS "\n");
350 simple 1.1 if (admin[0])
351     dprintf(idx, "Admin: %s\n", admin);
352    
353     dprintf(idx, "Config file: %s\n", configfile);
354     dprintf(idx, "OS: %s %s\n", uni_t, vers_t);
355 pseudo 1.2 dprintf(idx, "Process ID: %d (parent %d)\n", getpid(), getppid());
356 simple 1.1
357     /* info library */
358     dprintf(idx, "%s %s\n", MISC_TCLLIBRARY,
359     ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
360     tcl_resultstring() : "*unknown*");
361    
362     /* info tclversion/patchlevel */
363     dprintf(idx, "%s %s (%s %s)\n", MISC_TCLVERSION,
364     ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
365     tcl_resultstring() : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
366     tcl_resultstring() : "*unknown*", MISC_TCLHVERSION,
367     TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL : "*unknown*");
368    
369     if (tcl_threaded())
370     dprintf(idx, "Tcl is threaded.\n");
371 pseudo 1.4 #ifdef TLS
372     dprintf(idx, "TLS support is enabled.\n");
373     dprintf(idx, "TLS library: %s\n", SSLeay_version(SSLEAY_VERSION));
374     #else
375     dprintf(idx, "TLS support is not available.\n");
376     #endif
377     #ifdef IPV6
378     dprintf(idx, "IPv6 support is enabled.\n");
379     #else
380     dprintf(idx, "IPv6 support is not available.\n");
381     #endif
382 simple 1.1 dprintf(idx, "Socket table: %d/%d\n", threaddata()->MAXSOCKS, max_socks);
383     }
384    
385     /* Show all internal state variables
386     */
387     void tell_settings(int idx)
388     {
389     char s[1024];
390     int i;
391     struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 };
392    
393     dprintf(idx, "Botnet nickname: %s\n", botnetnick);
394     if (firewall[0])
395     dprintf(idx, "Firewall: %s:%d\n", firewall, firewallport);
396     dprintf(idx, "Userfile: %s\n", userfile);
397     dprintf(idx, "Motd: %s\n", motdfile);
398     dprintf(idx, "Directories:\n");
399     #ifndef STATIC
400     dprintf(idx, " Help : %s\n", helpdir);
401     dprintf(idx, " Temp : %s\n", tempdir);
402     dprintf(idx, " Modules: %s\n", moddir);
403     #else
404     dprintf(idx, " Help: %s\n", helpdir);
405     dprintf(idx, " Temp: %s\n", tempdir);
406     #endif
407     fr.global = default_flags;
408    
409     build_flags(s, &fr, NULL);
410     dprintf(idx, "%s [%s], %s: %s\n", MISC_NEWUSERFLAGS, s,
411     MISC_NOTIFY, notify_new);
412     if (owner[0])
413     dprintf(idx, "%s: %s\n", MISC_PERMOWNER, owner);
414     for (i = 0; i < max_logs; i++)
415     if (logs[i].filename != NULL) {
416     dprintf(idx, "Logfile #%d: %s on %s (%s: %s)\n", i + 1,
417     logs[i].filename, logs[i].chname,
418     masktype(logs[i].mask), maskname(logs[i].mask));
419     }
420     dprintf(idx, "Ignores last %d minute%s.\n", ignore_time,
421     (ignore_time != 1) ? "s" : "");
422     }
423    
424     void reaffirm_owners()
425     {
426     char *p, *q, s[121];
427     struct userrec *u;
428    
429     /* Please stop breaking this function. */
430     if (owner[0]) {
431     q = owner;
432     p = strchr(q, ',');
433     while (p) {
434     strncpyz(s, q, (p - q) + 1);
435     rmspace(s);
436     u = get_user_by_handle(userlist, s);
437     if (u)
438     u->flags = sanity_check(u->flags | USER_OWNER);
439     q = p + 1;
440     p = strchr(q, ',');
441     }
442     strcpy(s, q);
443     rmspace(s);
444     u = get_user_by_handle(userlist, s);
445     if (u)
446     u->flags = sanity_check(u->flags | USER_OWNER);
447     }
448     }
449    
450     void chanprog()
451     {
452     int i;
453     FILE *f;
454     char s[161], rands[8];
455    
456     admin[0] = 0;
457     helpdir[0] = 0;
458     tempdir[0] = 0;
459     conmask = 0;
460    
461     for (i = 0; i < max_logs; i++)
462     logs[i].flags |= LF_EXPIRING;
463    
464     /* Turn off read-only variables (make them write-able) for rehash */
465     protect_readonly = 0;
466    
467     /* Now read it */
468     if (!readtclprog(configfile))
469     fatal(MISC_NOCONFIGFILE, 0);
470    
471     for (i = 0; i < max_logs; i++) {
472     if (logs[i].flags & LF_EXPIRING) {
473     if (logs[i].filename != NULL) {
474     nfree(logs[i].filename);
475     logs[i].filename = NULL;
476     }
477     if (logs[i].chname != NULL) {
478     nfree(logs[i].chname);
479     logs[i].chname = NULL;
480     }
481     if (logs[i].f != NULL) {
482     fclose(logs[i].f);
483     logs[i].f = NULL;
484     }
485     logs[i].mask = 0;
486     logs[i].flags = 0;
487     }
488     }
489    
490     /* We should be safe now */
491     call_hook(HOOK_REHASH);
492     protect_readonly = 1;
493    
494     if (!botnetnick[0])
495     strncpyz(botnetnick, origbotname, HANDLEN + 1);
496    
497     if (!botnetnick[0])
498     fatal("I don't have a botnet nick!!\n", 0);
499    
500     if (!userfile[0])
501     fatal(MISC_NOUSERFILE2, 0);
502    
503     if (!readuserfile(userfile, &userlist)) {
504     if (!make_userfile) {
505     char tmp[178];
506    
507     egg_snprintf(tmp, sizeof tmp, MISC_NOUSERFILE, configfile);
508     fatal(tmp, 0);
509     }
510     printf("\n\n%s\n", MISC_NOUSERFILE2);
511     if (module_find("server", 0, 0))
512     printf(MISC_USERFCREATE1, origbotname);
513     printf("%s\n\n", MISC_USERFCREATE2);
514     } else if (make_userfile) {
515     make_userfile = 0;
516     printf("%s\n", MISC_USERFEXISTS);
517     }
518    
519     if (helpdir[0])
520     if (helpdir[strlen(helpdir) - 1] != '/')
521     strcat(helpdir, "/");
522    
523     if (tempdir[0])
524     if (tempdir[strlen(tempdir) - 1] != '/')
525     strcat(tempdir, "/");
526    
527     /* Test tempdir: it's vital. */
528    
529     /* Possible file race condition solved by using a random string
530     * and the process id in the filename.
531     * FIXME: This race is only partitially fixed. We could still be
532     * overwriting an existing file / following a malicious
533     * link.
534     */
535     make_rand_str(rands, 7); /* create random string */
536     sprintf(s, "%s.test-%u-%s", tempdir, getpid(), rands);
537     f = fopen(s, "w");
538     if (f == NULL)
539     fatal(MISC_CANTWRITETEMP, 0);
540     fclose(f);
541     unlink(s);
542     reaffirm_owners();
543     check_tcl_event("userfile-loaded");
544     }
545    
546     /* Reload the user file from disk
547     */
548     void reload()
549     {
550     if (!file_readable(userfile)) {
551     putlog(LOG_MISC, "*", MISC_CANTRELOADUSER);
552     return;
553     }
554    
555     noshare = 1;
556     clear_userlist(userlist);
557     noshare = 0;
558     userlist = NULL;
559     if (!readuserfile(userfile, &userlist))
560     fatal(MISC_MISSINGUSERF, 0);
561     reaffirm_owners();
562     check_tcl_event("userfile-loaded");
563     call_hook(HOOK_READ_USERFILE);
564     }
565    
566     void rehash()
567     {
568     call_hook(HOOK_PRE_REHASH);
569     noshare = 1;
570     clear_userlist(userlist);
571     noshare = 0;
572     userlist = NULL;
573     chanprog();
574     }
575    
576     /*
577     * Brief venture into timers
578     */
579    
580     /* Add a timer
581     */
582 pseudo 1.6 unsigned long add_timer(tcl_timer_t ** stack, int elapse, int count,
583     char *cmd, unsigned long prev_id)
584 simple 1.1 {
585     tcl_timer_t *old = (*stack);
586    
587     *stack = nmalloc(sizeof **stack);
588     (*stack)->next = old;
589 pseudo 1.6 (*stack)->mins = (*stack)->interval = elapse;
590     (*stack)->count = count;
591 simple 1.1 (*stack)->cmd = nmalloc(strlen(cmd) + 1);
592     strcpy((*stack)->cmd, cmd);
593     /* If it's just being added back and already had an id,
594     * don't create a new one.
595     */
596     if (prev_id > 0)
597     (*stack)->id = prev_id;
598     else
599     (*stack)->id = timer_id++;
600     return (*stack)->id;
601     }
602    
603     /* Remove a timer, by id
604     */
605     int remove_timer(tcl_timer_t ** stack, unsigned long id)
606     {
607     tcl_timer_t *old;
608     int ok = 0;
609    
610     while (*stack) {
611     if ((*stack)->id == id) {
612     ok++;
613     old = *stack;
614     *stack = ((*stack)->next);
615     nfree(old->cmd);
616     nfree(old);
617     } else
618     stack = &((*stack)->next);
619     }
620     return ok;
621     }
622    
623     /* Check timers, execute the ones that have expired.
624     */
625     void do_check_timers(tcl_timer_t ** stack)
626     {
627     tcl_timer_t *mark = *stack, *old = NULL;
628     char x[16];
629    
630     /* New timers could be added by a Tcl script inside a current timer
631     * so i'll just clear out the timer list completely, and add any
632     * unexpired timers back on.
633     */
634     *stack = NULL;
635     while (mark) {
636     if (mark->mins > 0)
637     mark->mins--;
638     old = mark;
639     mark = mark->next;
640     if (!old->mins) {
641     egg_snprintf(x, sizeof x, "timer%lu", old->id);
642     do_tcl(x, old->cmd);
643 pseudo 1.6 if (old->count == 1) {
644     nfree(old->cmd);
645     nfree(old);
646     continue;
647     } else {
648     old->mins = old->interval;
649     if (old->count > 1)
650     old->count--;
651     }
652 simple 1.1 }
653 pseudo 1.6 old->next = *stack;
654     *stack = old;
655 simple 1.1 }
656     }
657    
658     /* Wipe all timers.
659     */
660     void wipe_timers(Tcl_Interp *irp, tcl_timer_t **stack)
661     {
662     tcl_timer_t *mark = *stack, *old;
663    
664     while (mark) {
665     old = mark;
666     mark = mark->next;
667     nfree(old->cmd);
668     nfree(old);
669     }
670     *stack = NULL;
671     }
672    
673     /* Return list of timers
674     */
675     void list_timers(Tcl_Interp *irp, tcl_timer_t *stack)
676     {
677 pseudo 1.6 char mins[10], count[10], id[16], *x;
678     EGG_CONST char *argv[4];
679 simple 1.1 tcl_timer_t *mark;
680    
681     for (mark = stack; mark; mark = mark->next) {
682     egg_snprintf(mins, sizeof mins, "%u", mark->mins);
683     egg_snprintf(id, sizeof id, "timer%lu", mark->id);
684 pseudo 1.6 egg_snprintf(count, sizeof count, "%u", mark->count);
685 simple 1.1 argv[0] = mins;
686     argv[1] = mark->cmd;
687     argv[2] = id;
688 pseudo 1.6 argv[3] = count;
689 thommey 1.7 x = Tcl_Merge(sizeof(argv)/sizeof(*argv), argv);
690 simple 1.1 Tcl_AppendElement(irp, x);
691     Tcl_Free((char *) x);
692     }
693     }
694    
695     /* Oddly enough, written by Sup (former(?) Eggdrop coder)
696     */
697     int isowner(char *name)
698     {
699     register char *ptr = NULL, *s = NULL, *n = NULL;
700    
701     if (!name)
702     return 0;
703    
704     ptr = owner - 1;
705    
706     do {
707     ptr++;
708     if (*ptr && !egg_isspace(*ptr) && *ptr != ',') {
709     if (!s)
710     s = ptr;
711     } else if (s) {
712     for (n = name; *n && *s && s < ptr &&
713     tolower((unsigned) *n) == tolower((unsigned) *s); n++, s++);
714    
715     if (s == ptr && !*n)
716     return 1;
717    
718     s = NULL;
719     }
720     } while (*ptr);
721    
722     return 0;
723     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23