/[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.36 - (show annotations) (download) (as text)
Fri Oct 26 22:22:22 2001 UTC (17 years, 8 months ago) by stdarg
Branch: MAIN
Changes since 1.35: +1 -6 lines
File MIME type: text/x-chdr
* Converted the last few bind tables (I think).
* Removed unused builtin_* functions.

1 /*
2 * chanprog.c -- handles:
3 * rmspace()
4 * telling the current programmed settings
5 * initializing a lot of stuff and loading the tcl scripts
6 *
7 * $Id: chanprog.c,v 1.35 2001/10/19 01:55:04 tothwolf Exp $
8 */
9 /*
10 * Copyright (C) 1997 Robey Pointer
11 * Copyright (C) 1999, 2000, 2001 Eggheads Development Team
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include "main.h"
29 #if HAVE_GETRUSAGE
30 #include <sys/resource.h>
31 #if HAVE_SYS_RUSAGE_H
32 #include <sys/rusage.h>
33 #endif
34 #endif
35 #ifdef HAVE_UNAME
36 #include <sys/utsname.h>
37 #endif
38 #include "modules.h"
39
40 extern struct userrec *userlist;
41 extern Tcl_Interp *interp;
42 extern char ver[], botnetnick[], firewall[],
43 motdfile[], userfile[], helpdir[], tempdir[],
44 moddir[], notify_new[], owner[], configfile[];
45 extern time_t now, online_since;
46 extern int backgrd, term_z, con_chan, cache_hit, cache_miss,
47 firewallport, default_flags, conmask,
48 protect_readonly, make_userfile, noshare,
49 ignore_time;
50
51 struct chanset_t *chanset = NULL; /* Channel list */
52 char admin[121] = ""; /* Admin info */
53 char origbotname[NICKLEN + 1];
54 char botname[NICKLEN + 1]; /* Primary botname */
55
56
57 /* Remove space characters from beginning and end of string
58 * (more efficent by Fred1)
59 */
60 void rmspace(char *s)
61 {
62 #define whitespace(c) (((c) == 32) || ((c) == 9) || ((c) == 13) || ((c) == 10))
63 char *p;
64
65 if (*s == '\0')
66 return;
67
68 /* Wipe end of string */
69 for (p = s + strlen(s) - 1; ((whitespace(*p)) && (p >= s)); p--);
70 if (p != s + strlen(s) - 1)
71 *(p + 1) = 0;
72 for (p = s; ((whitespace(*p)) && (*p)); p++);
73 if (p != s)
74 strcpy(s, p);
75 }
76
77 /* Returns memberfields if the nick is in the member list.
78 */
79 memberlist *ismember(struct chanset_t *chan, char *nick)
80 {
81 register memberlist *x;
82
83 for (x = chan->channel.member; x && x->nick[0]; x = x->next)
84 if (!irccmp(x->nick, nick))
85 return x;
86 return NULL;
87 }
88
89 /* Find a chanset by channel name as the server knows it (ie !ABCDEchannel)
90 */
91 struct chanset_t *findchan(const char *name)
92 {
93 register struct chanset_t *chan;
94
95 for (chan = chanset; chan; chan = chan->next)
96 if (!irccmp(chan->name, name))
97 return chan;
98 return NULL;
99 }
100
101 /* Find a chanset by display name (ie !channel)
102 */
103 struct chanset_t *findchan_by_dname(const char *name)
104 {
105 register struct chanset_t *chan;
106
107 for (chan = chanset; chan; chan = chan->next)
108 if (!irccmp(chan->dname, name))
109 return chan;
110 return NULL;
111 }
112
113 /*
114 * "caching" functions
115 */
116
117 /* Shortcut for get_user_by_host -- might have user record in one
118 * of the channel caches.
119 */
120 struct userrec *check_chanlist(const char *host)
121 {
122 char *nick, *uhost, buf[UHOSTLEN];
123 register memberlist *m;
124 register struct chanset_t *chan;
125
126 strncpyz(buf, host, sizeof buf);
127 nick = strtok(buf, "!");
128 uhost = strtok(NULL, "!");
129 for (chan = chanset; chan; chan = chan->next)
130 for (m = chan->channel.member; m && m->nick[0]; m = m->next)
131 if (!irccmp(nick, m->nick) && !strcasecmp(uhost, m->userhost))
132 return m->user;
133 return NULL;
134 }
135
136 /* Shortcut for get_user_by_handle -- might have user record in channels
137 */
138 struct userrec *check_chanlist_hand(const char *hand)
139 {
140 register struct chanset_t *chan;
141 register memberlist *m;
142
143 for (chan = chanset; chan; chan = chan->next)
144 for (m = chan->channel.member; m && m->nick[0]; m = m->next)
145 if (m->user && !strcasecmp(m->user->handle, hand))
146 return m->user;
147 return NULL;
148 }
149
150 /* Clear the user pointers in the chanlists.
151 *
152 * Necessary when a hostmask is added/removed, a user is added or a new
153 * userfile is loaded.
154 */
155 void clear_chanlist(void)
156 {
157 register memberlist *m;
158 register struct chanset_t *chan;
159
160 for (chan = chanset; chan; chan = chan->next)
161 for (m = chan->channel.member; m && m->nick[0]; m = m->next)
162 m->user = NULL;
163 }
164
165 /* Clear the user pointer of a specific nick in the chanlists.
166 *
167 * Necessary when a hostmask is added/removed, a nick changes, etc.
168 * Does not completely invalidate the channel cache like clear_chanlist().
169 */
170 void clear_chanlist_member(const char *nick)
171 {
172 register memberlist *m;
173 register struct chanset_t *chan;
174
175 for (chan = chanset; chan; chan = chan->next)
176 for (m = chan->channel.member; m && m->nick[0]; m = m->next)
177 if (!irccmp(m->nick, nick)) {
178 m->user = NULL;
179 break;
180 }
181 }
182
183 /* If this user@host is in a channel, set it (it was null)
184 */
185 void set_chanlist(const char *host, struct userrec *rec)
186 {
187 char *nick, *uhost, buf[UHOSTLEN];
188 register memberlist *m;
189 register struct chanset_t *chan;
190
191 strncpyz(buf, host, sizeof buf);
192 nick = strtok(buf, "!");
193 uhost = strtok(NULL, "!");
194 for (chan = chanset; chan; chan = chan->next)
195 for (m = chan->channel.member; m && m->nick[0]; m = m->next)
196 if (!irccmp(nick, m->nick) && !strcasecmp(uhost, m->userhost))
197 m->user = rec;
198 }
199
200 /* Dump status info out to dcc
201 */
202 void tell_verbose_status(int idx)
203 {
204 char s[256], s1[121], s2[81];
205 char *vers_t, *uni_t;
206 int i;
207 time_t now2, hr, min;
208 #if HAVE_GETRUSAGE
209 struct rusage ru;
210 #else
211 # if HAVE_CLOCK
212 clock_t cl;
213 # endif
214 #endif
215 #ifdef HAVE_UNAME
216 struct utsname un;
217
218 if (!uname(&un) < 0) {
219 #endif
220 vers_t = " ";
221 uni_t = "*unknown*";
222 #ifdef HAVE_UNAME
223 } else {
224 vers_t = un.release;
225 uni_t = un.sysname;
226 }
227 #endif
228
229 i = count_users(userlist);
230 dprintf(idx, "I am %s, running %s: %d user%s\n",
231 botnetnick, ver, i, i == 1 ? "" : "s");
232 dprintf(idx, "Running on %s %s\n", uni_t, vers_t);
233 if (admin[0])
234 dprintf(idx, "Admin: %s\n", admin);
235 now2 = now - online_since;
236 s[0] = 0;
237 if (now2 > 86400) {
238 /* days */
239 sprintf(s, "%d day", (int) (now2 / 86400));
240 if ((int) (now2 / 86400) >= 2)
241 strcat(s, "s");
242 strcat(s, ", ");
243 now2 -= (((int) (now2 / 86400)) * 86400);
244 }
245 hr = (time_t) ((int) now2 / 3600);
246 now2 -= (hr * 3600);
247 min = (time_t) ((int) now2 / 60);
248 sprintf(&s[strlen(s)], "%02d:%02d", (int) hr, (int) min);
249 s1[0] = 0;
250 if (backgrd)
251 strcpy(s1, _("background"));
252 else {
253 if (term_z)
254 strcpy(s1, _("terminal mode"));
255 else if (con_chan)
256 strcpy(s1, _("status mode"));
257 else
258 strcpy(s1, _("log dump mode"));
259 }
260 #if HAVE_GETRUSAGE
261 getrusage(RUSAGE_SELF, &ru);
262 hr = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) / 60);
263 min = (int) ((ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) - (hr * 60));
264 sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min); /* Actally min/sec */
265 #else
266 # if HAVE_CLOCK
267 cl = (clock() / CLOCKS_PER_SEC);
268 hr = (int) (cl / 60);
269 min = (int) (cl - (hr * 60));
270 sprintf(s2, "CPU %02d:%02d", (int) hr, (int) min); /* Actually min/sec */
271 # else
272 sprintf(s2, "CPU ???");
273 # endif
274 #endif
275 dprintf(idx, "%s %s (%s) %s %s %4.1f%%\n", _("Online for"),
276 s, s1, s2, _("cache hit"),
277 100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
278
279 /* info library */
280 dprintf(idx, "%s %s\n", _("Tcl library:"),
281 ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
282 interp->result : "*unknown*");
283
284 /* info tclversion/patchlevel */
285 dprintf(idx, "%s %s (%s %s)\n", _("Tcl version:"),
286 ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
287 interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
288 interp->result : "*unknown*", _("header version"),
289 TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL : "*unknown*");
290
291 #if HAVE_TCL_THREADS
292 dprintf(idx, "Tcl is threaded\n");
293 #endif
294
295 }
296
297 /* Show all internal state variables
298 */
299 void tell_settings(int idx)
300 {
301 char s[1024];
302 int i;
303 struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
304
305 dprintf(idx, "Botnet Nickname: %s\n", botnetnick);
306 if (firewall[0])
307 dprintf(idx, "Firewall: %s, port %d\n", firewall, firewallport);
308 dprintf(idx, "Userfile: %s Motd: %s\n", userfile, motdfile);
309 dprintf(idx, "Directories:\n");
310 dprintf(idx, " Help : %s\n", helpdir);
311 dprintf(idx, " Temp : %s\n", tempdir);
312 #ifndef STATIC
313 dprintf(idx, " Modules : %s\n", moddir);
314 #endif
315 fr.global = default_flags;
316
317 build_flags(s, &fr, NULL);
318 dprintf(idx, "%s [%s], %s: %s\n", _("New users get flags"), s,
319 _("notify"), notify_new);
320 if (owner[0])
321 dprintf(idx, "%s: %s\n", _("Permanent owner(s)"), owner);
322 dprintf(idx, "Ignores last %d mins\n", ignore_time);
323 }
324
325 void reaffirm_owners()
326 {
327 char *p, *q, s[121];
328 struct userrec *u;
329
330 /* Make sure default owners are +n */
331 if (owner[0]) {
332 q = owner;
333 p = strchr(q, ',');
334 while (p) {
335 strncpyz(s, q, p - q);
336 rmspace(s);
337 u = get_user_by_handle(userlist, s);
338 if (u)
339 u->flags = sanity_check(u->flags | USER_OWNER);
340 q = p + 1;
341 p = strchr(q, ',');
342 }
343 strcpy(s, q);
344 rmspace(s);
345 u = get_user_by_handle(userlist, s);
346 if (u)
347 u->flags = sanity_check(u->flags | USER_OWNER);
348 }
349 }
350
351 void chanprog()
352 {
353 int i;
354
355 admin[0] = 0;
356 helpdir[0] = 0;
357 tempdir[0] = 0;
358 conmask = 0;
359 /* Turn off read-only variables (make them write-able) for rehash */
360 protect_readonly = 0;
361 /* Now read it */
362 if (!readtclprog(configfile))
363 fatal(_("CONFIG FILE NOT LOADED (NOT FOUND, OR ERROR)"), 0);
364 /* We should be safe now */
365 call_hook(HOOK_REHASH);
366 protect_readonly = 1;
367 if (!userfile[0])
368 fatal(_("STARTING BOT IN USERFILE CREATION MODE.\n\
369 Telnet to the bot and enter 'NEW' as your nickname."), 0);
370 if (!readuserfile(userfile, &userlist)) {
371 if (!make_userfile) {
372 char tmp[178];
373
374 snprintf(tmp, sizeof tmp, _("USER FILE NOT FOUND! (try ./eggdrop -m %s to make one)\n"), configfile);
375 fatal(tmp, 0);
376 }
377 printf(_("\n\nSTARTING BOT IN USERFILE CREATION MODE.\n\
378 Telnet to the bot and enter 'NEW' as your nickname.\n"));
379 if (module_find("server", 0, 0))
380 printf(_("OR Go to IRC and: /msg %s hello\n"), origbotname);
381 printf(_("This will make the bot recognize you as the master.\n\n"));
382 } else if (make_userfile) {
383 make_userfile = 0;
384 printf(_("USERFILE ALREADY EXISTS (drop the -m)\n"));
385 }
386 if (helpdir[0])
387 if (helpdir[strlen(helpdir) - 1] != '/')
388 strcat(helpdir, "/");
389 if (tempdir[0])
390 if (tempdir[strlen(tempdir) - 1] != '/')
391 strcat(tempdir, "/");
392 if (!botnetnick[0]) {
393 strncpyz(botnetnick, origbotname, HANDLEN + 1);
394 }
395 if (!botnetnick[0])
396 fatal("I don't have a botnet nick!!\n", 0);
397 /* Test tempdir: it's vital */
398 {
399 FILE *f;
400 char s[161], rands[8];
401
402 /* Possible file race condition solved by using a random string
403 * and the process id in the filename.
404 * FIXME: This race is only partitially fixed. We could still be
405 * overwriting an existing file / following a malicious
406 * link.
407 */
408 make_rand_str(rands, 7); /* create random string */
409 sprintf(s, "%s.test-%u-%s", tempdir, getpid(), rands);
410 f = fopen(s, "w");
411 if (f == NULL)
412 fatal(_("CANT WRITE TO TEMP DIR"), 0);
413 fclose(f);
414 unlink(s);
415 }
416 reaffirm_owners();
417 }
418
419 /* Reload the user file from disk
420 */
421 void reload()
422 {
423 FILE *f;
424
425 f = fopen(userfile, "r");
426 if (f == NULL) {
427 putlog(LOG_MISC, "*", _("Cant reload user file!"));
428 return;
429 }
430 fclose(f);
431 noshare = 1;
432 clear_userlist(userlist);
433 noshare = 0;
434 userlist = NULL;
435 if (!readuserfile(userfile, &userlist))
436 fatal(_("User file is missing!"), 0);
437 reaffirm_owners();
438 call_hook(HOOK_READ_USERFILE);
439 }
440
441 void rehash()
442 {
443 call_hook(HOOK_PRE_REHASH);
444 noshare = 1;
445 clear_userlist(userlist);
446 noshare = 0;
447 userlist = NULL;
448 chanprog();
449 }
450
451 /* Oddly enough, written by proton (Emech's coder)
452 */
453 int isowner(char *name)
454 {
455 char *pa, *pb;
456 char nl, pl;
457
458 if (!owner || !*owner)
459 return (0);
460 if (!name || !*name)
461 return (0);
462 nl = strlen(name);
463 pa = owner;
464 pb = owner;
465 while (1) {
466 while (1) {
467 if ((*pb == 0) || (*pb == ',') || (*pb == ' '))
468 break;
469 pb++;
470 }
471 pl = (unsigned int) pb - (unsigned int) pa;
472 if (pl == nl && !strncasecmp(pa, name, nl))
473 return (1);
474 while (1) {
475 if ((*pb == 0) || ((*pb != ',') && (*pb != ' ')))
476 break;
477 pb++;
478 }
479 if (*pb == 0)
480 return (0);
481 pa = pb;
482 }
483 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23