/[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.1 - (show annotations) (download) (as text)
Mon Sep 13 14:36:18 1999 UTC (19 years, 10 months ago) by segfault
Branch: MAIN
File MIME type: text/x-chdr
Initial commit based off of .29 cvs

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 if (logs[i].filename != NULL) {
389 nfree(logs[i].filename);
390 logs[i].filename = NULL;
391 }
392 if (logs[i].chname != NULL) {
393 nfree(logs[i].chname);
394 logs[i].chname = NULL;
395 }
396 if (logs[i].f != NULL) {
397 fclose(logs[i].f);
398 logs[i].f = NULL;
399 }
400 logs[i].mask = 0;
401 }
402 conmask = 0;
403 /* turn off read-only variables (make them write-able) for rehash */
404 protect_readonly = 0;
405 /* now read it */
406 context;
407 if (!readtclprog(configfile))
408 fatal(MISC_NOCONFIGFILE, 0);
409 /* We should be safe now */
410 call_hook(HOOK_REHASH);
411 context;
412 protect_readonly = 1;
413 if (!userfile[0])
414 fatal(MISC_NOUSERFILE2, 0);
415 if ((int) getuid() == 0) {
416 /* perhaps you should make it run something innocent here ;)
417 * like rm -rf /etc :) */
418 printf("\n\n%s\n", MISC_ROOTWARN);
419 }
420 if (!readuserfile(userfile, &userlist)) {
421 if (!make_userfile)
422 fatal(MISC_NOUSERFILE, 0);
423 printf("\n\n%s\n", MISC_NOUSERFILE2);
424 if (module_find("server", 0, 0))
425 printf(MISC_USERFCREATE1, origbotname);
426 printf("%s\n\n", MISC_USERFCREATE2);
427 } else if (make_userfile) {
428 make_userfile = 0;
429 printf(MISC_USERFEXISTS);
430 readuserfile(userfile, &userlist);
431 }
432 context;
433 if (helpdir[0])
434 if (helpdir[strlen(helpdir) - 1] != '/')
435 strcat(helpdir, "/");
436 if (tempdir[0])
437 if (tempdir[strlen(tempdir) - 1] != '/')
438 strcat(tempdir, "/");
439 if (!botnetnick[0]) {
440 strncpy(botnetnick, origbotname, HANDLEN);
441 botnetnick[HANDLEN] = 0;
442 }
443 if (!botnetnick[0])
444 fatal("I don't have a botnet nick!!\n", 0);
445 context;
446 /* test tempdir: it's vital */
447 {
448 FILE *f;
449 char s[161];
450
451 /* FIXME: possible file race condition */
452 simple_sprintf(s, "%s.test.file", tempdir);
453 f = fopen(s, "w");
454 if (f == NULL)
455 fatal(MISC_CANTWRITETEMP, 0);
456 fclose(f);
457 unlink(s);
458 }
459 context;
460 reaffirm_owners();
461 }
462
463 /* reload the user file from disk */
464 void reload()
465 {
466 FILE *f;
467
468 f = fopen(userfile, "r");
469 if (f == NULL) {
470 putlog(LOG_MISC, "*", MISC_CANTRELOADUSER);
471 return;
472 }
473 fclose(f);
474 noshare = 1;
475 clear_userlist(userlist);
476 noshare = 0;
477 userlist = NULL;
478 if (!readuserfile(userfile, &userlist))
479 fatal(MISC_MISSINGUSERF, 0);
480 context;
481 reaffirm_owners();
482 call_hook(HOOK_READ_USERFILE);
483 }
484
485 void rehash()
486 {
487 call_hook(HOOK_PRE_REHASH);
488 noshare = 1;
489 clear_userlist(userlist);
490 noshare = 0;
491 userlist = NULL;
492 chanprog();
493 }
494
495 /* brief venture into timers */
496
497 /* add a timer */
498 unsigned long add_timer(tcl_timer_t ** stack, int elapse, char *cmd,
499 unsigned long prev_id)
500 {
501 tcl_timer_t *old = (*stack);
502
503 *stack = (tcl_timer_t *) nmalloc(sizeof(tcl_timer_t));
504 (*stack)->next = old;
505 (*stack)->mins = elapse;
506 (*stack)->cmd = (char *) nmalloc(strlen(cmd) + 1);
507 strcpy((*stack)->cmd, cmd);
508 /* if it's just being added back and already had an id,
509 * don't create a new one */
510 if (prev_id > 0)
511 (*stack)->id = prev_id;
512 else
513 (*stack)->id = timer_id++;
514 return (*stack)->id;
515 }
516
517 /* remove a timer, by id */
518 int remove_timer(tcl_timer_t ** stack, unsigned long id)
519 {
520 tcl_timer_t *old;
521 int ok = 0;
522
523 while (*stack) {
524 if ((*stack)->id == id) {
525 ok++;
526 old = *stack;
527 *stack = ((*stack)->next);
528 nfree(old->cmd);
529 nfree(old);
530 } else
531 stack = &((*stack)->next);
532 }
533 return ok;
534 }
535
536 /* check timers, execute the ones that have expired */
537 void do_check_timers(tcl_timer_t ** stack)
538 {
539 tcl_timer_t *mark = *stack, *old = NULL;
540 char x[30];
541
542 /* new timers could be added by a Tcl script inside a current timer */
543 /* so i'll just clear out the timer list completely, and add any
544 * unexpired timers back on */
545 context;
546 *stack = NULL;
547 while (mark) {
548 context;
549 if (mark->mins > 0)
550 mark->mins--;
551 old = mark;
552 mark = mark->next;
553 if (old->mins == 0) {
554 context;
555 simple_sprintf(x, "timer%d", old->id);
556 do_tcl(x, old->cmd);
557 nfree(old->cmd);
558 nfree(old);
559 } else {
560 context;
561 old->next = *stack;
562 *stack = old;
563 }
564 }
565 }
566
567 /* wipe all timers */
568 void wipe_timers(Tcl_Interp * irp, tcl_timer_t ** stack)
569 {
570 tcl_timer_t *mark = *stack, *old;
571
572 while (mark) {
573 old = mark;
574 mark = mark->next;
575 nfree(old->cmd);
576 nfree(old);
577 }
578 *stack = NULL;
579 }
580
581 /* return list of timers */
582 void list_timers(Tcl_Interp * irp, tcl_timer_t * stack)
583 {
584 tcl_timer_t *mark = stack;
585 char mins[10], id[20], *argv[3], *x;
586
587 while (mark != NULL) {
588 sprintf(mins, "%u", mark->mins);
589 sprintf(id, "timer%lu", mark->id);
590 argv[0] = mins;
591 argv[1] = mark->cmd;
592 argv[2] = id;
593 x = Tcl_Merge(3, argv);
594 Tcl_AppendElement(irp, x);
595 n_free(x, "", 0);
596 mark = mark->next;
597 }
598 }
599
600 /* Oddly enough, written by proton (Emech's coder) */
601
602 int isowner(char *name)
603 {
604 char *pa, *pb;
605 char nl, pl;
606
607 if (!owner || !*owner)
608 return (0);
609 if (!name || !*name)
610 return (0);
611 nl = strlen(name);
612 pa = owner;
613 pb = owner;
614 while (1) {
615 while (1) {
616 if ((*pb == 0) || (*pb == ',') || (*pb == ' '))
617 break;
618 pb++;
619 }
620 pl = (unsigned int) pb - (unsigned int) pa;
621 if ((pl == nl) && (!strncasecmp(pa, name, nl)))
622 return (1);
623 while (1) {
624 if ((*pb == 0) || ((*pb != ',') && (*pb != ' ')))
625 break;
626 pb++;
627 }
628 if (*pb == 0)
629 return (0);
630 pa = pb;
631 }
632 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23