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

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

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


Revision 1.7 - (hide annotations) (download) (as text)
Wed Nov 10 21:35:02 1999 UTC (19 years, 9 months ago) by fabian
Branch: MAIN
Changes since 1.6: +4 -1 lines
File MIME type: text/x-chdr
Resync with 1.4

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23