/[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.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Wed Jun 23 19:51:26 1999 UTC (22 years, 4 months ago) by segfault
Branch: eggdev
CVS Tags: start
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Eggdrop 1.3.28 CVS Code

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23