/[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.43 - (show annotations) (download) (as text)
Thu Feb 7 22:19:04 2002 UTC (17 years, 5 months ago) by wcc
Branch: MAIN
Changes since 1.42: +2 -2 lines
File MIME type: text/x-chdr
Updated copyright info for 2002

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23