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

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

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


Revision 1.20 - (show annotations) (download) (as text)
Sun Mar 26 17:11:37 2000 UTC (19 years, 3 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 /*
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 * config file format changed 27jan1994 (Tcl outdates that)
11 * dprintf'ized, 1nov1995
12 *
13 * $Id: chanprog.c,v 1.19 2000/01/08 21:23:13 per Exp $
14 */
15 /*
16 * Copyright (C) 1997 Robey Pointer
17 * Copyright (C) 1999, 2000 Eggheads
18 *
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 */
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 if (*s == '\0')
74 return;
75
76 /* 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 while (x && x->nick[0] && rfc_casecmp(x->nick, nick))
92 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 strncpy(buf, host, UHOSTMAX);
121 buf[UHOSTMAX] = 0; /* why is this case sanely done, when there
122 * are so many others? */
123 uhost = buf;
124 nick = splitnick(&uhost);
125 for (chan = chanset; chan; chan = chan->next) {
126 m = chan->channel.member;
127 while (m && 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 && 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 && 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 strncpy(buf, host, UHOSTMAX);
182 buf[UHOSTMAX] = 0;
183 uhost = buf;
184 nick = splitnick(&uhost);
185 while (chan) {
186 m = chan->channel.member;
187 while (m && m->nick[0]) {
188 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 Context;
204 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 void tell_verbose_uptime(int idx)
218 {
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 void tell_verbose_status(int idx)
252 {
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 botnetnick, ver, i, i == 1 ? "" : "s",
284 (int) (expected_memory() / 1024));
285 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 for (i = 0; i < max_logs; i++)
405 logs[i].flags |= LF_EXPIRING;
406 conmask = 0;
407 /* turn off read-only variables (make them write-able) for rehash */
408 protect_readonly = 0;
409 /* now read it */
410 Context;
411 if (!readtclprog(configfile))
412 fatal(MISC_NOCONFIGFILE, 0);
413 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 /* We should be safe now */
432 call_hook(HOOK_REHASH);
433 Context;
434 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 printf("\n\n%s\n", MISC_USERFCREATE);
446 if (module_find("server", 0, 0))
447 printf(MISC_USERFCREATE1, origbotname);
448 printf("%s\n\n", MISC_USERFCREATE2);
449 } else if (make_userfile) {
450 make_userfile = 0;
451 printf("%s\n", MISC_USERFEXISTS);
452 }
453 Context;
454 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 Context;
467 /* test tempdir: it's vital */
468 {
469 FILE *f;
470 char s[161], rands[8];
471
472 /* 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 f = fopen(s, "w");
477 if (f == NULL)
478 fatal(MISC_CANTWRITETEMP, 0);
479 fclose(f);
480 unlink(s);
481 }
482 Context;
483 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 Context;
504 reaffirm_owners();
505 call_hook(HOOK_READ_USERFILE);
506 }
507
508 void rehash()
509 {
510 call_hook(HOOK_PRE_REHASH);
511 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 Tcl_Free((char *) x);
615 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