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

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

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


Revision 1.20 - (hide annotations) (download) (as text)
Sun Mar 26 17:11:37 2000 UTC (19 years, 5 months ago) by guppy
Branch: MAIN
CVS Tags: eggdrop104030RC2, eggdrop10404, eggdrop10403, HEAD
Changes since 1.19: +1 -5 lines
File MIME type: text/x-chdr
RC2 me thinks

1 guppy 1.17 /*
2 segfault 1.1 * chanprog.c -- handles:
3 guppy 1.17 * 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     * config file format changed 27jan1994 (Tcl outdates that)
11 segfault 1.1 * dprintf'ized, 1nov1995
12 guppy 1.17 *
13 guppy 1.20 * $Id: chanprog.c,v 1.19 2000/01/08 21:23:13 per Exp $
14 segfault 1.1 */
15 guppy 1.17 /*
16     * Copyright (C) 1997 Robey Pointer
17 per 1.19 * Copyright (C) 1999, 2000 Eggheads
18 guppy 1.17 *
19     * This program is free software; you can redistribute it and/or
20     * modify it under the terms of the GNU General Public License
21     * as published by the Free Software Foundation; either version 2
22     * of the License, or (at your option) any later version.
23     *
24     * This program is distributed in the hope that it will be useful,
25     * but WITHOUT ANY WARRANTY; without even the implied warranty of
26     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27     * GNU General Public License for more details.
28     *
29     * You should have received a copy of the GNU General Public License
30     * along with this program; if not, write to the Free Software
31     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 segfault 1.1 */
33    
34     #include "main.h"
35     #if HAVE_GETRUSAGE
36     #include <sys/resource.h>
37     #if HAVE_SYS_RUSAGE_H
38     #include <sys/rusage.h>
39     #endif
40     #endif
41     #ifdef HAVE_UNAME
42     #include <sys/utsname.h>
43     #endif
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[];
50     extern char motdfile[], userfile[], helpdir[], tempdir[];
51     extern char moddir[], notify_new[], owner[], configfile[];
52     extern time_t now, online_since;
53     extern int backgrd, term_z, con_chan, cache_hit, cache_miss, firewallport;
54     extern int default_flags, max_logs, conmask, protect_readonly, make_userfile;
55     extern int noshare, ignore_time;
56    
57     tcl_timer_t *timer = NULL, *utimer = NULL; /* timers (minutely) and
58     * utimers (secondly) */
59     unsigned long timer_id = 1; /* next timer of any sort will have this
60     * number */
61     struct chanset_t *chanset = NULL; /* channel list */
62     char admin[121] = ""; /* admin info */
63     char origbotname[NICKLEN + 1];
64     char botname[NICKLEN + 1]; /* primary botname */
65    
66     /* remove space characters from beginning and end of string */
67     /* (more efficent by Fred1) */
68     void rmspace(char *s)
69     {
70     #define whitespace(c) ( ((c)==32) || ((c)==9) || ((c)==13) || ((c)==10) )
71     char *p;
72    
73 guppy 1.12 if (*s == '\0')
74     return;
75    
76 segfault 1.1 /* wipe end of string */
77     for (p = s + strlen(s) - 1; ((whitespace(*p)) && (p >= s)); p--);
78     if (p != s + strlen(s) - 1)
79     *(p + 1) = 0;
80     for (p = s; ((whitespace(*p)) && (*p)); p++);
81     if (p != s)
82     strcpy(s, p);
83     }
84    
85     /* returns memberfields if the nick is in the member list */
86     memberlist *ismember(struct chanset_t *chan, char *nick)
87     {
88     memberlist *x;
89    
90     x = chan->channel.member;
91 guppy 1.13 while (x && x->nick[0] && rfc_casecmp(x->nick, nick))
92 segfault 1.1 x = x->next;
93     if (!x->nick[0])
94     return NULL;
95     return x;
96     }
97    
98     /* find a chanset by channel name */
99     struct chanset_t *findchan(char *name)
100     {
101     struct chanset_t *chan = chanset;
102    
103     while (chan != NULL) {
104     if (!rfc_casecmp(chan->name, name))
105     return chan;
106     chan = chan->next;
107     }
108     return NULL;
109     }
110    
111     /* stupid "caching" functions */
112     /* shortcut for get_user_by_host -- might have user record in one
113     * of the channel caches */
114     struct userrec *check_chanlist(char *host)
115     {
116     char *nick, *uhost, buf[UHOSTLEN];
117     memberlist *m;
118     struct chanset_t *chan;
119    
120 guppy 1.9 strncpy(buf, host, UHOSTMAX);
121     buf[UHOSTMAX] = 0; /* why is this case sanely done, when there
122     * are so many others? */
123 segfault 1.1 uhost = buf;
124     nick = splitnick(&uhost);
125     for (chan = chanset; chan; chan = chan->next) {
126     m = chan->channel.member;
127 guppy 1.13 while (m && m->nick[0]) {
128 segfault 1.1 if (!rfc_casecmp(nick, m->nick) &&
129     !strcasecmp(uhost, m->userhost))
130     return m->user;
131     m = m->next;
132     }
133     }
134     return NULL;
135     }
136    
137     /* shortcut for get_user_by_handle -- might have user record in channels */
138     struct userrec *check_chanlist_hand(char *hand)
139     {
140     struct chanset_t *chan = chanset;
141     memberlist *m;
142    
143     while (chan) {
144     m = chan->channel.member;
145 guppy 1.13 while (m && m->nick[0]) {
146 segfault 1.1 if (m->user)
147     if (!strcasecmp(m->user->handle, hand))
148     return m->user;
149     m = m->next;
150     }
151     chan = chan->next;
152     }
153     return NULL;
154     }
155    
156     /* clear the user pointers in the chanlists */
157     /* (necessary when a hostmask is added/removed or a user is added) */
158     void clear_chanlist()
159     {
160     memberlist *m;
161     struct chanset_t *chan = chanset;
162    
163     while (chan) {
164     m = chan->channel.member;
165 guppy 1.13 while (m && m->nick[0]) {
166 segfault 1.1 m->user = NULL;
167     m = m->next;
168     }
169     chan = chan->next;
170     }
171     }
172    
173     /* if this user@host is in a channel, set it (it was null) */
174     void set_chanlist(char *host, struct userrec *rec)
175     {
176     char *nick, *uhost, buf[UHOSTLEN];
177     memberlist *m;
178     struct chanset_t *chan = chanset;
179    
180 guppy 1.15 Context;
181 guppy 1.14 strncpy(buf, host, UHOSTMAX);
182     buf[UHOSTMAX] = 0;
183 segfault 1.1 uhost = buf;
184     nick = splitnick(&uhost);
185     while (chan) {
186     m = chan->channel.member;
187 guppy 1.13 while (m && m->nick[0]) {
188 segfault 1.1 if (!rfc_casecmp(nick, m->nick) &&
189     !strcasecmp(uhost, m->userhost))
190     m->user = rec;
191     m = m->next;
192     }
193     chan = chan->next;
194     }
195     }
196    
197     /* memory we should be using */
198     int expmem_chanprog()
199     {
200     int tot;
201     tcl_timer_t *t;
202    
203 guppy 1.16 Context;
204 segfault 1.1 tot = 0;
205     for (t = timer; t; t = t->next) {
206     tot += sizeof(tcl_timer_t);
207     tot += strlen(t->cmd) + 1;
208     }
209     for (t = utimer; t; t = t->next) {
210     tot += sizeof(tcl_timer_t);
211     tot += strlen(t->cmd) + 1;
212     }
213     return tot;
214     }
215    
216     /* dump uptime info out to dcc (guppy 9Jan99) */
217 poptix 1.5 void tell_verbose_uptime(int idx)
218 segfault 1.1 {
219     char s[256], s1[121];
220     time_t now2, hr, min;
221    
222     now2 = now - online_since;
223     s[0] = 0;
224     if (now2 > 86400) {
225     /* days */
226     sprintf(s, "%d day", (int) (now2 / 86400));
227     if ((int) (now2 / 86400) >= 2)
228     strcat(s, "s");
229     strcat(s, ", ");
230     now2 -= (((int) (now2 / 86400)) * 86400);
231     }
232     hr = (time_t) ((int) now2 / 3600);
233     now2 -= (hr * 3600);
234     min = (time_t) ((int) now2 / 60);
235     sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
236     s1[0] = 0;
237     if (backgrd)
238     strcpy(s1, MISC_BACKGROUND);
239     else {
240     if (term_z)
241     strcpy(s1, MISC_TERMMODE);
242     else if (con_chan)
243     strcpy(s1, MISC_STATMODE);
244     else
245     strcpy(s1, MISC_LOGMODE);
246     }
247     dprintf(idx, "%s %s (%s)\n", MISC_ONLINEFOR, s, s1);
248     }
249    
250     /* dump status info out to dcc */
251 poptix 1.5 void tell_verbose_status(int idx)
252 segfault 1.1 {
253     char s[256], s1[121], s2[81];
254     char *vers_t, *uni_t;
255     int i;
256     time_t now2, hr, min;
257    
258     #if HAVE_GETRUSAGE
259     struct rusage ru;
260    
261     #else
262     #if HAVE_CLOCK
263     clock_t cl;
264    
265     #endif
266     #endif
267     #ifdef HAVE_UNAME
268     struct utsname un;
269    
270     if (!uname(&un) < 0) {
271     #endif
272     vers_t = " ";
273     uni_t = "*unknown*";
274     #ifdef HAVE_UNAME
275     } else {
276     vers_t = un.release;
277     uni_t = un.sysname;
278     }
279     #endif
280    
281     i = count_users(userlist);
282     dprintf(idx, "I am %s, running %s: %d user%s (mem: %uk)\n",
283 guppy 1.3 botnetnick, ver, i, i == 1 ? "" : "s",
284     (int) (expected_memory() / 1024));
285 segfault 1.1 dprintf(idx, "Running on %s %s\n", uni_t, vers_t);
286     if (admin[0])
287     dprintf(idx, "Admin: %s\n", admin);
288     now2 = now - online_since;
289     s[0] = 0;
290     if (now2 > 86400) {
291     /* days */
292     sprintf(s, "%d day", (int) (now2 / 86400));
293     if ((int) (now2 / 86400) >= 2)
294     strcat(s, "s");
295     strcat(s, ", ");
296     now2 -= (((int) (now2 / 86400)) * 86400);
297     }
298     hr = (time_t) ((int) now2 / 3600);
299     now2 -= (hr * 3600);
300     min = (time_t) ((int) now2 / 60);
301     sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
302     s1[0] = 0;
303     if (backgrd)
304     strcpy(s1, MISC_BACKGROUND);
305     else {
306     if (term_z)
307     strcpy(s1, MISC_TERMMODE);
308     else if (con_chan)
309     strcpy(s1, MISC_STATMODE);
310     else
311     strcpy(s1, MISC_LOGMODE);
312     }
313     #if HAVE_GETRUSAGE
314     getrusage(RUSAGE_SELF, &ru);
315     hr = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) / 60);
316     min = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) - (hr * 60));
317     sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min); /* actally min/sec */
318     #else
319     #if HAVE_CLOCK
320     cl = (clock() / CLOCKS_PER_SEC);
321     hr = (int) (cl / 60);
322     min = (int) (cl - (hr * 60));
323     sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min); /* actually min/sec */
324     #else
325     sprintf(s2, "CPU ???");
326     #endif
327     #endif
328     dprintf(idx, "%s %s (%s) %s %s %4.1f%%\n", MISC_ONLINEFOR,
329     s, s1, s2, MISC_CACHEHIT,
330     100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
331     strcpy(s, "info library");
332     if ((interp) && (Tcl_Eval(interp, s) == TCL_OK))
333     dprintf(idx, "%s %s\n", MISC_TCLLIBVER, interp->result);
334     }
335    
336     /* show all internal state variables */
337     void tell_settings(int idx)
338     {
339     char s[1024];
340     int i;
341     struct flag_record fr =
342     {FR_GLOBAL, 0, 0, 0, 0, 0};
343    
344     dprintf(idx, "Botnet Nickname: %s\n", botnetnick);
345     if (firewall[0])
346     dprintf(idx, "Firewall: %s, port %d\n", firewall, firewallport);
347     dprintf(idx, "Userfile: %s Motd: %s\n", userfile, motdfile);
348     dprintf(idx, "Directories:\n");
349     dprintf(idx, " Help : %s\n", helpdir);
350     dprintf(idx, " Temp : %s\n", tempdir);
351     #ifndef STATIC
352     dprintf(idx, " Modules : %s\n", moddir);
353     #endif
354     fr.global = default_flags;
355    
356     build_flags(s, &fr, NULL);
357     dprintf(idx, "%s [%s], %s: %s\n", MISC_NEWUSERFLAGS, s,
358     MISC_NOTIFY, notify_new);
359     if (owner[0])
360     dprintf(idx, "%s: %s\n", MISC_PERMOWNER, owner);
361     for (i = 0; i < max_logs; i++)
362     if (logs[i].filename != NULL) {
363     dprintf(idx, "Logfile #%d: %s on %s (%s: %s)\n", i + 1,
364     logs[i].filename, logs[i].chname,
365     masktype(logs[i].mask), maskname(logs[i].mask));
366     }
367     dprintf(idx, "Ignores last %d mins\n", ignore_time);
368     }
369    
370     void reaffirm_owners()
371     {
372     char *p, *q, s[121];
373     struct userrec *u;
374    
375     /* make sure default owners are +n */
376     if (owner[0]) {
377     q = owner;
378     p = strchr(q, ',');
379     while (p) {
380     strncpy(s, q, p - q);
381     s[p - q] = 0;
382     rmspace(s);
383     u = get_user_by_handle(userlist, s);
384     if (u)
385     u->flags = sanity_check(u->flags | USER_OWNER);
386     q = p + 1;
387     p = strchr(q, ',');
388     }
389     strcpy(s, q);
390     rmspace(s);
391     u = get_user_by_handle(userlist, s);
392     if (u)
393     u->flags = sanity_check(u->flags | USER_OWNER);
394     }
395     }
396    
397     void chanprog()
398     {
399     int i;
400    
401     admin[0] = 0;
402     helpdir[0] = 0;
403     tempdir[0] = 0;
404 guppy 1.7 for (i = 0; i < max_logs; i++)
405     logs[i].flags |= LF_EXPIRING;
406 segfault 1.1 conmask = 0;
407     /* turn off read-only variables (make them write-able) for rehash */
408     protect_readonly = 0;
409     /* now read it */
410 guppy 1.15 Context;
411 segfault 1.1 if (!readtclprog(configfile))
412     fatal(MISC_NOCONFIGFILE, 0);
413 guppy 1.7 for (i = 0; i < max_logs; i++) {
414     if (logs[i].flags & LF_EXPIRING) {
415     if (logs[i].filename != NULL) {
416     nfree(logs[i].filename);
417     logs[i].filename = NULL;
418     }
419     if (logs[i].chname != NULL) {
420     nfree(logs[i].chname);
421     logs[i].chname = NULL;
422     }
423     if (logs[i].f != NULL) {
424     fclose(logs[i].f);
425     logs[i].f = NULL;
426     }
427     logs[i].mask = 0;
428     logs[i].flags = 0;
429     }
430     }
431 segfault 1.1 /* We should be safe now */
432     call_hook(HOOK_REHASH);
433 guppy 1.15 Context;
434 segfault 1.1 protect_readonly = 1;
435     if (!userfile[0])
436     fatal(MISC_NOUSERFILE2, 0);
437     if ((int) getuid() == 0) {
438     /* perhaps you should make it run something innocent here ;)
439     * like rm -rf /etc :) */
440     printf("\n\n%s\n", MISC_ROOTWARN);
441     }
442     if (!readuserfile(userfile, &userlist)) {
443     if (!make_userfile)
444     fatal(MISC_NOUSERFILE, 0);
445 guppy 1.18 printf("\n\n%s\n", MISC_USERFCREATE);
446 segfault 1.1 if (module_find("server", 0, 0))
447     printf(MISC_USERFCREATE1, origbotname);
448     printf("%s\n\n", MISC_USERFCREATE2);
449 segfault 1.2 } else if (make_userfile) {
450     make_userfile = 0;
451 arthur2 1.10 printf("%s\n", MISC_USERFEXISTS);
452 segfault 1.2 }
453 guppy 1.15 Context;
454 segfault 1.1 if (helpdir[0])
455     if (helpdir[strlen(helpdir) - 1] != '/')
456     strcat(helpdir, "/");
457     if (tempdir[0])
458     if (tempdir[strlen(tempdir) - 1] != '/')
459     strcat(tempdir, "/");
460     if (!botnetnick[0]) {
461     strncpy(botnetnick, origbotname, HANDLEN);
462     botnetnick[HANDLEN] = 0;
463     }
464     if (!botnetnick[0])
465     fatal("I don't have a botnet nick!!\n", 0);
466 guppy 1.15 Context;
467 segfault 1.1 /* test tempdir: it's vital */
468     {
469     FILE *f;
470 poptix 1.6 char s[161], rands[8];
471 segfault 1.1
472 poptix 1.6 /* possible file race condition solved by using a random string
473     * and the process id in the filename */
474     make_rand_str(rands, 7); /* create random string */
475     sprintf(s, "%s.test-%u-%s", tempdir, getpid(), rands);
476 segfault 1.1 f = fopen(s, "w");
477     if (f == NULL)
478     fatal(MISC_CANTWRITETEMP, 0);
479     fclose(f);
480     unlink(s);
481     }
482 guppy 1.15 Context;
483 segfault 1.1 reaffirm_owners();
484     }
485    
486     /* reload the user file from disk */
487     void reload()
488     {
489     FILE *f;
490    
491     f = fopen(userfile, "r");
492     if (f == NULL) {
493     putlog(LOG_MISC, "*", MISC_CANTRELOADUSER);
494     return;
495     }
496     fclose(f);
497     noshare = 1;
498     clear_userlist(userlist);
499     noshare = 0;
500     userlist = NULL;
501     if (!readuserfile(userfile, &userlist))
502     fatal(MISC_MISSINGUSERF, 0);
503 guppy 1.15 Context;
504 segfault 1.1 reaffirm_owners();
505     call_hook(HOOK_READ_USERFILE);
506     }
507    
508     void rehash()
509     {
510 guppy 1.4 call_hook(HOOK_PRE_REHASH);
511 segfault 1.1 noshare = 1;
512     clear_userlist(userlist);
513     noshare = 0;
514     userlist = NULL;
515     chanprog();
516     }
517    
518     /* brief venture into timers */
519    
520     /* add a timer */
521     unsigned long add_timer(tcl_timer_t ** stack, int elapse, char *cmd,
522     unsigned long prev_id)
523     {
524     tcl_timer_t *old = (*stack);
525    
526     *stack = (tcl_timer_t *) nmalloc(sizeof(tcl_timer_t));
527     (*stack)->next = old;
528     (*stack)->mins = elapse;
529     (*stack)->cmd = (char *) nmalloc(strlen(cmd) + 1);
530     strcpy((*stack)->cmd, cmd);
531     /* if it's just being added back and already had an id,
532     * don't create a new one */
533     if (prev_id > 0)
534     (*stack)->id = prev_id;
535     else
536     (*stack)->id = timer_id++;
537     return (*stack)->id;
538     }
539    
540     /* remove a timer, by id */
541     int remove_timer(tcl_timer_t ** stack, unsigned long id)
542     {
543     tcl_timer_t *old;
544     int ok = 0;
545    
546     while (*stack) {
547     if ((*stack)->id == id) {
548     ok++;
549     old = *stack;
550     *stack = ((*stack)->next);
551     nfree(old->cmd);
552     nfree(old);
553     } else
554     stack = &((*stack)->next);
555     }
556     return ok;
557     }
558    
559     /* check timers, execute the ones that have expired */
560     void do_check_timers(tcl_timer_t ** stack)
561     {
562     tcl_timer_t *mark = *stack, *old = NULL;
563     char x[30];
564    
565     /* new timers could be added by a Tcl script inside a current timer */
566     /* so i'll just clear out the timer list completely, and add any
567     * unexpired timers back on */
568     *stack = NULL;
569     while (mark) {
570     if (mark->mins > 0)
571     mark->mins--;
572     old = mark;
573     mark = mark->next;
574     if (old->mins == 0) {
575     simple_sprintf(x, "timer%d", old->id);
576     do_tcl(x, old->cmd);
577     nfree(old->cmd);
578     nfree(old);
579     } else {
580     old->next = *stack;
581     *stack = old;
582     }
583     }
584     }
585    
586     /* wipe all timers */
587     void wipe_timers(Tcl_Interp * irp, tcl_timer_t ** stack)
588     {
589     tcl_timer_t *mark = *stack, *old;
590    
591     while (mark) {
592     old = mark;
593     mark = mark->next;
594     nfree(old->cmd);
595     nfree(old);
596     }
597     *stack = NULL;
598     }
599    
600     /* return list of timers */
601     void list_timers(Tcl_Interp * irp, tcl_timer_t * stack)
602     {
603     tcl_timer_t *mark = stack;
604     char mins[10], id[20], *argv[3], *x;
605    
606     while (mark != NULL) {
607     sprintf(mins, "%u", mark->mins);
608     sprintf(id, "timer%lu", mark->id);
609     argv[0] = mins;
610     argv[1] = mark->cmd;
611     argv[2] = id;
612     x = Tcl_Merge(3, argv);
613     Tcl_AppendElement(irp, x);
614 guppy 1.11 Tcl_Free((char *) x);
615 segfault 1.1 mark = mark->next;
616     }
617     }
618    
619     /* Oddly enough, written by proton (Emech's coder) */
620    
621     int isowner(char *name)
622     {
623     char *pa, *pb;
624     char nl, pl;
625    
626     if (!owner || !*owner)
627     return (0);
628     if (!name || !*name)
629     return (0);
630     nl = strlen(name);
631     pa = owner;
632     pb = owner;
633     while (1) {
634     while (1) {
635     if ((*pb == 0) || (*pb == ',') || (*pb == ' '))
636     break;
637     pb++;
638     }
639     pl = (unsigned int) pb - (unsigned int) pa;
640     if ((pl == nl) && (!strncasecmp(pa, name, nl)))
641     return (1);
642     while (1) {
643     if ((*pb == 0) || ((*pb != ',') && (*pb != ' ')))
644     break;
645     pb++;
646     }
647     if (*pb == 0)
648     return (0);
649     pa = pb;
650     }
651     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23