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

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

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


Revision 1.3 - (show annotations) (download) (as text)
Fri Oct 15 10:44:57 1999 UTC (19 years, 9 months ago) by fabian
Branch: MAIN
Changes since 1.2: +0 -1 lines
File MIME type: text/x-chdr
resync 1.3: 939574072->939863113

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23