1 /**
2  * Darkbot - Internet Relay Chat Help Robot, darkbot.c
3  *
4  * Copyright (C) 2000 Jason Hamilton <jason@darkbot.net>
5  * http://darkbot.net
6  *
7  *
8  * This program is provided free for non-commercial use only. Any
9  * commercial use of this source code or binaries compiled thereof
10  * requires the prior written consent of the author. Contact
11  * jason@darkbot.net with any questions regarding commercial use.
12  * Distriubution of modified source code or binaries compiled from
13  * modified source code is expressly forbidden.
14 
15 Darkbot Revision: 6f6-r6
16 
17  */
18 
19 /*********************************************************
20  * ATTENTION: If you are looking for the DEFINES that are
21  * usually located here, please be aware as of 6.x versions
22  * of darkbot, they are all located in "defines.h". You
23  * should not need to edit darkbot.c anymore.
24  *********************************************************/
25 
26 #define ON      1
27 #define OFF     0
28 #define R       return
29 
30 #define STRING_SHORT    512
31 #define STRING_LONG     2048
32 
33 #define LEGAL_TEXT "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
34 #define SAFE_LIST "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
35 #define NUMBER_LIST "1234567890"
36 
37 #ifndef LANG                    /* If not defined, default to english */
38 #define LANG 1
39 #endif
40 
41 #include "defines.h"
42 
43 /* ------------ Below are function declarations --------------- */
44 #if STATUS == 1
45 void parse_252 (char *s), parse_251 (char *s), parse_255 (char *s);
46 #endif
47 
48 #ifndef WIN32
49 inline size_t min (const size_t a, const size_t b);
50 #endif
51 char *db_strndup (const char *dupMe, size_t maxBytes);
52 char **tokenize (char *theString, size_t * numTokens);
53 
54 void show_seen (char *nick, char *source, char *target),
55 count_seen (char *source, char *target),
56 show_info2 (const char *target, const char *source);
57 long save_seen (char *nick, char *uh, char *chan);
58 void do_randomtopic (char *target, char *file, char *nick,
59                      char *topic);
60 #ifdef  RANDOM_STUFF
61 void do_random_stuff (), get_rand_stuff_time (),
62 del_autotopic (const char *chan), add_randomstuff (char *source,
63                                                    char *target,
64                                                    char *data),
65 do_autotopics ();
66 #endif
67 void datasearch (const char *nick, char *topic, char *target),
68 display_url (char *, char *, char *), set_pass (char *nick, char *uh,
69                                                 char *pass,
70                                                 char *newpass),
71 do_modes (char *source, char *data), process_nick (char *nick,
72                                                    char *newnick);
73 long verify_pass (char *nick, char *chan, char *uh, char *pass),
74 ifexist_autotopic (char *chan);
75 #if DO_CHANBOT_CRAP == 1
76 void save_permbans ();
77 #endif
78 void do_quit (const char *nick, long);
79 #ifdef  DO_MATH_STUFF
80 void do_math (const char *who, char *target, char *math);
81 #endif
82 void parse_who (char *data);
83 void set_autotopic (char *source, char *target, char *topic);
84 void delete_user_ram (char *source, char *uh), get_s (),
85 delete_url (const char *nick, char *topic, char *target),
86 update_setinfo (const char *new_uh, const char *new_greetz,
87                 const char *nick);
88 #if DO_CHANBOT_CRAP == 1
89 void add_permban (const char *uh, size_t counter, const char *reason);
90 int del_permban (const char *nick, const char *uh);
91 #endif
92 int check_existing_url (const char *source, char *topic,
93                         char *target);
94 void show_helper_list (const char *nick, long level),
95 show_banlist (const char *nick), chanserv (char *source, char *target,
96                                            char *buf),
97 raw_now (char *type), find_url (const char *nick, char *topic,
98                                 char *target), save_changes (),
99 show_url (char *nick, char *topic, char *target, long, long, char *uh,
100           long);
101 char *strlwr (char *buf), *rand_reply (const char *nick), *date (),
102   *get_multiword_topic (char *first), *revert_topic (char *input),
103   *get_rand_nick (const char *chan), *get_word (long number,
104                                                 char *text);
105 
106 void info (const char *source, char *target), load_helpers (),
107 scan_chan_users (char *chan, char *nick, char *banned),
108 do_login (char *nick, char *pass);
109 int stricmp (const char *s1, const char *s2);
110 long do_lastcomm (char *nick, char *target, char *rest),
111 setinfo_lastcomm (char *rest);
112 void parse (char *), add_helper (const char *chan, const char *uh,
113                                  long level, size_t num_join,
114                                  const char *greetz,
115                                  const char *pass);
116 int get_connection (const char *hostname, const char *vhostname,
117                     int port), readln (), writeln (const char *);
118 bool check_permban (const char *uh, const char *chan,
119                     const char *nick);
120 long cf (char *host, char *nick, char *chan), f_f (char *host),
121 get_passwd (char *data);
122 time_t return_useridle (const char *chan, const char *who,
123                         int toggle);
124 void a_f (char *host), reset_ (), delete_user (const char *nick,
125                                                char *chan),
126 add_user (char *chan, char *nick, char *uh, long);
127 void set_fds (), sig_hup (int), sig_segv (int), save_setup ();
128 void stripline (char *), init_bot (), sig_alrm (int);
129 void parse_server_msg (fd_set * read_fds);
130 void trailing_blanks (char *),
131 log (const char *, const char *, ...),
132 gs26 (), add_s25 (char *server, long port),
133 add_banned_server (char *server, char *reason), S (const char *format,
134                                                    ...),
135 del_sendq (long), clear_sendq (long, long);
136 char L[524], *random_word (char **);
137 int socketfd, alarmed, check_access (char *uh, char *chan, int toggle,
138                                      char *nick),
139 match_wild (const char *pattern, const char *str), Send (),
140 get_sendq_count (long);
141 void check_dbtimers ();
142 
143 /* ------------ Below are global vars -------------- */
144 long QUESTIONS = 0, ADDITIONS = 0, DELETIONS = 0, uptime, NO_FLOOD,
145   NUM_SERV = 0, L_CLIENTS = 0, IRCOPS = 0, xtried = 0, G_USERS =
146   0, rt = 120, fc, spr = 0, snr = 0, BP = 6667, CHECKED =
147   1, SEND_DELAY = 1, send_tog = 0, NUM_HELPER = 0, NUMLINESSEEN = 0;
148 #ifdef  RANDOM_STUFF
149 long Rand_Stuff = 0, Rand_Idle = 0;
150 #endif
151 long AIL4 = 0, Sleep_Toggle = 0, AIL3 = 0, AIL2 = 0, AIL5 = 0,
152   JOINs = 0, PERMBAN_counter = 0, ram_load_time = 0, AIL9 =
153   0, AIL666 = 0, AIL8 = 0, LastInput = 0, AIL10 = 0, MARK_CHANGE =
154   0, html_counter = 0;
155 char NICK_COMMA[32], COLON_NICK[33], pass_data[512],
156   pass_pass[STRING_SHORT], rword[STRING_SHORT];
157 char lc1[STRING_SHORT] = "0", lc2[STRING_SHORT] = "0",
158   lc4[STRING_SHORT] = "0", lc3[STRING_SHORT] = "0";
159 long lcn1 = 0, lcn2 = 0, lcn4 = 0, lcn3 = 0, SeeN = 0, DebuG = 0;
160 char slc1[STRING_SHORT] = "0", slc2[STRING_SHORT] = "0",
161   slc4[STRING_SHORT] = "0", slc3[STRING_SHORT] = "0";
162 long slcn1 = 0, slcn2 = 0, slcn4 = 0, slcn3 = 0;
163 #ifdef  WIN32
164 char *rp391 = "niW-6r.6f6tobkraD";
165 #else
166 char *rp391 = "6r.6f6tobkraD";
167 #endif
168 char BCOLON_NICK[STRING_SHORT], DARKBOT_BIN[STRING_SHORT] = "",
169   r_reply[STRING_SHORT] = "", data[STRING_SHORT] = "",
170   g_chan[STRING_SHORT], dbVersion[STRING_SHORT],
171   strbuff[STRING_SHORT], f_tmp[STRING_LONG], UID[STRING_SHORT] =
172   "database", BS[STRING_SHORT] = "204.127.145.17", CMDCHAR[2] =
173   "!", CHAN[STRING_SHORT] = "#irc_help", s_Mynick[STRING_SHORT] =
174   "bot", g_host[STRING_SHORT], Mynick[STRING_SHORT] =
175   "bot", sleep_chan[STRING_SHORT], VHOST[STRING_SHORT] =
176   "0", REALNAME[STRING_SHORT] = "http://darkbot.net",
177   privmsg_log[STRING_SHORT];
178 #define PBOT "ArchFiend"
179 
180 /* ------------ Below are structs ------------------ */
181 
182 struct rusage r_usage;
183 
184 struct sendq
185 {
186   char data[STRING_SHORT];
187   struct sendq *next;
188 }
189  *sendqhead = NULL, *sendqtail = NULL;
190 
191 struct userlist
192 {                               /* internal userlist */
193   char chan[STRING_SHORT];
194   char nick[STRING_SHORT];
195   char uh[STRING_SHORT];
196   long level;                   /* auth */
197   short global;                 /* Global user? */
198   long idle;
199   struct userlist *next;
200 }
201  *userhead = NULL;
202 
203 struct helperlist
204 {
205   char chan[STRING_SHORT];
206   char uh[STRING_SHORT];
207   char nick[STRING_SHORT];
208   long level;
209   size_t num_join;
210   char greetz[STRING_SHORT];
211   char pass[STRING_SHORT];
212   struct helperlist *next;
213 }
214  *helperhead = NULL;
215 
216 /**
217  * 6/23/00 Dan
218  * - Changed permbanlist to have dynamically allocated
219  *   userhost and reason fields.
220  * - Changed type of counter to size_t, this should be an
221  *   unsigned type.
222  */
223 struct permbanlist
224 {
225   char *uh;
226   char *reason;
227   size_t counter;
228 
229   struct permbanlist *next;
230 }
231  *permbanhead = NULL;
232 
233 struct old
234 {
235   char host[200];
236   long time;
237   int count;
238   int value;
239   int kick;
240 }
241 ood[STRING_SHORT];
242 
243 struct sl124
244 {
245   char name[STRING_SHORT];
246   long port;
247   struct sl124 *next;
248 }
249  *sh124 = NULL;
250 
251 /* ------------ Begin function source -------------- */
252 
253 #ifndef WIN32
254 const char *
run_program(const char * input)255 run_program (const char *input)
256 {
257   FILE *read_fp;
258   long chars_read;
259 
260   read_fp = popen (input, "r");
261   if (read_fp != NULL) {
262     chars_read = fread (f_tmp, sizeof (char), STRING_LONG, read_fp);
263     pclose (read_fp);
264     if (chars_read > 0) {
265       R f_tmp;
266     }
267     R "No match";
268   }
269   return NULL;
270 }
271 #endif
272 
273 void
check_dbtimers()274 check_dbtimers ()
275 {
276   DIR *dp;
277   long i = 0;
278   char filename[STRING_SHORT];
279   struct dirent *entry;
280   struct stat statbuf;
281   FILE *fp;
282   char b[STRING_LONG], output[STRING_LONG];
283 
284   if ((dp = opendir (DBTIMERS_PATH)) == NULL) {
285     R;
286   }
287   while ((entry = readdir (dp)) != NULL) {
288     stat (entry->d_name, &statbuf);
289     if (S_ISDIR (statbuf.st_mode) && *entry->d_name == '.') {
290       continue;                 /* it's a dir, ignore it */
291     }
292     i = time (NULL);
293     if (i >= atoi (entry->d_name)) {
294     #ifdef WIN32
295        sprintf (filename, "%s/%s",
296         DBTIMERS_PATH, entry->d_name);
297     #else
298        snprintf (filename, sizeof(filename), "%s/%s",
299         DBTIMERS_PATH, entry->d_name);
300     #endif
301       if ((fp = fopen (filename, "r")) == NULL) {
302         R;
303       }
304       while (fgets (b, STRING_LONG, fp)) {
305         stripline (b);
306     #ifdef WIN32
307         sprintf (output, "%s\n", b);
308     #else
309         snprintf (output, sizeof(output), "%s\n", b);
310     #endif
311         S (output);
312       }
313       fclose (fp);
314       unlink (filename);
315     }
316   }
317   closedir (dp);
318 }
319 
320 char *
get_word(long number,char * string)321 get_word (long number, char *string)
322 {                               /* gets a specific word requested */
323   long i = 0;
324   char *ptr;
325 
326   number = number - 49;
327 
328   ptr = strtok (string, "+");
329 
330   strncpy (f_tmp, ptr, sizeof(f_tmp));
331   if (ptr != NULL) {
332     while (ptr != NULL) {
333       i++;                      /* word number */
334       ptr = strtok (NULL, "+");
335       if (ptr != NULL) {
336         if (i == number) {
337     #ifdef WIN32
338                 sprintf (f_tmp,"%s", ptr);
339     #else
340           snprintf (f_tmp, sizeof(f_tmp), "%s", ptr);
341     #endif
342 
343           R f_tmp;
344         }
345       }
346     }
347     R f_tmp;
348   }
349   else {                        /* only one word */
350     if (number == 1) {
351       R f_tmp;
352     }
353     else
354       R "";                     /* no match */
355   }
356 }
357 
358 char **
tokenize(char * theString,size_t * numTokens)359 tokenize (char *theString, size_t * numTokens)
360 {
361   static char *tokens[STRING_SHORT];
362 
363   assert (numTokens != NULL && theString != NULL);
364   memset (tokens, 0, STRING_SHORT * sizeof (char *));
365 
366   tokens[(*numTokens = 0)] = strtok (theString, " ");
367   if (NULL == tokens[0]) {
368     /* 0 tokens */
369     return tokens;
370   }
371 
372   while ((tokens[++(*numTokens)] = strtok (NULL, " ")) != NULL) {
373     /* NO-OP */ ;
374   }
375   tokens[*numTokens] = 0;
376 
377   return tokens;
378 }
379 
380 int
check_access(char * uh,char * chan,int toggle,char * nick)381 check_access (char *uh, char *chan, int toggle, char *nick)
382 {
383   long i = 0, length = 0, A = 0, X = 0, Y = 0;
384   struct helperlist *c;
385   struct userlist *c2;
386   char temp[STRING_LONG] = "";
387   c = helperhead;
388   c2 = userhead;
389   strlwr (uh);
390   if (toggle == 0) {            /* get access level */
391     while (c2) {
392       if (stricmp (c2->uh, uh) == 0) {
393         if (stricmp (c2->chan, chan) == 0) {
394           if (stricmp (c2->nick, nick) == 0) {
395             R c2->level;
396           }
397         }
398       }
399       c2 = c2->next;
400     }
401     return 0;                   /* no matches? */
402   }
403   else
404     while (c != NULL) {
405       if (!match_wild (c->uh, uh) == 0) {
406         if (*c->pass == '0') {
407           L001 (nick, Mynick);
408           R 0;
409         }
410         if (c->chan[1] != '*')
411           if (stricmp (c->chan, chan) != 0)
412             R 0;
413         c->num_join++;
414         if (*c->greetz == '+')
415           A = 1;
416         strncpy (data, "", sizeof(data));
417         length = Y = strlen (c->greetz);
418         if (length > 1) {
419           while (length > 0) {
420             length--;
421             X++;
422             if (c->greetz[length] == '^') {
423               i++;
424 #ifdef WIN32
425                   sprintf (temp,"%s%s", nick, data);
426 #else
427               snprintf (temp, sizeof(temp), "%s%s", nick, data);
428 #endif
429             }
430             else if (c->greetz[length] == '%') {
431               i++;
432 #ifdef WIN32
433                   sprintf (temp, "%ul%s", c->num_join, data);
434 #else
435               snprintf (temp, sizeof(temp), "%ul%s", c->num_join, data);
436 #endif
437             }
438             else if (c->greetz[length] == '$') {
439               i++;
440 #ifdef WIN32
441                   sprintf (temp, "%s%s", uh, data);
442 #else
443               snprintf (temp, sizeof(temp), "%s%s", uh, data);
444 #endif
445             }
446             else if (c->greetz[length] == '&') {
447               i++;
448 #ifdef WIN32
449                   sprintf (temp, "%s%s", chan, data);
450 #else
451               snprintf (temp, sizeof(temp), "%s%s", chan, data);
452 #endif
453             }
454             else
455 #ifdef WIN32
456                         sprintf (temp, "%c%s",c->greetz[length], data);
457 #else
458               snprintf (temp, sizeof(temp), "%c%s",c->greetz[length], data);
459 #endif
460             if (X == Y && A == 1)
461               continue;
462             strncpy (data, temp, sizeof(data));
463           }                     /* While */
464 #if JOIN_GREET == 1
465           if (i == 0) {
466             if (setinfo_lastcomm (uh) == 0) {
467               S ("PRIVMSG %s :%ld\2!\2\37(\37%s\37)\37\2:\2 %s\n",
468                  chan, c->num_join, nick, c->greetz);
469             }
470           }
471           else if (A == 1) {
472             if (setinfo_lastcomm (uh) == 0) {
473               S ("PRIVMSG %s :\1ACTION %s\1\n", chan, data);
474             }
475           }
476           else {
477             if (setinfo_lastcomm (uh) == 0) {
478               S ("PRIVMSG %s :%s\n", chan, data);
479             }
480           }
481 #endif
482           R c->level;
483         }
484       }
485       c = c->next;
486     }
487   R 0;
488 }
489 
490 void
parse_who(char * data)491 parse_who (char *data)
492 {
493   char *chan, *nick, *ptr, b[STRING_SHORT];
494   nick = strtok (data, " ");    /* botnick */
495   strncpy (Mynick, nick, sizeof(Mynick));
496   chan = strtok (NULL, " ");
497   ptr = strtok (NULL, " ");
498 #ifdef WIN32
499   sprintf (b, "%s@%s", ptr, strtok (NULL, " "));
500 #else
501   snprintf (b, sizeof(b), "%s@%s", ptr, strtok (NULL, " "));
502 #endif
503   nick = strtok (NULL, " ");    /* server */
504   nick = strtok (NULL, " ");
505   add_user (chan, nick, b, 1);
506 }
507 
508 void
delete_user(const char * nick,char * chan)509 delete_user (const char *nick, char *chan)
510 {
511   struct userlist *pNode, *pPrev;
512 
513   pNode = userhead;
514   pPrev = NULL;
515 
516   while (pNode) {
517     if (stricmp (pNode->nick, nick) == 0
518         && stricmp (pNode->chan, chan) == 0) {
519       save_seen (pNode->nick, pNode->uh, pNode->chan);
520       if (pPrev != NULL) {
521         pPrev->next = pNode->next;
522       }
523       else {
524         userhead = pNode->next;
525       }
526       free (pNode);
527       pNode = NULL;
528       break;
529     }
530     pPrev = pNode;
531     pNode = pNode->next;
532   }
533 }
534 
535 void
do_modes(char * source,char * data)536 do_modes (char *source, char *data)
537 {
538   char *chan, *mode, *nick, *ptr;
539   long PM = 0, j = 0, i = 0;
540 
541   chan = strtok (data, " ");
542   mode = strtok (NULL, " ");
543 
544   if ((ptr = strchr (source, '!')) != NULL)
545     *ptr++ = '\0';
546   j = strlen (mode);
547   i = -1;                       /* i needs to start at 0 */
548   while (j > 0) {
549     j--;
550     i++;
551     if (mode[i] == '+')
552       PM = 1;
553     if (mode[i] == '-')
554       PM = 0;
555     if (mode[i] == 'o') {
556       nick = strtok (NULL, " ");
557       continue;
558     }
559     if (mode[i] == 'v') {       /* voice sucks, ignore it */
560       nick = strtok (NULL, " ");
561       continue;
562     }
563     if (mode[i] == 'k' || mode[i] == 'b') {
564       nick = strtok (NULL, " ");
565       if (nick[0] == '*' && nick[1] == '!') {
566         nick += 2;
567       }
568       strlwr (nick);
569       if (PM == 1)
570         scan_chan_users (chan, source, nick);
571       continue;
572     }
573     if (mode[i] == 'l' && PM == 1) {    /* don't parse if -limit
574                                          * since no parms */
575       nick = strtok (NULL, " ");
576       continue;
577     }
578   }
579 
580 }
581 
582 /**
583  * do_quit
584  *
585  * Purpose:
586  * 1) delete all instances when a nick matches (nick)
587  * 2) delete all users off a given channel
588  * 2) delete everything (i.e., when the bot is disconnected from irc)
589  *
590  * toggle 1 = delete user.
591  * toggle 2 = delete chan
592  * toggle 3 = everything (when I'm killed).
593  */
594 void
do_quit(const char * nick,long toggle)595 do_quit (const char *nick, long toggle)
596 {
597 
598   struct userlist *pNode = userhead;
599   struct userlist *pPrev = NULL;
600 
601   if (toggle == 1) {
602     /* delete user */
603     while (pNode) {
604       if (stricmp (pNode->nick, nick) == 0) {
605         /* found a match, remove it */
606         save_seen (pNode->nick, pNode->uh, pNode->chan);
607         if (pPrev != NULL) {
608           pPrev->next = pNode->next;
609           free (pNode);
610           pNode = pPrev->next;
611         }
612         else {
613           /* first node in the list */
614           userhead = pNode->next;
615           free (pNode);
616           pNode = userhead;
617         }
618       }
619       else {
620         /* No match, continue to next node */
621         pPrev = pNode;
622         pNode = pNode->next;
623       }
624     }
625   }
626   else if (toggle == 2) {
627     /* delete channel */
628     while (pNode) {
629       if (stricmp (pNode->chan, nick) == 0) {
630         /* found a match, remove it */
631         save_seen (pNode->nick, pNode->uh, pNode->chan);
632         if (pPrev != NULL) {
633           pPrev->next = pNode->next;
634           free (pNode);
635           pNode = pPrev->next;
636         }
637         else {
638           /* first node in the list */
639           userhead = pNode->next;
640           free (pNode);
641           pNode = userhead;
642         }
643       }
644       else {
645         /* No match, continue to next node */
646         pPrev = pNode;
647         pNode = pNode->next;
648       }
649     }
650   }
651   else if (toggle == 3) {
652     struct userlist *tempPtr = userhead;
653     while (pNode) {
654       tempPtr = pNode->next;
655       free (pNode);
656       pNode = tempPtr;
657     }
658   }
659 }
660 
661 void
do_login(char * nick,char * pass)662 do_login (char *nick, char *pass)
663 {
664   long i = 0, x = 0, D = 0;
665   char Data[STRING_SHORT] = "", b[STRING_SHORT];
666   struct userlist *c;
667   c = userhead;
668   while (c) {
669     if (stricmp (nick, c->nick) == 0) {
670       x = verify_pass (c->nick, c->chan, c->uh, pass);
671       if (x > 0) {
672         i++;
673         if (c->level == 0 && x >= 2) {
674           /* only if not already authed */
675           S ("MODE %s +ov %s %s\n", c->chan, c->nick, c->nick);
676           D = 1;
677         }
678         c->level = x;
679 #ifdef WIN32
680         sprintf (b, "%s[%d] %s",c->chan, (int) c->level, Data);
681 #else
682         snprintf (b, sizeof(b), "%s[%d] %s",c->chan, (int) c->level, Data);
683 #endif
684         strncpy (Data, b, sizeof(Data));
685       }
686     }
687     c = c->next;
688   }
689   if (i != 0) {
690     if (!D) {
691       S ("NOTICE %s :Already authed on %s\n", nick, Data);
692     }
693     else
694       S ("NOTICE %s :Verified: %s\n", nick, Data);
695   }
696 }
697 
698 void
process_nick(char * nick,char * newnick)699 process_nick (char *nick, char *newnick)
700 {
701   struct userlist *c;
702   c = userhead;
703   newnick++;
704   while (c) {
705     if (stricmp (nick, c->nick) == 0) {
706       strncpy (c->nick, newnick, sizeof(c->nick));
707     }
708     c = c->next;
709   }
710 }
711 
712 void
scan_chan_users(char * chan,char * nick,char * banned)713 scan_chan_users (char *chan, char *nick, char *banned)
714 {
715   struct userlist *c;
716   c = userhead;
717   if (banned[0] == '*' && banned[1] == '!' && banned[2] == '*'
718       && banned[3] == '\0') {
719     S ("MODE %s -ob %s %s\n", chan, nick, banned);
720     R;
721   }
722 #if KICK_ON_BAN == 1
723   while (c) {
724     if (!match_wild (banned, c->uh) == 0) {
725       if (stricmp (c->nick, Mynick) != 0) {
726         S ("KICK %s %s :BANNED\n", chan, c->nick);
727       }
728       else {
729         S ("MODE %s -ob %s %s\n", chan, nick, banned);
730         R;
731       }
732     }
733     c = c->next;
734   }
735 #endif
736 }
737 
738 /**
739  * 6/23/00 Dan:
740  * - All method arguments are now pointer to const
741  * - Return type is now time_t
742  * - A for loop is now used instead of a while loop
743  */
return_useridle(const char * chan,const char * who,int toggle)744 time_t return_useridle (const char *chan, const char *who, int toggle)
745 {                               /* toggle=0 is for idle time, toggle=1 is to check if user
746                                    is in the chan */
747   const struct userlist *c = userhead;
748 
749   for (; c != NULL; c = c->next) {
750     if (!stricmp (who, c->nick) && !stricmp (chan, c->chan)) {
751       if (toggle == 1) {
752         /* If we only care if user is present or not.. */
753         return 1;
754       }
755       else
756         return c->idle;
757     }                           /* if */
758   }                             /* for */
759   return 0;
760 }
761 
762 /**
763  * 6/23/00 Dan:
764  * - All method arguments are now pointer to const
765  * - A for loop is now used instead of a while loop
766  */
767 void
show_chaninfo(const char * nick,const char * chan)768 show_chaninfo (const char *nick, const char *chan)
769 {
770   size_t totalUsers = 0, foundUsers = 0;
771   const struct userlist *c = userhead;
772 
773   for (; c != NULL; c = c->next) {
774     ++totalUsers;
775     if (!stricmp (chan, c->chan))
776       ++foundUsers;
777   }
778   S ("PRIVMSG %s :%s, I see %d users in %s (%d users total in ram)\n",
779      chan, nick, foundUsers, chan, totalUsers);
780 }
781 
782 /**
783  * 6/22/00 Dan
784  * - Removed srand(), should only be done once, in main()
785  * - Changed while to for loop
786  */
787 char *
get_rand_nick(const char * chan)788 get_rand_nick (const char *chan)
789 {
790   size_t x = 0;
791   size_t i = 0;
792   const struct userlist *c = userhead;
793 
794   /* Iterate through the userlist */
795   for (; c != NULL; c = c->next) {
796     /* Check if this user is on the channel */
797     if (stricmp (chan, c->chan) == 0) {
798 	if (stricmp (Mynick, c->nick) != 0) {
799       	  strncpy (f_tmp, c->nick, sizeof(f_tmp));
800           i++;
801 	}
802     }
803   }
804 
805   x = rand () % i + 2;
806   i = 0;                        /* reinit! */
807 
808   for (c = userhead; c != NULL; c = c->next) {
809     if (stricmp (chan, c->chan) == 0) {
810       i++;
811       if (i == x) {
812         if (*c->nick == '0') {
813           return f_tmp;
814         }
815         if (stricmp (Mynick, c->nick) != 0) {
816 	  strncpy (f_tmp, c->nick, sizeof(f_tmp));
817           return f_tmp;
818 	}
819       }
820     }
821   }
822   return f_tmp;
823 }
824 
825 void
add_user(char * chan,char * nick,char * uh,long tog)826 add_user (char *chan, char *nick, char *uh, long tog)
827 {
828   /* toggle of 0 means to unidle the client */
829   struct userlist *n, *c;
830   c = userhead;
831   if (strlen (uh) > 399)
832     uh[399] = '\0';
833   while (c) {                   /* don't readd data that already exists */
834     if (tog == 0) {
835       if (stricmp (c->nick, nick) == 0
836           && stricmp (c->chan, chan) == 0) {
837         c->idle = time (NULL);
838       }
839     }
840     if (tog == 1) {
841       if (stricmp (c->nick, nick) == 0
842           && stricmp (c->chan, chan) == 0) {
843         /* If user is somehow already here, just update his data instead
844            of readding */
845         strncpy (c->chan, chan, sizeof(c->chan));
846         strncpy (c->uh, uh, sizeof(c->uh));
847         strlwr (c->uh);
848         strncpy (c->nick, nick,sizeof(c->nick));
849         c->idle = time (NULL);
850         c->level = 0;
851         R;
852       }
853     }
854     c = c->next;
855   }
856   if (tog == 0) {
857     /* all we wanted to do was unidle, so we can quit now */
858     R;
859   }
860   n = (struct userlist *) malloc (sizeof (struct userlist));
861   if (n == NULL) {
862     log ("error.log", "AHHH! No ram left! in add_user!\n");
863     R;
864   }
865   memset (n, 0, sizeof (struct userlist));
866   if (n != NULL) {
867     strncpy (n->chan, chan, sizeof(n->chan));
868     strncpy (n->uh, uh, sizeof(n->uh));
869     strlwr (n->uh);
870     strncpy (n->nick, nick, sizeof(n->nick));
871     n->idle = time (NULL);
872     n->level = 0;
873 
874     n->next = userhead;
875     userhead = n;
876   }
877 }
878 
879 #if DO_CHANBOT_CRAP == 1
880 /**
881  * Remove a permban based on nickname and user@host.
882  * 6/23/00 Dan:
883  * - Both arguments are now pointers to const data
884  * - Added free() for both pNode->uh and pNode->reason now
885  *   that the permbanlist has dynamically allocated fields
886  * - Changed type of toggle from long to bool
887  * - Changed name of toggle variable to (foundBan)
888  * - permbanlist pointers are now initialized when declared
889  * - Added if statement at end of method, this will only save
890  *   the bans if a ban was removed
891  */
892 int
del_permban(const char * nick,const char * uh)893 del_permban (const char *nick, const char *uh)
894 {
895 
896   bool foundBan = false;
897   struct permbanlist *pNode = permbanhead, *pPrev = 0;
898 
899   while (pNode) {
900     if (stricmp (pNode->uh, uh) == 0) {
901       L002 (nick, PERMBAN_counter, uh);
902       PERMBAN_counter--;
903       if (pPrev != NULL) {
904         pPrev->next = pNode->next;
905       }
906       else {
907         permbanhead = pNode->next;
908       }
909 
910       free (pNode->uh);
911       free (pNode->reason);
912       free (pNode);
913       foundBan = true;
914       pNode = NULL;
915       break;
916     }
917     pPrev = pNode;
918     pNode = pNode->next;
919   }
920 
921   if (foundBan) {
922     /* Only need to save bans if ban list has changed */
923     save_permbans ();
924   }
925   return foundBan;
926 }
927 #endif
928 
929 char *
revert_topic(char * input)930 revert_topic (char *input)
931 {
932   char *ptr, b[STRING_SHORT];
933 
934   ptr = strtok (input, "+");
935   strncpy (f_tmp, ptr, sizeof(f_tmp));
936   if (ptr != NULL) {
937     while (ptr != NULL) {
938       ptr = strtok (NULL, "+");
939       if (ptr != NULL) {
940 #ifdef WIN32
941     sprintf (b, "%s %s", f_tmp, ptr);
942 #else
943         snprintf (b, sizeof(b), "%s %s", f_tmp, ptr);
944 #endif
945         strncpy (f_tmp, b, sizeof(f_tmp));
946       }
947     }
948     R f_tmp;
949   }
950   else
951     R f_tmp;
952 }
953 
954 char *
get_multiword_topic(char * first)955 get_multiword_topic (char *first)
956 {
957   char *tmp2;
958 
959   tmp2 = strtok (NULL, " ");
960   if (tmp2 != NULL) {
961           sprintf (f_tmp, "%s", first);
962     while (tmp2 != NULL) {
963                 sprintf (f_tmp, "%s+%s", f_tmp, tmp2);
964       tmp2 = strtok (NULL, " ");
965     }
966     R f_tmp;
967   }
968   else
969     R first;
970 }
971 
972 /**
973  * Delete one or more elements from the sendq
974  * 1 = delete all pri/not's
975  * 0 = delete first in queue
976  * 6/23/00 Dan
977  * - Updated to use head and tail pointer queue
978  * - All variables now initialized when declared
979  * - Optimized the main while loop a bit, reduced amount of code
980  */
981 void
del_sendq(long toggle)982 del_sendq (long toggle)
983 {
984   struct sendq *pNode = sendqhead, *pPrev = 0;
985 
986   if (NULL == sendqhead) {
987     return;
988   }
989 
990   if (toggle == 0) {
991     /* Just delete the head */
992     pNode = sendqhead;
993     sendqhead = sendqhead->next;
994 
995     free (pNode);
996   }
997   else {
998     /* Iterate through the queue and delete each element which is
999      * a PRIVMSG or NOTICE
1000      */
1001     for (; pNode != NULL; pPrev = pNode, pNode = pNode->next) {
1002       if (0 == strncmp (pNode->data, "PRI", 3)
1003           || 0 == strncmp (pNode->data, "NOT", 3)) {
1004         /* Found one, let's delete it */
1005         if (pPrev != NULL) {
1006           pPrev->next = pNode->next;
1007         }
1008         else {
1009           sendqhead = pNode->next;
1010         }
1011         free (pNode);
1012         pNode = NULL;
1013         break;
1014       }
1015     }                           /* for */
1016   }                             /* else */
1017 
1018 /* Update the tail pointer if needed */
1019   if (NULL == sendqhead) {
1020     sendqtail = NULL;
1021   }
1022 }
1023 
1024 /**
1025  * 6/23/00 Dan
1026  * - Changed method argument to be pointer to const data
1027  * - Initialized b
1028  */
1029 int
Snow(const char * format,...)1030 Snow (const char *format, ...)
1031 {
1032   va_list arglist;
1033   char b[STRING_LONG] = { 0 };
1034 
1035   va_start (arglist, format);
1036   vsprintf (b, format, arglist);
1037   va_end (arglist);
1038   if (DebuG == 1)
1039     printf ("OUT: %s\n", b);
1040   R (writeln (b));
1041 }
1042 
1043 /**
1044  * 6/23/00 Dan
1045  * - Changed method argument to be pointer to const data
1046  * - Initialized variables when declared
1047  * - Changed b to a power of 2
1048  */
1049 void
S(const char * format,...)1050 S (const char *format, ...)
1051 {
1052   va_list arglist;
1053   char b[STRING_LONG] = { 0 };
1054   struct sendq *n = 0;
1055 
1056   va_start (arglist, format);
1057   vsprintf (b, format, arglist);
1058   va_end (arglist);
1059 
1060   if (send_tog == 0) {
1061     send_tog = 1;
1062     if (DebuG == 1) {
1063       printf ("OUT: %s\n", b);
1064     }
1065     writeln (b);
1066     R;
1067   }
1068 
1069   n = (struct sendq *) malloc (sizeof (struct sendq));
1070   if (n == NULL) {
1071     log ("error.log", "AHH! no ram left! in S!\n");
1072     R;
1073   }
1074 
1075   memset (n, 0, sizeof (struct sendq));
1076   strncpy (n->data, b, sizeof(n->data));
1077 
1078   if (sendqhead == NULL) {
1079     sendqhead = sendqtail = n;
1080   }
1081   else {
1082     sendqtail->next = n;
1083     sendqtail = sendqtail->next;
1084   }
1085 }
1086 
1087 void
count_seen(char * source,char * target)1088 count_seen (char *source, char *target)
1089 {
1090   FILE *fp;
1091   char temp[STRING_LONG] = "";
1092   long i = 0;
1093   if ((fp = fopen (SEEN_FILE, "r")) == NULL) {
1094     L003 (source, SEEN_FILE);
1095     R;
1096   }
1097   while (fgets (temp, STRING_LONG, fp)) {
1098     i++;
1099   }
1100   fclose (fp);
1101   L004 (target, source, i);
1102 }
1103 
1104 void
show_seen(char * nick,char * source,char * target)1105 show_seen (char *nick, char *source, char *target)
1106 {
1107   FILE *fp;
1108   char temp[STRING_LONG] = "", *intime, *r_nick, *uh, *chan, *ptr;
1109   long unixtime = 0;
1110 
1111   if (nick == NULL)
1112     R;
1113   if (strlen (nick) > 30)
1114     R;
1115   if (stricmp (nick, source) == 0) {
1116     L005 (target, source);
1117     R;
1118   }
1119   if ((ptr = strchr (nick, '?')) != NULL)
1120     memmove (ptr, ptr + 1, strlen (ptr + 1) + 1);
1121   if ((fp = fopen (SEEN_FILE, "r")) == NULL) {
1122     L003 (source, SEEN_FILE);
1123     R;
1124   }
1125   while (fgets (temp, STRING_LONG, fp)) {
1126     stripline (temp);
1127     r_nick = strtok (temp, " ");
1128     if (stricmp (nick, r_nick) == 0) {
1129       uh = strtok (NULL, " ");
1130       chan = strtok (NULL, " ");
1131       if (uh == NULL || chan == NULL)
1132         continue;
1133       intime = strtok (NULL, " ");
1134       if (intime == NULL)
1135         continue;
1136       unixtime = time (NULL) - atoi (intime);
1137       if (unixtime > 86400)
1138         S
1139           ("PRIVMSG %s :%s, I last saw %s (%s) %d day%s, %02d:%02d ago in %s\n",
1140            target, source, r_nick, uh, unixtime / 86400,
1141            (unixtime / 86400 == 1) ? "" : "s", (unixtime / 3600) % 24,
1142            (unixtime / 60) % 60, chan);
1143       else if (unixtime > 3600)
1144         S
1145           ("PRIVMSG %s :%s, I last saw %s (%s) %d hour%s, %d min%s ago in %s\n",
1146            target, source, r_nick, uh, unixtime / 3600,
1147            unixtime / 3600 == 1 ? "" : "s", (unixtime / 60) % 60,
1148            (unixtime / 60) % 60 == 1 ? "" : "s", chan);
1149       else
1150         S
1151           ("PRIVMSG %s :%s, I last saw %s (%s) %d minute%s, %d sec%s ago in %s\n",
1152            target, source, r_nick, uh, unixtime / 60,
1153            unixtime / 60 == 1 ? "" : "s", unixtime % 60,
1154            unixtime % 60 == 1 ? "" : "s", chan);
1155       fclose (fp);
1156       R;
1157     }
1158   }
1159   fclose (fp);
1160   L006 (target, source, nick, SEEN_REPLY);
1161 }
1162 
1163 long
save_seen(char * nick,char * uh,char * chan)1164 save_seen (char *nick, char *uh, char *chan)
1165 {
1166   FILE *fp;
1167   char temp[STRING_LONG] = "", *r_nick, *r_chan, *r_uh, *r_time;
1168   long toggle = 0, unixtime = 0;
1169 
1170 #ifdef  WIN32
1171   printf ("*** Writing seen file: %s (%s)\n", CHAN, SEEN_FILE,
1172           date ());
1173 #endif
1174   unlink (TMP_FILE);
1175   if ((fp = fopen (SEEN_FILE, "r")) == NULL) {
1176     log (SEEN_FILE, "%s %s %s %d\n", nick, uh, chan, time (NULL));
1177     R - 1;
1178   }
1179   while (fgets (temp, STRING_LONG, fp)) {
1180     stripline (temp);
1181     r_nick = strtok (temp, " ");
1182     if (stricmp (nick, r_nick) == 0) {
1183       toggle = 1;
1184       log (TMP_FILE, "%s %s %s %d\n", nick, uh, chan, time (NULL));
1185     }
1186     else {
1187       r_uh = strtok (NULL, " ");
1188       r_chan = strtok (NULL, " ");
1189       r_time = strtok (NULL, " ");
1190       if (r_uh == NULL || r_chan == NULL || r_time == NULL)
1191         continue;
1192       unixtime = time (NULL) - atoi (r_time);
1193       if (unixtime < MAX_LASTSEEN)
1194         log (TMP_FILE, "%s %s %s %s\n", r_nick, r_uh, r_chan, r_time);
1195     }
1196   }
1197   fclose (fp);
1198   if (toggle == 0) {
1199     log (TMP_FILE, "%s %s %s %d\n", nick, uh, chan, time (NULL));
1200   }
1201   rename (TMP_FILE, SEEN_FILE);
1202   return toggle;
1203 }
1204 
1205 #if DO_CHANBOT_CRAP == 1
1206 /**
1207  * Save the permban list to file.
1208  * 6/23/00 Dan:
1209  * - the permbanlist pointer (c) is now pointer to const, because
1210  *   this is a read only method, and that is a read only variable
1211  * - Initialized c when it is declared
1212  */
1213 void
save_permbans()1214 save_permbans ()
1215 {
1216 
1217   const struct permbanlist *c = permbanhead;
1218 
1219   unlink (TMP_FILE);
1220 
1221 #ifdef  WIN32
1222   printf ("*** Writing permbans: %s (%s)\n", PERMBAN, date ());
1223 #endif
1224 
1225   for (; c != NULL; c = c->next) {
1226     log (TMP_FILE, "%s %d %s\n", c->uh, c->counter, c->reason);
1227   }
1228   rename (TMP_FILE, PERMBAN);
1229 
1230   if (PERMBAN_counter == 0)
1231     unlink (PERMBAN);
1232 }
1233 #endif
1234 
1235 /**
1236  * Remove the autotopic for a particular channel.
1237  * 6/23/00 Dan:
1238  * - Method argument is now pointer to const data
1239  * - All variables are now initialized when declared
1240  * - Changed size of b to be power of 2
1241  * - Changed variable types of toggle and x in accordance
1242  *   with their use
1243  */
1244 void
del_autotopic(const char * chan)1245 del_autotopic (const char *chan)
1246 {
1247   FILE *fp = 0;
1248   char b[STRING_LONG] = { 0 }, *r_chan = 0, *r_data = 0;
1249   bool toggle = false;
1250   size_t x = 0;
1251 
1252   unlink (TMP_FILE);
1253   fp = fopen (AUTOTOPIC_F, "r");
1254   if (NULL == fp) {
1255     return;
1256   }
1257 
1258   while (fgets (b, STRING_LONG, fp)) {
1259     x++;
1260     stripline (b);
1261 
1262     r_chan = strtok (b, " ");
1263     r_data = strtok (NULL, "");
1264 
1265     if (stricmp (r_chan, chan) == 0) {
1266       /* Found the channel */
1267       toggle = true;
1268     }
1269     else {
1270       log (TMP_FILE, "%s %s\n", r_chan, r_data);
1271     }
1272   }
1273 
1274   fclose (fp);
1275   if (x == 1 && toggle) {
1276     /* The autotopic file is now empty */
1277     unlink (AUTOTOPIC_F);
1278     unlink (TMP_FILE);
1279     R;
1280   }
1281 
1282   if (toggle) {
1283     /* We found the topic, change the temp file to the
1284      * the name of the autotopic file */
1285     rename (TMP_FILE, AUTOTOPIC_F);
1286   }
1287   else {
1288     /* We were unable to find the channel, just
1289      * return */
1290     unlink (TMP_FILE);
1291   }
1292 }
1293 
1294 void
do_autotopics()1295 do_autotopics ()
1296 {
1297   FILE *fp;
1298   char b[STRING_LONG], *r_chan, *r_data;
1299 
1300   if ((fp = fopen (AUTOTOPIC_F, "r")) == NULL)
1301     R;
1302   while (fgets (b, STRING_LONG, fp)) {
1303     stripline (b);
1304     r_chan = strtok (b, " ");
1305     r_data = strtok (NULL, "");
1306     if (*r_data != '0') {
1307       db_sleep (1);
1308       S ("TOPIC %s :%s\n", r_chan, r_data);
1309     }
1310   }
1311   fclose (fp);
1312 }
1313 
1314 long
ifexist_autotopic(char * chan)1315 ifexist_autotopic (char *chan)
1316 {
1317   FILE *fp;
1318   char b[STRING_LONG], *r_chan;
1319 
1320   if ((fp = fopen (AUTOTOPIC_F, "r")) == NULL)
1321     R - 1;
1322   while (fgets (b, STRING_LONG, fp)) {
1323     stripline (b);
1324     if (*b == '/')
1325       continue;
1326     r_chan = strtok (b, " ");
1327     if (stricmp (r_chan, chan) == 0) {
1328       fclose (fp);
1329       R 1;                      /* exists */
1330     }
1331   }
1332   fclose (fp);
1333   R 0;                          /* doesn't exist */
1334 }
1335 
1336 void
set_autotopic(char * source,char * target,char * topic)1337 set_autotopic (char *source, char *target, char *topic)
1338 {
1339   long exist = 0;
1340 
1341   exist = ifexist_autotopic (target);
1342   if (exist == 0 && *topic == '0') {    /* never existed, lets humor
1343                                          * the guy */
1344     L007 (source, target);
1345     R;
1346   }
1347   else if (exist == 1 && *topic == '0') {       /* delete it! */
1348     L008 (source, target);
1349     S ("TOPIC %s :\n", target);
1350     del_autotopic (target);
1351     R;
1352   }
1353   if (strlen (topic) >= 400)    /* make sure no overflow */
1354     topic[400] = '\0';
1355   if (exist == 0) {             /* no such autotopic, so add it */
1356     L009 (source, target, topic);
1357     log (AUTOTOPIC_F, "%s %s\n", target, topic);
1358     R;
1359   }
1360   /* only thing left is if topic exists and you want to update it */
1361   del_autotopic (target);
1362   L010 (source, target, topic);
1363   S ("TOPIC %s :%s\n", target, topic);
1364   log (AUTOTOPIC_F, "%s %s\n", target, topic);
1365 }
1366 
1367 #ifdef  RANDOM_STUFF
1368 void
add_randomstuff(char * source,char * target,char * data)1369 add_randomstuff (char *source, char *target, char *data)
1370 {
1371   FILE *fp;
1372   char b[STRING_LONG], file2[STRING_SHORT], *ptr;
1373   long int i = 0, x = 0;
1374   long TOG = 0;
1375 
1376   if (*data == '~') {
1377     data++;
1378     TOG = 1;
1379     ptr = strtok (data, " ");
1380     if (ptr != NULL)
1381       strlwr (ptr);
1382 
1383     if (strspn (ptr, LEGAL_TEXT) != strlen (ptr)) {
1384       S
1385         ("PRIVMSG %s :%s, rdb file must be made up of letters and or numbers, no other text is accepted.\n",
1386          target, source);
1387       R;
1388     }
1389 #ifdef WIN32
1390     sprintf (file2, "dat/%s.rdb", ptr);
1391 #else
1392         snprintf(file2,sizeof(file2),"dat/%s.rdb",ptr);
1393 #endif
1394     data = strtok (NULL, "");
1395   }
1396   else
1397 #ifdef WIN32
1398           sprintf (file2, "%s", RAND_FILE);
1399 #else
1400       snprintf(file2,sizeof(file2), "%s", RAND_FILE);
1401 #endif
1402   if ((fp = fopen (file2, "r")) == NULL) {
1403     if (TOG == 1) {
1404       log (file2, "1\n%s\n", data);
1405       S ("PRIVMSG %s :Done, there is 1 topic under %s\n", target,
1406          file2);
1407     }
1408     R;
1409   }
1410   unlink (TMP_FILE);
1411   while (fgets (b, STRING_LONG, fp)) {
1412     stripline (b);
1413     i++;
1414     if (*b == '/')
1415       continue;
1416     if (i == 1) {
1417       if (b != NULL) {
1418         x = atol (strtok (b, " "));
1419         log (TMP_FILE, "%ld\n", x + 1);
1420       }
1421     }
1422     else {
1423       log (TMP_FILE, "%s\n", b);
1424     }
1425   }
1426   log (TMP_FILE, "%s\n", data);
1427   L011 (target, source, i);
1428   fclose (fp);
1429   rename (TMP_FILE, file2);
1430 }
1431 #endif
1432 
1433 #ifdef  RANDOM_STUFF
1434 void
get_rand_stuff_time()1435 get_rand_stuff_time ()
1436 {
1437   Rand_Stuff = rand () % RAND_STUFF_TIME + 2;
1438   if (Rand_Stuff < RAND_STUFF_TIME / 2)
1439     Rand_Stuff = RAND_STUFF_TIME;
1440 }
1441 #endif
1442 
1443 #ifdef  RANDOM_STUFF
1444 /**
1445  * 6/23/00 Dan:
1446  * - Removed an unused variable
1447  * - Changed initialization of temp
1448  * - Changed size of b to be power of 2, and initialized
1449  * - Initialized all other variables
1450  */
1451 void
do_random_stuff()1452 do_random_stuff ()
1453 {
1454   FILE *fp = 0;
1455   char temp[STRING_SHORT] = { 0 }, b[STRING_LONG] =
1456   {
1457   0}
1458   , *b2 = 0;
1459   bool A = false;
1460   size_t i = 0;
1461   size_t length = 0;
1462   size_t x = 0, y = 0;
1463   srand (time (0));   /* this makes things more random! */
1464 
1465 
1466   fp = fopen (RAND_FILE, "r");
1467   if (NULL == fp) {
1468     return;
1469   }
1470 
1471   while (fgets (b, STRING_LONG, fp)) {
1472     if (*b == '/') {
1473       continue;
1474     }
1475     i++;
1476     stripline (b);
1477 
1478     if (i == 1) {
1479       y = atoi (b);
1480       x = rand () % y + 2;
1481     }
1482     if (i == x) {
1483       if (*b == '+') {
1484         A = true;
1485       }
1486       length = strlen (b);
1487       i = 0;
1488 
1489       memset (data, 0, sizeof (data));
1490       while (length > 0) {
1491         i++;
1492         length--;
1493         if (b[length] == '~') {
1494           /* $chan */
1495 #ifdef WIN32
1496                 sprintf (temp, "%s%s", CHAN, data);
1497 #else
1498                 snprintf(temp, sizeof(temp), "%s%s", CHAN, data);
1499 #endif
1500         }
1501         else {
1502 #ifdef WIN32
1503                 sprintf (temp, "%c%s", b[length], data);
1504 #else
1505                 snprintf(temp, sizeof(temp), "%c%s", b[length], data);
1506 #endif
1507         }
1508         strncpy (data, temp, sizeof(data));
1509       }
1510       if (!A) {
1511         S ("PRIVMSG %s :%s\n", CHAN, data);
1512         fclose (fp);
1513         R;
1514       }
1515       else {
1516         b2 = data;
1517         b2++;
1518         S ("PRIVMSG %s :\1ACTION %s\1\n", CHAN, b2);
1519         fclose (fp);
1520         R;
1521       }
1522     }
1523   }                             /* while() */
1524 
1525 /* fclose(fp); */
1526 }
1527 #endif
1528 
1529 
1530 void
do_randomtopic(char * target,char * file,char * nick,char * topic)1531 do_randomtopic (char *target, char *file, char *nick, char *topic)
1532 {
1533   FILE *fp = 0;
1534 
1535   char temp[STRING_SHORT] = { 0 };
1536   char b2[STRING_LONG] = { 0 };
1537   char *b = 0;
1538   char file2[STRING_SHORT] = { 0 };
1539   char Data[STRING_LONG] = { 0 };
1540 
1541   long x = 0;
1542   long y = 0;
1543   long A = 0;
1544 
1545   size_t i = 0;
1546   size_t length = 0;
1547 
1548   bool Tog = false;
1549 
1550   if (file != NULL)
1551 #ifdef WIN32
1552           sprintf (file2, "dat/%s.rdb", file);
1553 #else
1554      snprintf (file2, sizeof(file2), "dat/%s.rdb", file);
1555 #endif
1556   if ((fp = fopen (file2, "r")) == NULL) {
1557     S ("PRIVMSG %s :Sorry, I cannot answer that topic because "
1558        "darkbot random text file (rdb) \"%s\" was not found.\n",
1559        target, file2);
1560     R;
1561   }
1562   db_sleep (1);
1563   while (fgets (b2, STRING_LONG, fp)) {
1564     i++;
1565     stripline (b2);
1566     if (i == 1) {
1567       y = atoi (b2);
1568       x = rand () % y + 2;
1569     }
1570     if (i == x) {
1571       i = 0;
1572       b = b2;
1573       if (*b == '+') {
1574         b++;
1575         A = 1;
1576       }
1577       length = strlen (b);
1578       while (length > 0) {
1579         length--;
1580         if (Tog) {
1581           Tog = false;
1582 #ifdef WIN32
1583           if (b[length] == 'N') {       /* nick */
1584             sprintf (temp, "%s%s", nick, Data);
1585           }
1586           else if (b[length] == 'C') {  /* chan */
1587             sprintf (temp, "%s%s", target, Data);
1588           }
1589           else if (b[length] == 'T') {  /* time */
1590             sprintf (temp, "%s%s", date (), Data);
1591           }
1592           else if (b[length] == 'R') {  /* rand */
1593             sprintf (temp, "%s%s", get_rand_nick (target),
1594 Data);
1595           }
1596           else if (b[length] == 'S') {  /* serv */
1597             sprintf (temp, "%s%s", BS, Data);
1598           }
1599           else if (b[length] == 'P') {  /* port */
1600             sprintf (temp, "%d%s", (int) BP, Data);
1601           }
1602           else if (b[length] == 'Q') {  /* question */
1603             sprintf (temp, "%s%s", revert_topic (topic),
1604 Data);
1605           }
1606           else if (b[length] == 'W') {  /* WWW page */
1607             sprintf (temp,"http://darkbot.net%s", Data);
1608           }
1609           else if (b[length] == '!') {  /* cmdchar */
1610             sprintf (temp,"%c%s", *CMDCHAR, Data);
1611           }
1612           else if (b[length] == 'V') {  /* version */
1613             sprintf (temp,"%s%s", dbVersion, Data);
1614           }
1615           else if (b[length] == 'B') {  /* mynick */
1616             sprintf (temp,"%s%s", Mynick, Data);
1617           }
1618           else {
1619             sprintf (temp,"%c~%s", b[length], Data);
1620           }
1621         }
1622         else if (b[length] == '~') {
1623           Tog = true;
1624         }
1625         else {
1626           sprintf (temp,"%c%s", b[length], Data);
1627         }
1628         strncpy (Data, temp, sizeof(Data));
1629       }                         /* While */
1630 #else
1631           if (b[length] == 'N') {       /* nick */
1632             snprintf (temp, sizeof(temp), "%s%s", nick, Data);
1633           }
1634           else if (b[length] == 'C') {  /* chan */
1635             snprintf (temp, sizeof(temp), "%s%s", target, Data);
1636           }
1637           else if (b[length] == 'T') {  /* time */
1638             snprintf (temp, sizeof(temp), "%s%s", date (), Data);
1639           }
1640           else if (b[length] == 'R') {  /* rand */
1641             snprintf (temp, sizeof(temp), "%s%s", get_rand_nick (target),
1642   Data);
1643           }
1644           else if (b[length] == 'S') {  /* serv */
1645             snprintf (temp, sizeof(temp), "%s%s", BS, Data);
1646           }
1647           else if (b[length] == 'P') {  /* port */
1648             snprintf (temp, sizeof(temp), "%d%s", (int) BP, Data);
1649           }
1650           else if (b[length] == 'Q') {  /* question */
1651             snprintf (temp,sizeof(temp), "%s%s", revert_topic (topic),
1652   Data);
1653           }
1654           else if (b[length] == 'W') {  /* WWW page */
1655             snprintf (temp,sizeof(temp), "http://darkbot.net%s", Data);
1656           }
1657           else if (b[length] == '!') {  /* cmdchar */
1658             snprintf (temp, sizeof(temp), "%c%s", *CMDCHAR, Data);
1659           }
1660           else if (b[length] == 'V') {  /* version */
1661             snprintf (temp,sizeof(temp), "%s%s", dbVersion, Data);
1662           }
1663           else if (b[length] == 'B') {  /* mynick */
1664             snprintf (temp, sizeof(temp),"%s%s", Mynick, Data);
1665           }
1666           else {
1667             snprintf (temp,sizeof(temp), "%c~%s", b[length], Data);
1668           }
1669         }
1670         else if (b[length] == '~') {
1671           Tog = true;
1672         }
1673         else {
1674           snprintf (temp, sizeof(temp),"%c%s", b[length], Data);
1675         }
1676         strncpy (Data, temp, sizeof(Data));
1677         }                               /* While */
1678 #endif
1679       if (A == 0) {
1680         S ("PRIVMSG %s :%s\n", target, Data);
1681       }
1682       else {
1683         S ("PRIVMSG %s :\1ACTION %s\1\n", target, Data);
1684       }
1685       fclose (fp);
1686       R;
1687     }
1688   }
1689   fclose (fp);
1690 }
1691 
1692 
1693 /**
1694  * Add a permban to the permban list.
1695  * 6/23/00 Dan:
1696  * - Both pointer variables are now received as pointer to const data
1697  * - Changed counter to type size_t, this should be an unsigned type
1698  * - Initialiazed n to 0 on declaration
1699  * - Added support for dynamically allocated uh and reason fields
1700  *   in the struct permban list
1701  * - Did some extra memory leak prevention
1702  */
1703 void
add_permban(const char * uh,size_t counter,const char * reason)1704 add_permban (const char *uh, size_t counter, const char *reason)
1705 {
1706 
1707   struct permbanlist *n = 0;
1708   n = (struct permbanlist *)
1709     malloc (sizeof (struct permbanlist));
1710   if (n == NULL) {
1711     log ("error.log", "AHHH! no ram left! in add_permban!\n");
1712     R;
1713   }
1714 
1715   memset (n, 0, sizeof (struct permbanlist));
1716   n->uh = db_strndup (uh, STRING_SHORT);
1717   if (NULL == n->uh) {
1718     log ("error.log", "add_permban> Memory allocation failure\n");
1719     /* Prevent memory leaks */
1720     free (n);
1721     return;
1722   }
1723 
1724   n->reason = db_strndup (reason, STRING_SHORT);
1725   if (NULL == n->reason) {
1726     log ("error.log", "add_permban> Memory allocation failure\n");
1727     /* Prevent memory leaks */
1728     free (n->uh);
1729     free (n);
1730     return;
1731   }
1732 
1733   strlwr (n->uh);
1734   n->counter = counter;
1735   PERMBAN_counter++;
1736   n->next = permbanhead;
1737   permbanhead = n;
1738 }
1739 
1740 /**
1741  * Check if a permban exists for a given uh/channel/nick set.
1742  * 6/23/00 Dan:
1743  * - Changed all method arguments to be pointers to const data
1744  * - Return type is now bool, returns true if ban is found,
1745  *   false otherwise
1746  */
1747 bool
check_permban(const char * uh,const char * chan,const char * nick)1748 check_permban (const char *uh, const char *chan, const char *nick)
1749 {
1750   static char tmpBuf[STRING_SHORT + 1];
1751   struct permbanlist *c = permbanhead;
1752   strncpy (tmpBuf, uh, min (STRING_SHORT, strlen (uh)));
1753   strlwr (tmpBuf);
1754   for (; c != NULL; c = c->next) {
1755     if (!match_wild (c->uh, tmpBuf) == 0) {
1756       c->counter++;
1757       S ("MODE %s +b %s\n", chan, c->uh);
1758       S ("KICK %s %s :\2[\2%d\2]\2: %s\n",
1759          chan, nick, c->counter, c->reason);
1760       R true;
1761     }
1762   }
1763   R false;
1764 }
1765 
1766 #ifndef WIN32
min(const size_t a,const size_t b)1767 size_t min (const size_t a, const size_t b)
1768 {
1769   return ((a < b) ? a : b);
1770 }
1771 #endif
1772 
1773 long
get_pass(char * data)1774 get_pass (char *data)
1775 {
1776   /* returns 0 for no data */
1777   /* returns 1 for just pass */
1778   /* returns 2 for pass and data */
1779   char b[STRING_SHORT], b2[STRING_SHORT], *temp;
1780   long i = 0;
1781   strncpy (pass_data, "0", sizeof(pass_data));  /* init */
1782   strncpy (pass_pass, "0", sizeof(pass_pass));
1783   if (data == NULL)
1784     R 0;
1785   strncpy (b2, data, sizeof(b2));
1786   temp = strtok (data, " ");
1787   if (temp == NULL)
1788     R - 1;
1789   strncpy (b, temp, sizeof(b));
1790   while (temp != NULL) {
1791     i++;
1792     strncpy (pass_pass, temp, sizeof(pass_pass));
1793     temp = strtok (NULL, " ");
1794     if (temp == NULL)
1795       break;
1796 #ifdef WIN32
1797     sprintf (b,"%s %s", b, temp);
1798 #else
1799      snprintf (b, sizeof(b),"%s %s", b, temp);
1800 #endif
1801   }
1802   strncpy (b, "", sizeof(b));           /* reinit */
1803   temp = strtok (b2, " ");
1804   strncpy (b, temp, sizeof(b));
1805   while (i > 2) {
1806     i--;
1807     temp = strtok (NULL, " ");
1808 #ifdef WIN32
1809     sprintf (b,"%s %s", b, temp);
1810 #else
1811      snprintf (b, sizeof(b),"%s %s", b, temp);
1812 #endif
1813   }
1814   if (stricmp (b, pass_pass) == 0) {
1815     strncpy (pass_data, "0", sizeof(pass_data));
1816     R 1;
1817   }
1818   strncpy (pass_data, b, sizeof(pass_data));
1819   R 2;
1820 }
1821 
1822 void
set_pass(char * nick,char * uh,char * pass,char * newpass)1823 set_pass (char *nick, char *uh, char *pass, char *newpass)
1824 {
1825   struct helperlist *c;
1826   c = helperhead;
1827   strlwr (uh);
1828   while (c) {
1829     if (!match_wild (c->uh, uh) == 0) {
1830       if (strcmp (c->pass, pass) == 0) {
1831         strncpy (c->pass, newpass, sizeof(c->pass));
1832         L012 (nick, uh);
1833         save_changes ();
1834         R;
1835       }
1836       else {
1837         L013 (nick);
1838         R;
1839       }
1840     }
1841     c = c->next;
1842   }
1843   L014 (nick);
1844 }
1845 
1846 long
verify_pass(char * nick,char * chan,char * uh,char * pass)1847 verify_pass (char *nick, char *chan, char *uh, char *pass)
1848 {
1849   struct helperlist *c;
1850   c = helperhead;
1851   strlwr (uh);
1852   while (c) {
1853     if (!match_wild (c->uh, uh) == 0) {
1854       if (*c->pass == '0')
1855         R 0;                    /* no pass set */
1856       if (strcmp (c->pass, pass) == 0) {
1857         if (c->chan[0] == '#' && c->chan[1] == '*')
1858           R c->level;
1859         if (*chan == '*')
1860           R c->level;
1861         if (stricmp (c->chan, chan) == 0)
1862           R c->level;
1863         R 0;                    /* don't match chan access */
1864       }
1865     }
1866     c = c->next;
1867   }
1868   R 0;
1869 }
1870 
1871 void
delete_user_ram(char * source,char * uh)1872 delete_user_ram (char *source, char *uh)
1873 {
1874   struct helperlist *pNode, *pPrev;
1875   pNode = helperhead;
1876   pPrev = NULL;
1877   while (pNode) {
1878     if (stricmp (pNode->uh, uh) == 0) {
1879       L015 (source, pNode->uh, pNode->level, pNode->num_join);
1880       if (pPrev != NULL) {
1881         pPrev->next = pNode->next;
1882       }
1883       else
1884         helperhead = pNode->next;
1885       free (pNode);
1886       pNode = NULL;
1887       break;
1888     }
1889     pPrev = pNode;
1890     pNode = pNode->next;
1891   }
1892   save_changes ();
1893 }
1894 
1895 #ifdef  DO_MATH_STUFF
1896 void
do_math(const char * who,char * target,char * math)1897 do_math (const char *who, char *target, char *math)
1898 {
1899   char input[STRING_SHORT];
1900   char number_string[STRING_SHORT];
1901   char op = 0;
1902   unsigned int index = 0;
1903   unsigned int to = 0;
1904   unsigned int input_length = 0;
1905   unsigned int number_length = 0;
1906   double result = 0.0;
1907   double number = 0.0;
1908   strncpy (input, math, sizeof(input));
1909   input_length = strlen (input);
1910   for (to = 0, index = 0; index <= input_length; index++)
1911     if (*(input + index) != ' ')
1912       *(input + to++) = *(input + index);
1913   input_length = strlen (input);
1914   index = 0;
1915   if (input[index] == '=')
1916     index++;
1917   else {
1918     number_length = 0;
1919     if (input[index] == '+' || input[index] == '-')
1920       *(number_string + number_length++) = *(input + index++);
1921     for (; isdigit (*(input + index)); index++)
1922       *(number_string + number_length++) = *(input + index);
1923     if (*(input + index) == '.') {
1924       *(number_string + number_length++) = *(input + index++);
1925       for (; isdigit (*(input + index)); index++)
1926         *(number_string + number_length++) = *(input + index);
1927     }
1928     *(number_string + number_length) = '\0';
1929     if (number_length > 0)
1930       result = atof (number_string);
1931   }
1932   for (; index < input_length;) {
1933     op = *(input + index++);
1934     number_length = 0;
1935     if (input[index] == '+' || input[index] == '-')
1936       *(number_string + number_length++) = *(input + index++);
1937     for (; isdigit (*(input + index)); index++)
1938       *(number_string + number_length++) = *(input + index);
1939     if (*(input + index) == '.') {
1940       *(number_string + number_length++) = *(input + index++);
1941       for (; isdigit (*(input + index)); index++)
1942         *(number_string + number_length++) = *(input + index);
1943     }
1944     *(number_string + number_length) = '\0';
1945     number = atof (number_string);
1946     switch (op) {
1947     case '+':
1948       result += number;
1949       break;
1950     case '-':
1951       result -= number;
1952       break;
1953     case '*':
1954       result *= number;
1955       break;
1956     case '/':
1957       if (number == 0) {
1958         L016 (target, who);
1959         R;
1960       }
1961       else
1962         result /= number;
1963       break;
1964     case '%':
1965       if ((long) number == 0) {
1966         L016 (target, who);
1967         R;
1968       }
1969       else
1970         result = (double) ((long) result % (long) number);
1971       break;
1972     default:
1973       L017 (target, who);
1974       R;
1975     }
1976   }
1977   S ("PRIVMSG %s :%s\2:\2 %f\n", target, who, result);
1978 }
1979 #endif
1980 
1981 long
cf(char * host,char * nick,char * chan)1982 cf (char *host, char *nick, char *chan)
1983 {
1984   int f_n;
1985   if (check_access (host, chan, 0, nick)
1986       >= 3)
1987     R 0;
1988   f_n = f_f (host);
1989   if (f_n == -1) {
1990     a_f (host);
1991     R 0;
1992   }
1993   if (ood[f_n].value)
1994     R 1;
1995   ood[f_n].count++;
1996   if ((time (NULL) - ood[f_n].time) > ft)
1997     ood[f_n].count = 0;
1998   else if ((time (NULL) - ood[f_n].time) <= ft
1999            && ood[f_n].count >= fr) {
2000     ood[f_n].value = true;
2001     if (!ood[f_n].kick) {
2002       ood[f_n].kick = 1;
2003 #ifdef  FLOOD_KICK
2004       if (*chan == '#' || *chan == '&') {
2005         L018 (chan, nick, FLOOD_REASON, fc, host);
2006       }
2007       else
2008         L019 (CHAN, fc, host);
2009 #else
2010       if (*chan == '#' || *chan == '&') {
2011         L019 (CHAN, fc, host);
2012       }
2013       else
2014         L019 (CHAN, fc, host);
2015 #endif
2016     }
2017     R 1;
2018   }
2019   ood[f_n].time = time (NULL);
2020   R 0;
2021 }
2022 
2023 /**
2024  * 6/23/00 Dan:
2025  * - Initialized all variables
2026  */
2027 void
raw_now(char * type)2028 raw_now (char *type)
2029 {
2030   FILE *fp = 0;
2031   long i = 0, counter = 0;
2032   char str[STRING_LONG] = {
2033     0
2034   }
2035   , *dat = 0, *ptr = 0, *tmp1 = 0, *tmp2 = 0, *tmp3 = 0;
2036   if (stricmp (type, "PERFORM") == 0)
2037     if ((fp = fopen (PERFORM, "r")) == NULL)
2038       R;
2039   if (stricmp (type, "PERMBAN") == 0)
2040     if ((fp = fopen (PERMBAN, "r")) == NULL)
2041       R;
2042   if (stricmp (type, "DEOP") == 0)
2043     if ((fp = fopen (DEOP, "r")) == NULL)
2044       R;
2045   if (stricmp (type, "SERVERS") == 0)
2046     if ((fp = fopen (SERVERS, "r")) == NULL) {
2047       printf
2048         ("%s not found. You must create the file with format:\n",
2049          SERVERS);
2050       printf
2051         ("server port ...this list can be as long as you want.\n");
2052       exit (0);
2053     }
2054   if (stricmp (type, "SETUP") == 0)
2055     if ((fp = fopen (SETUP, "r")) == NULL) {
2056       printf ("Unable to locate %s! You must run configure!.\n",
2057               SETUP);
2058       exit (0);
2059     }
2060   while (!feof (fp)) {
2061     if (stricmp (type, "SETUP") == 0) {
2062       printf ("Loading %s data...\n", SETUP);
2063       SeeN = 1;
2064       while (fgets (str, STRING_LONG, fp)) {
2065         if (*str == '/')
2066           continue;
2067         stripline (str);
2068         dat = strtok (str, "");
2069         if ((ptr = strchr (dat, '=')) != NULL)
2070           *ptr++ = '\0';
2071         if (stricmp (dat, "NICK") == 0) {
2072           strncpy (Mynick, ptr, sizeof(Mynick));
2073           strncpy (s_Mynick, ptr, sizeof(s_Mynick));
2074 #if     LOG_PRIVMSG == 1
2075 #ifdef WIN32
2076           sprintf (privmsg_log,"%s%s-privmsg.log",
2077 LOG_DIR, Mynick);
2078 #else
2079           snprintf (privmsg_log,sizeof(privmsg_log), "%s%s-privmsg.log",
2080   LOG_DIR, Mynick);
2081 #endif
2082 #endif
2083         }
2084         else if (stricmp (dat, "USERID") == 0) {
2085           strncpy (UID, ptr, sizeof(UID));
2086         }
2087         else if (stricmp (dat, "CHAN") == 0) {
2088           strncpy (CHAN, ptr, sizeof(CHAN));
2089         }
2090         else if (stricmp (dat, "SEEN") == 0) {
2091           SeeN = atoi (ptr);
2092         }
2093         else if (stricmp (dat, "VHOST") == 0) {
2094           strncpy (VHOST, ptr, sizeof(VHOST));
2095         }
2096         else if (stricmp (dat, "REALNAME") == 0) {
2097           strncpy (REALNAME, ptr, sizeof(REALNAME));
2098         }
2099         else if (stricmp (dat, "CMDCHAR") == 0) {
2100           *CMDCHAR = *ptr;
2101         }
2102       }
2103 #ifdef  VERB
2104       printf ("   - botnick(%s),", Mynick);
2105       printf ("userid(%s),", UID);
2106       printf ("channel(%s)\n", CHAN);
2107       printf ("   - cmdchar(%c),", *CMDCHAR);
2108       printf ("vhost(%s),", VHOST);
2109       printf ("seen(%s)\n", SeeN == 1 ? "On" : "Off");
2110       printf ("   - realname(%s)\n", REALNAME);
2111 #endif
2112     }
2113     else if (stricmp (type, "PERMBAN") == 0) {
2114       while (fgets (str, STRING_LONG, fp)) {
2115         stripline (str);
2116         tmp1 = strtok (str, " ");
2117         if (tmp1 == NULL)
2118           continue;
2119         tmp2 = strtok (NULL, " ");
2120         if (tmp2 == NULL)
2121           tmp2 = "0";
2122         tmp3 = strtok (NULL, "");
2123         if (tmp3 == NULL)
2124           tmp3 = "Permbanned!";
2125         strlwr (tmp1);
2126         counter = atoi (tmp2);
2127         add_permban (tmp1, counter, tmp3);
2128       }
2129     }
2130     else if (stricmp (type, "SERVERS") == 0) {
2131 #ifndef WIN32
2132       printf ("Loading %s file ", SERVERS);
2133 #endif
2134       while (fgets (str, STRING_LONG, fp)) {
2135         i++;
2136         printf (".");
2137         fflush (stdout);
2138         stripline (str);
2139         tmp1 = strtok (str, " ");
2140         if (tmp1 == NULL) {
2141           printf
2142             ("Found error in %s! Aboring! please re-run configure!\n",
2143              SERVERS); exit (0);
2144         }
2145         else
2146           tmp2 = strtok (NULL, " ");
2147         if (tmp2 == NULL) {
2148           printf ("%s has no matching port in %s!\n", tmp1, SERVERS);
2149           exit (0);
2150         }
2151         add_s25 (tmp1, atoi (tmp2));
2152       }
2153       printf ("done(%d).\n", (int) i);
2154     }
2155     else if (fgets (str, STRING_LONG, fp))
2156       S ("%s\n", str);
2157   }
2158   fclose (fp);
2159 }
2160 
2161 /**
2162  * 6/22/00 Dan
2163  * - Function argument is now pointer to const
2164  * - Fixed a problem where the file was never closed
2165  * - All variables are now initialized when declared
2166  * - Removed an unused variable
2167  * - Changed long variables to type size_t, they should be
2168  *   unsigned
2169  * - Changed reinitialization of data
2170  * - Moved the big if/else structure to a switch
2171  */
2172 char *
rand_reply(const char * nick)2173 rand_reply (const char *nick)
2174 {
2175 
2176   FILE *fp = 0;
2177   char temp[STRING_SHORT] = {
2178     0
2179   };
2180   size_t i = 0, x = 0, y = 0, length = 0;
2181   fp = fopen (RAND_SAY, "r");
2182   if (NULL == fp) {
2183     return 0;
2184   }
2185 
2186   while (fgets (r_reply, STRING_SHORT, fp)) {
2187     if (*r_reply == '/') {
2188       continue;
2189     }
2190     i++;
2191     stripline (r_reply);
2192     if (i == 1) {
2193       /* Read in random # from top line of * random.ini */
2194       y = atoi (r_reply);
2195       x = rand () % y + 2;
2196     }
2197     if (i != x) {
2198       continue;
2199     }
2200 
2201     /* Found it */
2202     fclose (fp);
2203     length = strlen (r_reply);
2204     i = 0;
2205     data[0] = 0;
2206     while (length > 0) {
2207       i++;
2208       length--;
2209       switch (r_reply[length]) {
2210       case '^':
2211 #ifdef WIN32
2212         sprintf (temp,"%s%s", nick, data);
2213         break;
2214       case '%':
2215         /* Bold */
2216         sprintf (temp,"\2%s", data);
2217         break;
2218       case '&':
2219         /* Underline */
2220         sprintf (temp,"\37%s", data);
2221         break;
2222       case '~':
2223         /* Inverse */
2224         sprintf (temp,"\26%s", data);
2225         break;
2226       default:
2227         sprintf (temp,"%c%s", r_reply[length], data);
2228         break;
2229 #else
2230         snprintf (temp,sizeof(temp), "%s%s", nick, data);
2231         break;
2232         case '%':
2233         /* Bold */
2234         snprintf (temp,sizeof(temp), "\2%s", data);
2235         break;
2236         case '&':
2237         /* Underline */
2238         snprintf (temp,sizeof(temp), "\37%s", data);
2239         break;
2240         case '~':
2241         /* Inverse */
2242         snprintf (temp,sizeof(temp), "\26%s", data);
2243         break;
2244         default:
2245         snprintf (temp,sizeof(temp), "%c%s", r_reply[length], data);
2246         break;
2247 #endif
2248       }                         /* switch */
2249       strncpy (data, temp, sizeof(data));
2250     }                           /* while( length > 0 ) */
2251 
2252     return data;                /* Found random line */
2253   }                             /* while(fgets()) */
2254 
2255   /* Unable to find match */
2256   fclose (fp);
2257   /* A space is returned to prevent crashing */
2258   return " ";
2259 }
2260 
2261 /**
2262  * Update a nick's channel greeting and user@host.
2263  * 6/23/00 Dan:
2264  * - All method arguments are now pointers to const data
2265  * - Rewrote to use a for loop, and fewer variables
2266  * - Info is only saved to disk if changes are made
2267  */
2268 void
update_setinfo(const char * new_uh,const char * new_greetz,const char * nick)2269 update_setinfo (const char *new_uh,
2270                 const char *new_greetz, const char *nick)
2271 {
2272   struct helperlist *c = helperhead;
2273   bool madeChange = false;
2274   size_t i = 0;
2275   for (; c != NULL; c = c->next) {
2276     ++i;
2277     if (!match_wild (c->uh, new_uh) == 0) {
2278       strncpy (c->greetz, new_greetz, sizeof(c->greetz));
2279       strlwr (c->uh);
2280       L020 (nick, i, c->uh, new_greetz);
2281       madeChange = true;
2282     }
2283   }
2284   if (madeChange) {
2285     save_changes ();
2286   }
2287 }
2288 
2289 void
save_setup()2290 save_setup ()
2291 {
2292 #ifdef  WIN32
2293   printf ("*** Writing setup file: %s (%s)\n", SETUP, date ());
2294 #endif
2295   unlink (TMP_FILE);
2296   log (TMP_FILE, "NICK=%s\n", s_Mynick);
2297   log (TMP_FILE, "USERID=%s\n", UID);
2298   log (TMP_FILE, "CHAN=%s\n", CHAN);
2299   log (TMP_FILE, "VHOST=%s\n", VHOST);
2300   log (TMP_FILE, "REALNAME=%s\n", REALNAME);
2301   log (TMP_FILE, "CMDCHAR=%c\n", *CMDCHAR);
2302   log (TMP_FILE, "SEEN=%d\n", SeeN);
2303   rename (TMP_FILE, SETUP);
2304 }
2305 
2306 void
save_changes()2307 save_changes ()
2308 {
2309   long i = 0;
2310   struct helperlist *c;
2311   c = helperhead;
2312   unlink (TMP_FILE);
2313   while (c != NULL) {
2314     i++;
2315     log (TMP_FILE, "%s %s %d %d %s %s\n",
2316          c->chan, c->uh, c->level, c->num_join, c->pass, c->greetz);
2317     c = c->next;
2318   }
2319   rename (TMP_FILE, HELPER_LIST);
2320 }
2321 
2322 void
datasearch(const char * nick,char * topic,char * target)2323 datasearch (const char *nick, char *topic, char *target)
2324 {
2325   FILE *fp;
2326   long i = 0, FOUND = 0, x = 0;
2327   char b[STRING_LONG], *dorf, *subj, *ptr2, DATA[STRING_SHORT] = "";
2328   if (strlen (topic) > MAX_TOPIC_SIZE)
2329     topic[MAX_TOPIC_SIZE] = '\0';
2330   strlwr (topic);
2331   if ((fp = fopen (URL2, "r")) == NULL) {
2332     L003 (nick, URL2);
2333     R;
2334   }
2335   while (fgets (b, STRING_LONG, fp)) {
2336     x++;
2337     stripline (b);
2338     strlwr (b);
2339     subj = strtok (b, " ");
2340     dorf = strtok (NULL, "");
2341     ptr2 = strstr (dorf, topic);
2342     if (ptr2 != NULL) {
2343       i++;
2344       FOUND = 1;
2345       sprintf (DATA, "%s %s", DATA, subj);
2346       if (strlen (DATA) >= MAX_SEARCH_LENGTH)
2347         break;
2348     }
2349   }
2350   fclose (fp);
2351   if (FOUND == 0) {
2352     L021 (target, NO_TOPIC, topic, x);
2353   }
2354   else if (i > 19) {
2355     L022 (target, i, DATA);
2356   }
2357   else if (i == 1) {
2358     L023 (target, nick, DATA);
2359   }
2360   else
2361     L024 (target, i, nick, DATA);
2362 }
2363 
2364 /**
2365  * 6/23/00 Dan:
2366  * - All variables now initialized when declared
2367  * - Altered variable types to reflect usage
2368  */
2369 void
info(const char * source,char * target)2370 info (const char *source, char *target)
2371 {
2372   FILE *fp = 0;
2373   clock_t starttime = 0;
2374   char b[STRING_LONG] = {
2375     0
2376   };
2377   size_t topics = 0, dup = 0;
2378   time_t t2time = 0, c_uptime = 0;
2379 #ifdef FIND_DUPS
2380   char *ptr = 0, *subj = 0;
2381   size_t last = 0, last2 = 0;
2382 #endif
2383   t2time = time (NULL);
2384   unlink (TMP_URL);
2385   starttime = clock ();
2386   fp = fopen (URL2, "r");
2387   if (NULL == fp) {
2388     L003 (source, URL2);
2389     R;
2390   }
2391   while (fgets (b, STRING_LONG, fp)) {
2392     topics++;
2393 #ifdef  FIND_DUPS
2394     stripline (b);
2395     subj = strtok (b, " ");
2396     ptr = strtok (NULL, "");
2397     strlwr (subj);
2398     if (stricmp (last, subj) == 0) {
2399       dup++;
2400 #ifdef  SAVE_DUPS
2401       log (BACKUP_DUP, "%s %s\n", subj, ptr);
2402 #endif
2403     }
2404     else {
2405       log (TMP_URL, "%s %s\n", subj, ptr);
2406     }
2407     strncpy (last2, subj, sizeof(last2));
2408     last = last2;
2409 #endif
2410   }
2411 
2412   fclose (fp);
2413   rename (TMP_URL, URL2);
2414 #ifdef  FIND_DUPS
2415   if (dup > 0) {
2416     L025 (target, dup);
2417   }
2418 #endif
2419   c_uptime = time (NULL) - uptime;
2420   topics -= dup;
2421   if (c_uptime > 86400) {
2422     L026 (target,
2423           dbVersion,
2424           topics,
2425           c_uptime / 86400,
2426           (c_uptime / 86400 ==
2427            1) ? "" : "s",
2428           (c_uptime / 3600) % 24,
2429           (c_uptime / 60) % 60, QUESTIONS,
2430           ADDITIONS, DELETIONS,
2431           (double) (clock () -
2432                     starttime) /
2433           CLOCKS_PER_SEC,
2434           (((double)
2435             (clock () - starttime) / CLOCKS_PER_SEC) ==
2436            1) ? "" : "s");
2437   }
2438   else if (c_uptime > 3600) {
2439     L027 (target,
2440           dbVersion,
2441           topics,
2442           c_uptime / 3600,
2443           c_uptime / 3600 == 1 ? "" : "s",
2444           (c_uptime / 60) % 60,
2445           (c_uptime / 60) % 60 ==
2446           1 ? "" : "s", QUESTIONS,
2447           ADDITIONS, DELETIONS,
2448           (double) (clock () -
2449                     starttime) /
2450           CLOCKS_PER_SEC,
2451           (((double)
2452             (clock () - starttime) / CLOCKS_PER_SEC) ==
2453            1) ? "" : "s");
2454   }
2455   else {
2456     L028 (target,
2457           dbVersion,
2458           topics,
2459           c_uptime / 60,
2460           c_uptime / 60 == 1 ? "" : "s",
2461           c_uptime % 60,
2462           c_uptime % 60 == 1 ? "" : "s",
2463           QUESTIONS, ADDITIONS, DELETIONS,
2464           (double) (clock () - starttime) / CLOCKS_PER_SEC, (((double)
2465 
2466                                                               (clock
2467                                                                () -
2468                                                                starttime)
2469                                                               /
2470                                                               CLOCKS_PER_SEC)
2471                                                              ==
2472                                                              1) ? "" :
2473           "s");
2474   }
2475 }
2476 
2477 int
check_existing_url(const char * source,char * topic,char * target)2478 check_existing_url (const char *source, char *topic, char *target)
2479 {
2480   FILE *fp;
2481   char b[STRING_LONG], *subj;
2482   if ((fp = fopen (URL2, "r")) == NULL) {
2483     L003 (source, URL2);
2484     R 0;
2485   }
2486   while (fgets (b, STRING_LONG, fp)) {
2487     stripline (b);
2488     subj = strtok (b, " ");
2489     if (stricmp (subj, topic) == 0) {
2490       fclose (fp);
2491       R 1;
2492     }
2493   }
2494   fclose (fp);
2495   R 0;
2496 }
2497 
2498 void
find_url(const char * nick,char * topic,char * target)2499 find_url (const char *nick, char *topic, char *target)
2500 {
2501   FILE *fp;
2502   long i = 0, FOUND = 0, x = 0;
2503   char b[STRING_LONG], *subj, *ptr2, DATA[STRING_SHORT] = "";
2504   if (strlen (topic) > MAX_TOPIC_SIZE)
2505     topic[MAX_TOPIC_SIZE] = '\0';
2506   strlwr (topic);
2507   if ((fp = fopen (URL2, "r")) == NULL) {
2508     L003 (nick, URL2);
2509     R;
2510   }
2511   while (fgets (b, STRING_LONG, fp)) {
2512     x++;
2513     stripline (b);
2514     subj = strtok (b, " ");
2515     strlwr (subj);
2516     ptr2 = strstr (subj, topic);
2517     if (ptr2 != NULL) {
2518       i++;
2519       FOUND = 1;
2520       sprintf (DATA, "%s %s", DATA, subj);
2521       if (strlen (DATA) >= MAX_SEARCH_LENGTH)
2522         break;
2523     }
2524   }
2525   fclose (fp);
2526   if (FOUND == 0) {
2527     L021 (target, NO_TOPIC, topic, x);
2528   }
2529   else if (i > 19) {
2530     L022 (target, i, DATA);
2531   }
2532   else if (i == 1) {
2533     L023 (target, nick, DATA);
2534   }
2535   else
2536     L024 (target, i, nick, DATA);
2537 }
2538 
2539 void
display_url(char * target,char * nick,char * topic)2540 display_url (char *target, char *nick, char *topic)
2541 {
2542   FILE *fp;
2543   long x = 0;
2544   char b[STRING_LONG], *subj, *ptr;
2545   strlwr (topic);
2546   if ((fp = fopen (URL2, "r")) == NULL) {
2547     R;
2548   }
2549   while (fgets (b, STRING_LONG, fp)) {
2550     x++;
2551     stripline (b);
2552     subj = strtok (b, " ");
2553     ptr = strtok (NULL, "");
2554     if (stricmp (subj, topic) == 0 || !match_wild (subj, topic) == 0) {
2555       QUESTIONS++;
2556       S ("PRIVMSG %s :Raw data for %s is: %s\n", target, topic, ptr);
2557       fclose (fp);
2558       R;
2559     }                           /* Subject match */
2560   }
2561   fclose (fp);
2562   S
2563     ("PRIVMSG %s :%s, I do not know of any topic named %s\n",
2564      target, nick, topic);}
2565 
2566 void
delete_url(const char * nick,char * topic,char * target)2567 delete_url (const char *nick, char *topic, char *target)
2568 {
2569   FILE *fp;
2570   long i = 0, FOUND = 0;
2571   char b[STRING_LONG], *subj, *ptr, DATA[STRING_SHORT] = "";
2572   if (*topic == '~') {
2573     topic++;
2574     if (topic != NULL)
2575       strlwr (topic);
2576 #ifdef WIN32
2577     sprintf (DATA,"dat/%s.rdb", topic);
2578 #else
2579      snprintf (DATA,sizeof(DATA), "dat/%s.rdb", topic);
2580 #endif
2581     if (strspn (topic, LEGAL_TEXT) != strlen (topic)) {
2582       S
2583         ("PRIVMSG %s :%s, rdb files are made up of letters and or numbers, no other text is accepted.\n",
2584          target, nick);
2585       R;
2586     }
2587 
2588     if ((fp = fopen (DATA, "r")) == NULL) {
2589       S
2590         ("PRIVMSG %s :%s, %s.rdb does not exist.\n",
2591          target, nick, topic); R;}
2592     fclose (fp);
2593     unlink (DATA);
2594     S ("PRIVMSG %s :I have unlinked %s.\n", target, DATA);
2595     R;
2596   }
2597 
2598   if ((fp = fopen (URL2, "r")) == NULL) {
2599     L003 (nick, URL2);
2600     R;
2601   }
2602   unlink (TMP_URL);
2603   while (fgets (b, STRING_LONG, fp)) {
2604     stripline (b);
2605     subj = strtok (b, " ");
2606     ptr = strtok (NULL, "");
2607     i++;
2608     if (stricmp (subj, topic) == 0) {
2609       FOUND = 1;
2610       DELETIONS++;
2611       L029 (target, nick, i, topic);
2612     }
2613     else if (strstr (subj, " ") == NULL)
2614       log (TMP_URL, "%s %s\n", subj, ptr);
2615   }
2616   fclose (fp);
2617   rename (TMP_URL, URL2);
2618   if (FOUND == 0)
2619     L030 (target, nick, topic);
2620 }
2621 
2622 void
chanserv(char * source,char * target,char * buf)2623 chanserv (char *source, char *target, char *buf)
2624 {
2625   char *cmd, *s, *s2, *s3, *s4, *s5, *ptr3, temp[1024], *userhost;
2626   long sn2 = 0, sn = 0, i = 0, unixtime = 0;
2627 #ifdef  RANDOM_STUFF
2628   if (stricmp (target, CHAN) == 0)
2629     Rand_Idle = 0;
2630 #endif
2631   stripline (buf);
2632   stripline (source);
2633   if (buf == NULL || target == NULL || source == NULL)
2634     R;
2635   cmd = strtok (buf, " ");
2636   if (cmd == NULL)
2637     R;
2638   if (*cmd == ':')
2639     cmd++;
2640   if ((userhost = strchr (source, '!')) != NULL) {
2641     *userhost++ = '\0';
2642   }
2643   /* ------ commands that require a privmsg ------ */
2644   if (*target != '#' && *target != '&' && *target != '+') {
2645     if (stricmp (cmd, "PASS") == 0
2646         || stricmp (cmd, "PASSWORD") == 0
2647         || stricmp (cmd, "PASSWD") == 0) {
2648       s = strtok (NULL, " ");
2649       s2 = strtok (NULL, " ");
2650       if (s == NULL || s2 == NULL) {
2651         L031 (source, Mynick);
2652         R;
2653       }
2654       if (strlen (s2) > 25)
2655         s2[25] = '\0';
2656       set_pass (source, userhost, s, s2);
2657       R;
2658     }
2659     else if (stricmp (cmd, "RAW") == 0) {
2660       if (check_access (userhost, target, 0, source) >= 3) {
2661         s = strtok (NULL, "");
2662         if (s != NULL)
2663           S ("%s\n", s);
2664       }
2665     }
2666     else if (stricmp (cmd, "ADDUSER") == 0) {
2667       if (check_access (userhost, "#*", 0, source)
2668           >= 3) {
2669         s4 = strtok (NULL, " ");
2670         s = strtok (NULL, " ");
2671         s2 = strtok (NULL, " ");
2672         s5 = strtok (NULL, " ");
2673         if (s == NULL || s4 == NULL || s2 == NULL || s5 == NULL) {
2674           L055 (source);
2675           R;
2676         }
2677         sn = atoi (s2);
2678         if (sn > 10 || sn <= 0)
2679           R;
2680         if (strlen (s) < 7)
2681           R;
2682         L056 (*CMDCHAR);
2683         add_helper (s4, s, sn, 0, temp, s5);
2684         L057 (source, s, sn);
2685         save_changes ();
2686       }
2687     }
2688     else if (stricmp (cmd, "DIE") == 0 || stricmp (cmd, "QUIT") == 0) {
2689       s = strtok (NULL, "");
2690       if (check_access (userhost, target, 0, source) >= 3) {
2691         if (s == NULL) {
2692           L032 (source);
2693         }
2694         else
2695           Snow ("QUIT :K\2\2illed (%s (%s))\n", source, s);
2696         db_sleep (1);
2697 #ifdef  WIN32
2698         printf ("\n\nGood-bye! %s (c) Jason Hamilton\n\n", dbVersion);
2699         uptime = time (NULL) - uptime;
2700         printf
2701           ("Time elapsed: %d hour%s, %d min%s\n\n",
2702            uptime / 3600,
2703            uptime / 3600 == 1 ? "" : "s",
2704            (uptime / 60) % 60, (uptime / 60) % 60 == 1 ? "" : "s");
2705         db_sleep (5);
2706 #endif
2707         exit (0);
2708       }
2709 #if CTCP == 1
2710     }
2711     else if (stricmp (cmd, "\1VERSION\1") == 0) {
2712       if (cf (userhost, source, target))
2713         R;
2714       if (cf (userhost, source, target))
2715         R;
2716       S ("NOTICE %s :\1VERSION %s\1\n", source, VERSION_REPLY);
2717     }
2718     else if (stricmp (cmd, "\1PING") == 0) {
2719       if (cf (userhost, source, target))
2720         R;
2721       if (cf (userhost, source, target))
2722         R;
2723       s2 = strtok (NULL, "");
2724       if (s2 != NULL) {
2725         if (strlen (s2) > 21)
2726           s2[21] = '\0';
2727         S ("NOTICE %s :\1PING %s\n", source, s2);
2728       }
2729 #endif
2730     }
2731     else if (stricmp (cmd, "LOGIN") == 0) {
2732       s = strtok (NULL, " ");
2733       if (s == NULL)
2734         R;
2735       do_login (source, s);
2736     }
2737     R;
2738   }
2739   add_user (target, source, userhost, 0);       /* Unidle */
2740   /* ------ Commands that require a CMDCHAR to activate ------ */
2741   if (*cmd == *CMDCHAR) {
2742     if (Sleep_Toggle == 1)
2743       R;
2744     cmd++;
2745     if (cf (userhost, source, target))
2746       R;
2747     if (stricmp (cmd, "USERLIST") == 0
2748         || stricmp (cmd, "HLIST") == 0
2749         || stricmp (cmd, "ACCESS") == 0) {
2750       if (check_access (userhost, target, 0, source) == 0)
2751         R;
2752       s = strtok (NULL, " ");
2753       if (s != NULL) {
2754         show_helper_list (source, atoi (s));
2755       }
2756       else
2757         show_helper_list (source, 0);
2758     }
2759     else if (stricmp (cmd, "BANLIST") == 0) {
2760       if (check_access (userhost, target, 0, source) == 0)
2761         R;
2762       show_banlist (source);
2763     }
2764     else
2765       if (stricmp (cmd, "LANG") == 0
2766           || stricmp (cmd, "LANGUAGE") == 0) {
2767       S ("PRIVMSG %s :%s, %s\n", target, source, I_SPEAK);
2768     }
2769     else if (stricmp (cmd, "CHANINFO") == 0) {
2770       show_chaninfo (source, target);
2771     }
2772     else if (stricmp (cmd, "IDLE") == 0) {
2773       s2 = strtok (NULL, " ");
2774       if (s2 == NULL)
2775         R;
2776       if (stricmp (s2, source) == 0) {
2777         S ("PRIVMSG %s :%s, don't be lame.\n", target, source);
2778         R;
2779       }
2780       unixtime = return_useridle (target, s2, 0);
2781       if (unixtime == 0) {
2782         S
2783           ("PRIVMSG %s :%s, I do not see %s in %s.\n",
2784            target, source, s2, target); return;
2785       }
2786       unixtime = time (NULL) - unixtime;
2787       if (unixtime > 86400)
2788         S
2789           ("PRIVMSG %s :%s, %s has been idle %d day%s, %02d:%02d\n",
2790            target, source, s2, unixtime / 86400,
2791            (unixtime / 86400 == 1) ? "" : "s",
2792            (unixtime / 3600) % 24, (unixtime / 60) % 60);
2793       else if (unixtime > 3600)
2794         S
2795           ("PRIVMSG %s :%s, %s has been idle %d hour%s, %d min%s\n",
2796            target, source, s2, unixtime / 3600,
2797            unixtime / 3600 == 1 ? "" : "s",
2798            (unixtime / 60) % 60,
2799            (unixtime / 60) % 60 == 1 ? "" : "s");
2800       else
2801         S ("PRIVMSG %s :%s, %s has been idle %d minute%s, %d sec%s\n",
2802            target, source, s2, unixtime / 60,
2803            unixtime / 60 == 1 ? "" : "s", unixtime % 60,
2804            unixtime % 60 == 1 ? "" : "s");
2805     }
2806     else if (stricmp (cmd, "N") == 0 || stricmp (cmd, "NICK") == 0) {
2807       if (check_access (userhost, target, 0, source) >= 3) {
2808         s = strtok (NULL, " ");
2809         if (s == NULL) {
2810           L036 (source);
2811           R;
2812         }
2813         strncpy (Mynick, s, sizeof(Mynick));
2814 #ifdef WIN32
2815         sprintf (NICK_COMMA,"%s,", Mynick);
2816         sprintf (COLON_NICK,"%s:", Mynick);
2817         sprintf (BCOLON_NICK,"%s\2:\2", Mynick);
2818 #else
2819         snprintf (NICK_COMMA,sizeof(NICK_COMMA), "%s,", Mynick);
2820         snprintf (COLON_NICK,sizeof(COLON_NICK), "%s:", Mynick);
2821         snprintf (BCOLON_NICK,sizeof(BCOLON_NICK), "%s\2:\2", Mynick);
2822 #endif
2823         L037 (source, Mynick);
2824         S ("NICK %s\n", Mynick);
2825       }
2826       else
2827         L038 (source, source);
2828     }
2829     else
2830       if (stricmp (cmd, "L") == 0
2831           || stricmp (cmd, "PART") == 0
2832           || stricmp (cmd, "LEAVE") == 0 || stricmp (cmd, "P") == 0) {
2833       if (check_access (userhost, target, 0, source) >= 2) {
2834         s = strtok (NULL, "");
2835         if (s == NULL) {
2836           S ("PART %s\n", target);
2837         }
2838         else {
2839           S ("PART %s\n", s);
2840           L039 (target, s);
2841         }
2842       }
2843     }
2844     else if (stricmp (cmd, "VARIABLES") == 0) {
2845       S ("PRIVMSG %s :%s, %s\n", target, source, myVariables);
2846     }
2847     else if (stricmp (cmd, "JOIN") == 0 || stricmp (cmd, "J") == 0) {
2848       if (check_access (userhost, target, 0, source) >= 2) {
2849         s = strtok (NULL, "");
2850         if (s == NULL) {
2851           S ("JOIN %s\n", target);
2852         }
2853         else {
2854           S ("JOIN %s\n", s);
2855           L040 (target, s);
2856         }
2857       }
2858 #if DO_CHANBOT_CRAP == 1
2859     }
2860     else if (stricmp (cmd, "OP") == 0) {
2861       if (check_access (userhost, target, 0, source) >= 2) {
2862         s = strtok (NULL, "");
2863         if (s == NULL) {
2864           S ("PRIVMSG %s :Specify a nick!\n", target);
2865           return;
2866         }
2867         else {
2868           S ("MODE %s +oooooo %s\n", target, s);
2869         }
2870       }
2871     }
2872     else if (stricmp (cmd, "DEOP") == 0) {
2873       if (check_access (userhost, target, 0, source) >= 2) {
2874         s = strtok (NULL, "");
2875         if (s == NULL) {
2876           S ("PRIVMSG %s :Specify a nick!\n", target);
2877           return;
2878         }
2879         else {
2880           S ("MODE %s -oooooo %s\n", target, s);
2881         }
2882       }
2883     }
2884     else if (stricmp (cmd, "DOWN") == 0) {
2885       if (check_access (userhost, target, 0, source) >= 2)
2886         S ("MODE %s -o %s\n", target, source);
2887     }
2888     else if (stricmp (cmd, "UP") == 0) {
2889       if (check_access (userhost, target, 0, source) >= 2)
2890         S ("MODE %s +o %s\n", target, source);
2891     }
2892     else
2893       if (
2894           (stricmp (cmd, "KICK") == 0
2895            || stricmp (cmd, "WACK") == 0
2896            || stricmp (cmd, "K") == 0 || stricmp (cmd, "NAIL") == 0)) {
2897       if (check_access (userhost, target, 0, source) >= 2) {
2898         s = strtok (NULL, " ");
2899         if (s == NULL) {
2900           S ("PRIVMSG %s :Specify a nick/chan!\n", target);
2901           return;
2902         }
2903         else {
2904           if (*s != '#' && *s != '&') {
2905             s2 = strtok (NULL, "");
2906             if (s2 == NULL) {
2907               if (stricmp (s, Mynick) == 0) {
2908                 S ("KICK %s %s :hah! As *IF*\n", target, source);
2909               }
2910               else
2911                 S ("KICK %s %s :\2%s\2'ed: %s\n",
2912                    target, s, cmd, DEFAULT_KICK);}
2913             else if (stricmp (s, Mynick) == 0) {
2914               S ("KICK %s %s :%s\n", target, s, s2);
2915             }
2916             else
2917               S ("KICK %s %s :\2%s\2'ed: %s\n", target, s, cmd, s2);
2918           }
2919           else {
2920             s2 = strtok (NULL, " ");
2921             if (s2 == NULL) {
2922               S
2923                 ("NOTICE %s :You must specify a nick to kick from %s!\n",
2924                  source, s);
2925             }
2926             else {
2927               s3 = strtok (NULL, "");
2928               if (s3 == NULL) {
2929                 if (stricmp (s2, Mynick) == 0) {
2930                   S ("KICK %s %s :hah! As *IF*\n", s, source);
2931                 }
2932                 else
2933                   S ("KICK %s %s :\2%s\2ed: %s\n", s, s2,
2934                      cmd, DEFAULT_KICK);}
2935               else {
2936 
2937                 if (stricmp (s2, Mynick) == 0) {
2938                   S ("KICK %s %s :hah! As *IF* (%s)\n", s, source);
2939                 }
2940                 else
2941                   S ("KICK %s %s :\2%s\2ed: %s\n", s, s2, cmd, s3);
2942               }
2943             }
2944           }
2945         }
2946       }
2947 #endif
2948     }
2949     else if (stricmp (cmd, "CYC") == 0 || stricmp (cmd, "CYCLE") == 0) {
2950       if (check_access (userhost, target, 0, source) >= 2) {
2951         s = strtok (NULL, "");
2952         if (s == NULL) {
2953           S ("PART %s\n", target);
2954           S ("JOIN %s\n", target);
2955         }
2956         else {
2957           S ("PART %s\n", s);
2958           S ("JOIN %s\n", s);
2959           S ("PRIVMSG %s :Cycling %s\n", target, s);
2960         }
2961       }
2962     }
2963     else if (stricmp (cmd, "DIE") == 0 || stricmp (cmd, "QUIT") == 0) {
2964       s = strtok (NULL, "");
2965       if (check_access (userhost, target, 0, source) >= 3) {
2966         if (s == NULL) {
2967           L032 (source);
2968         }
2969         else
2970           Snow ("QUIT :K\2\2illed (%s (%s))\n", source, s);
2971         db_sleep (1);
2972 #ifdef  WIN32
2973         printf ("\n\nGood-bye! %s (c) Jason Hamilton\n\n", dbVersion);
2974         uptime = time (NULL) - uptime;
2975         printf
2976           ("Time elapsed: %d hour%s, %d min%s\n\n",
2977            uptime / 3600,
2978            uptime / 3600 == 1 ? "" : "s",
2979            (uptime / 60) % 60, (uptime / 60) % 60 == 1 ? "" : "s");
2980         db_sleep (5);
2981 #endif
2982         exit (0);
2983       }
2984 #if DO_CHANBOT_CRAP == 1
2985     }
2986     else
2987       if (stricmp (cmd, "DEV") == 0
2988           || stricmp (cmd, "DV") == 0
2989           || stricmp (cmd, "DEVOICE") == 0
2990           || stricmp (cmd, "DVOICE") == 0) {
2991       if (check_access (userhost, target, 0, source) >= 1) {
2992         s = strtok (NULL, "");
2993         if (s == NULL) {
2994           L041 (target);
2995           R;
2996         }
2997         else
2998           S ("MODE %s -vvvvvvv %s\n", target, s);
2999       }
3000     }
3001     else if (stricmp (cmd, "VOICE") == 0 || stricmp (cmd, "V") == 0) {
3002       if (check_access (userhost, target, 0, source) >= 1) {
3003         s = strtok (NULL, "");
3004         if (s == NULL) {
3005           L041 (target);
3006           R;
3007         }
3008         else
3009           S ("MODE %s +vvvvvvv %s\n", target, s);
3010       }
3011     }
3012     else if (stricmp (cmd, "T") == 0 || stricmp (cmd, "TOPIC") == 0) {
3013       if (check_access (userhost, target, 0, source) >= 2) {
3014         s = strtok (NULL, "");
3015         if (s == NULL) {
3016           S ("TOPIC %s :\n", target);
3017           R;
3018         }
3019         else {
3020           S ("TOPIC %s :%s\n", target, s);
3021         }
3022       }
3023 #endif
3024     }
3025     else if (stricmp (cmd, "JUMP") == 0
3026              || stricmp (cmd, "SERVER") == 0) {
3027       if (check_access (userhost, target, 0, source) >= 3) {
3028         s = strtok (NULL, " ");
3029         if (s == NULL) {
3030           S ("NOTICE %s :Syntax: JUMP <server> [port]\n", source);
3031           R;
3032         }
3033         s2 = strtok (NULL, " ");
3034         if (s2 == NULL) {
3035           sn = 6667;
3036         }
3037         else
3038           sn = atoi (s2);
3039         S ("QUIT :Jumping to %s:%d\n", s, sn);
3040         db_sleep (1);
3041         socketfd = get_connection (s, VHOST, sn);
3042         init_bot ();
3043       }
3044 #if DO_CHANBOT_CRAP == 1
3045     }
3046     else if (stricmp (cmd, "DELBAN") == 0) {
3047       if (check_access (userhost, target, 0, source) >= 3) {
3048         s = strtok (NULL, " ");
3049         if (s == NULL) {
3050           L042 (source);
3051           R;
3052         }
3053         if (del_permban (source, s) == 1)
3054           S ("MODE %s -b %s\n", target, s);
3055         else
3056           L043 (source);
3057       }
3058 #endif
3059     }
3060     else if (stricmp (cmd, "DELUSER") == 0) {
3061       if (check_access (userhost, target, 0, source) >= 3) {
3062         s = strtok (NULL, " ");
3063         if (s == NULL) {
3064           L044 (source);
3065           R;
3066         }
3067         delete_user_ram (source, s);
3068       }
3069 #if DO_CHANBOT_CRAP == 1
3070     }
3071     else if (stricmp (cmd, "TEASEOP") == 0
3072              || stricmp (cmd, "TO") == 0) {
3073       if (check_access (userhost, target, 0, source) >= 2) {
3074         s = strtok (NULL, " ");
3075         if (s == NULL) {
3076           L036 (target);
3077           R;
3078         }
3079         if (stricmp (s, Mynick) == 0) {
3080           L045 (source);
3081         }
3082         else
3083           S
3084             ("MODE %s +o-o+o-o+o-o %s %s %s %s %s %s\n",
3085              target, s, s, s, s, s, s);
3086       }
3087 #endif
3088 #ifndef WIN32
3089     }
3090     else if (stricmp (cmd, "BACKUP") == 0) {
3091       if (check_access (userhost, target, 0, source) >= 3) {
3092 #ifdef WIN32
3093                   sprintf (temp,"/bin/cp -rf %s \"%s.bak @ `date`\"\n",
3094 #else
3095         snprintf (temp,sizeof(temp),
3096                  "/bin/cp -rf %s \"%s.bak @ `date`\"\n",
3097 #endif
3098                  URL2, URL2); system (temp);
3099         L046 (target);
3100       }
3101 #endif
3102     }
3103     else if (stricmp (cmd, "AUTOTOPIC") == 0) {
3104       if (check_access (userhost, target, 0, source) >= 3) {
3105         s = strtok (NULL, "");
3106         if (s == NULL) {
3107           L047 (source, *CMDCHAR);
3108           R;
3109         }
3110         set_autotopic (source, target, s);
3111       }
3112     }
3113     else if (stricmp (cmd, "SETCHAN") == 0) {
3114       if (check_access (userhost, target, 0, source) >= 3) {
3115         s = strtok (NULL, " ");
3116         if (s == NULL) {
3117           L048 (source);
3118           R;
3119         }
3120         strncpy (CHAN, s, sizeof(CHAN));
3121         L049 (source, CHAN);
3122         save_setup ();
3123       }
3124     }
3125     else if (stricmp (cmd, "SETCHAR") == 0) {
3126       if (check_access (userhost, target, 0, source) >= 3) {
3127         s = strtok (NULL, " ");
3128         if (s == NULL) {
3129           L050 (source);
3130           R;
3131         }
3132         *CMDCHAR = *s;
3133         L051 (source, *CMDCHAR);
3134         save_setup ();
3135       }
3136     }
3137     else if (stricmp (cmd, "SETUSER") == 0) {
3138       if (check_access (userhost, target, 0, source) >= 3) {
3139         s = strtok (NULL, " ");
3140         if (s == NULL) {
3141           L052 (source);
3142           R;
3143         }
3144         strncpy (UID, s, sizeof(UID));
3145         L053 (source, UID);
3146         save_setup ();
3147       }
3148     }
3149     else if (stricmp (cmd, "VHOST") == 0) {
3150       if (check_access (userhost, target, 0, source) >= 3) {
3151         s = strtok (NULL, " ");
3152         if (s == NULL) {
3153           L091 (source);
3154           R;
3155         }
3156         strncpy (VHOST, s, sizeof(VHOST));
3157         L092 (source, VHOST);
3158         save_setup ();
3159       }
3160     }
3161     else if (stricmp (cmd, "SETNICK") == 0) {
3162       if (check_access (userhost, target, 0, source) >= 3) {
3163         s = strtok (NULL, " ");
3164         if (s == NULL) {
3165           L054 (source);
3166           R;
3167         }
3168         S ("NICK %s\n", s);
3169         strncpy (s_Mynick, s, sizeof(s_Mynick));
3170         strncpy (Mynick, s, sizeof(Mynick));
3171 #ifdef WIN32
3172         sprintf (NICK_COMMA,"%s,", Mynick);
3173         sprintf (COLON_NICK,"%s:", Mynick);
3174         sprintf (BCOLON_NICK,"%s\2:\2", Mynick);
3175 #else
3176         snprintf (NICK_COMMA,sizeof(NICK_COMMA), "%s,", Mynick);
3177         snprintf (COLON_NICK,sizeof(COLON_NICK), "%s:", Mynick);
3178         snprintf (BCOLON_NICK,sizeof(BCOLON_NICK), "%s\2:\2", Mynick);
3179 #endif
3180         save_setup ();
3181       }
3182     }
3183     else if (stricmp (cmd, "RAW") == 0) {
3184       if (check_access (userhost, target, 0, source) >= 3) {
3185         s = strtok (NULL, "");
3186         if (s != NULL)
3187           S ("%s\n", s);
3188       }
3189     }
3190     else if (stricmp (cmd, "SEEN") == 0 && SeeN == 1) {
3191       s = strtok (NULL, " ");
3192       if (s == NULL) {
3193         count_seen (source, target);
3194         R;
3195       }
3196       if (return_useridle (target, s, 1) == 1) {
3197         S ("PRIVMSG %s :%s is right here in the channel!\n", target,
3198            s);
3199         R;
3200       }
3201       show_seen (s, source, target);
3202 #if STATUS == 1
3203     }
3204     else if (stricmp (cmd, "LUSERS") == 0) {
3205       if (check_access (userhost, target, 0, source) >= 1)
3206         S ("LUSERS\n");
3207 #endif
3208     }
3209     else if (stricmp (cmd, "ADDUSER") == 0) {
3210       if (check_access (userhost, target, 0, source) >= 3) {
3211         s4 = strtok (NULL, " ");
3212         s = strtok (NULL, " ");
3213         s2 = strtok (NULL, " ");
3214         s5 = strtok (NULL, " ");
3215         if (s == NULL || s4 == NULL || s2 == NULL || s5 == NULL) {
3216           L055 (source);
3217           R;
3218         }
3219         sn = atoi (s2);
3220         if (sn > 10 || sn <= 0)
3221           R;
3222         if (strlen (s) < 7)
3223           R;
3224         L056 (*CMDCHAR);
3225         add_helper (s4, s, sn, 0, temp, s5);
3226         L057 (source, s, sn);
3227         save_changes ();
3228       }
3229 #if DO_CHANBOT_CRAP == 1
3230     }
3231     else
3232       if (stricmp (cmd, "PERMBAN") == 0
3233           || stricmp (cmd, "SHITLIST") == 0) {
3234       if (check_access (userhost, target, 0, source) >= 3) {
3235         s = strtok (NULL, " ");
3236         if (s == NULL) {
3237           L058 (source, *CMDCHAR, cmd);
3238           R;
3239         }
3240         s2 = strtok (NULL, "");
3241         if (s2 == NULL)
3242           s2 = "Permbanned!";
3243         add_permban (s, 0, s2);
3244         L059 (source, PERMBAN_counter, s, s2);
3245         save_permbans ();
3246         S ("MODE %s +b %s\n", target, s);
3247       }
3248 #endif
3249     }
3250     else
3251       if (stricmp (cmd, "ALARM") == 0
3252           || stricmp (cmd, "ALARMCLOCK") == 0) {
3253       if (check_access (userhost, target, 0, source) >= 2) {
3254         s = strtok (NULL, " ");
3255         s2 = strtok (NULL, "");
3256         if (s == NULL || s2 == NULL) {
3257           S
3258             ("NOTICE %s :Syntax: <time type: d/h/m><time> <text to say>\n",
3259              source); R;
3260         }
3261         if (strlen (s) < 2) {
3262           S
3263             ("NOTICE %s :Syntax: <time type: d/h/m><time> <text to say>\n",
3264              source); R;
3265         }
3266         if (*s == 'd') {
3267           sn = 86400;
3268           s++;
3269         }
3270         else if (*s == 'h') {
3271           sn = 3600;
3272           s++;
3273         }
3274         else if (*s == 'm') {
3275           sn = 60;
3276           s++;
3277         }
3278         else {
3279           S
3280             ("NOTICE %s :Syntax: <time type: \2d/h/m\2><time> <text to say>\n",
3281              source); R;
3282         }
3283         if (strspn (s, NUMBER_LIST) != strlen (s)) {
3284           S ("NOTICE %s :Time must be a number.\n", source);
3285           R;
3286         }
3287         i = (atoi (s) * sn) + time (NULL);
3288 #ifdef WIN32
3289         sprintf (temp,"%s/%d", DBTIMERS_PATH, (int) i);
3290 #else
3291         snprintf (temp,sizeof(temp), "%s/%d", DBTIMERS_PATH, (int) i);
3292 #endif
3293         log (temp,
3294              "PRIVMSG %s :\2ALARMCLOCK\2 by %s!%s: %s\n",
3295              target, source, userhost, s2);
3296         unixtime = atoi (s) * sn;
3297         if (unixtime > 86400)
3298           S
3299             ("PRIVMSG %s :%s, alarmclock set to go off in %d day%s, %02d:%02d\n",
3300              target, source, unixtime / 86400,
3301              (unixtime / 86400 == 1) ? "" : "s",
3302              (unixtime / 3600) % 24, (unixtime / 60) % 60);
3303         else if (unixtime > 3600)
3304           S
3305             ("PRIVMSG %s :%s, alarmclock set to go off in %d hour%s, %d min%s\n",
3306              target, source, unixtime / 3600,
3307              unixtime / 3600 == 1 ? "" : "s",
3308              (unixtime / 60) % 60,
3309              (unixtime / 60) % 60 == 1 ? "" : "s");
3310         else
3311           S
3312             ("PRIVMSG %s :%s, alarmclock set to go off in %d minute%s, %d sec%s\n",
3313              target, source, unixtime / 60,
3314              unixtime / 60 == 1 ? "" : "s",
3315              unixtime % 60, unixtime % 60 == 1 ? "" : "s");
3316       }
3317     }
3318     else
3319       if (stricmp (cmd, "REPEAT") == 0
3320           || stricmp (cmd, "TIMER") == 0) {
3321       if (check_access (userhost, target, 0, source) >= 3) {
3322         s = strtok (NULL, " ");
3323         s2 = strtok (NULL, " ");
3324         s3 = strtok (NULL, "");
3325         if (s == NULL || s2 == NULL || s3 == NULL) {
3326           L060 (source);
3327           R;
3328         }
3329         sn = atoi (s);
3330         sn2 = atoi (s2);
3331         while (sn > 0) {
3332           S ("%s\n", s3);
3333           sn--;
3334           db_sleep (sn2);
3335         }
3336       }
3337 #ifndef WIN32
3338     }
3339     else
3340       if (stricmp (cmd, "REHASH") == 0
3341           || stricmp (cmd, "RESTART") == 0) {
3342       if (check_access (userhost, target, 0, source) >= 3) {
3343         L062 (dbVersion);
3344 #ifdef WIN32
3345         sprintf (temp,"sleep 2; %s", DARKBOT_BIN);
3346 #else
3347         snprintf (temp,sizeof(temp), "sleep 2; %s", DARKBOT_BIN);
3348 #endif
3349         system (temp);
3350         db_sleep (1);
3351         exit (0);
3352       }
3353 #endif
3354     }
3355     else if (stricmp (cmd, "PING") == 0) {
3356       if (check_access (userhost, target, 0, source) == 0) {
3357         S ("NOTICE %s PONG!\n", source);
3358       }
3359       else
3360         S ("PRIVMSG %s :PONG!\n", target);
3361     }
3362     else if (stricmp (cmd, "HELP") == 0) {
3363       L100 (source, NICK_COMMA, COLON_NICK,
3364             BCOLON_NICK, Mynick, NICK_COMMA, NICK_COMMA);
3365       db_sleep (3);
3366       if (cf (userhost, source, target))
3367         R;
3368       L101 (source, NICK_COMMA, NICK_COMMA, NICK_COMMA);
3369       db_sleep (2);
3370     }
3371     else if (stricmp (cmd, "SETINFO") == 0) {
3372       if (check_access (userhost, target, 0, source) >= 1) {
3373         s = strtok (NULL, "");
3374         if (s == NULL) {
3375           S ("NOTICE %s :%s\n", source, mySetinfo);
3376           R;
3377         }
3378         update_setinfo (userhost, s, source);
3379         save_changes ();
3380       }
3381     }
3382 #if CTCP == 1
3383   }
3384   else if (stricmp (cmd, "\1VERSION\1") == 0) { /* these are #chan
3385                                                  * ctcp's */
3386     if (cf (userhost, source, target))
3387       R;
3388     if (cf (userhost, source, target))
3389       R;
3390     S ("NOTICE %s :\1VERSION %s\1\n", source, VERSION_REPLY);
3391   }
3392   else if (stricmp (cmd, "\1PING") == 0) {
3393     if (cf (userhost, source, target))
3394       R;
3395     if (cf (userhost, source, target))
3396       R;
3397     s2 = strtok (NULL, "");
3398     if (s2 != NULL) {
3399       if (strlen (s2) > 21)
3400         s2[21] = '\0';
3401       S ("NOTICE %s :\1PING %s\n", source, s2);
3402     }
3403 #endif
3404   }
3405   else if (stricmp (cmd, "\2\2DARKBOT") == 0) {
3406     if (Sleep_Toggle == 1)
3407       R;
3408     if (cf (userhost, source, target))
3409       R;
3410     S
3411       ("PRIVMSG %s :%s reporting! My cmdchar is %c\n",
3412        target, dbVersion, *CMDCHAR);}
3413   else
3414     if (stricmp (cmd, NICK_COMMA) == 0
3415         || stricmp (cmd, COLON_NICK) == 0
3416         || stricmp (cmd, BCOLON_NICK) == 0
3417         || stricmp (cmd, Mynick) == 0) {
3418     s = strtok (NULL, " ");
3419     if (s != NULL) {
3420       if (stricmp (s, "WAKEUP") == 0) {
3421         if (Sleep_Toggle == 0)
3422           R;
3423         if (check_access (userhost, target, 0, source) >= SLEEP_LEVEL) {
3424           Sleep_Toggle = 0;
3425           AIL4 = 0;
3426           S ("PRIVMSG %s :%s\n", target, WAKEUP_ACTION);
3427           if (stricmp (sleep_chan, target) != 0)
3428             S ("PRIVMSG %s :%s\n", sleep_chan, WAKEUP_ACTION);
3429           R;
3430         }
3431       }
3432     }
3433     if (Sleep_Toggle == 1)
3434       R;
3435     if (cf (userhost, source, target))
3436       R;
3437     if (s != NULL) {
3438 #ifdef  RANDOM_STUFF
3439       if (stricmp (s, "RANDOMSTUFF") == 0
3440           || stricmp (s, "RANDSTUFF") == 0) {
3441         if (check_access (userhost, target, 0, source) >= RAND_LEVEL) {
3442           s2 = strtok (NULL, "");
3443           if (s2 == NULL) {
3444             L064 (target, source);
3445             R;
3446           }
3447           add_randomstuff (source, target, s2);
3448         }
3449       }
3450       else
3451 #endif
3452         if (stricmp (s, "ADD") == 0
3453             || stricmp (s, "REMEMBER") == 0
3454             || stricmp (s, "SAVE") == 0 || stricmp (s, "STORE") == 0) {
3455 #ifdef  REQ_ACCESS_ADD
3456         if (check_access (userhost, target, 0, source) >= 1) {
3457 #endif
3458           s2 = strtok (NULL, " ");
3459           if (s2 == NULL) {
3460             L065 (target, source);
3461             R;
3462           }
3463           if (strlen (s2) > MAX_TOPIC_SIZE) {
3464             s2[MAX_TOPIC_SIZE] = '\0';
3465             S
3466               ("PRIVMSG %s :%s, topic is over the limit, and has characters truncated.\n",
3467                target, source);
3468           }
3469           s3 = strtok (NULL, "");
3470           if (s3 == NULL) {
3471             L066 (target, source, s2);
3472             R;
3473           }
3474           if (strlen (s3) > MAX_DATA_SIZE)
3475             s3[MAX_DATA_SIZE] = '\0';
3476           strlwr (s2);
3477           if (*s2 == '~') {
3478             S
3479               ("PRIVMSG %s :%s, rdb files can only be called from the data of a topic, they cannot be used in the topic itself.\n",
3480                target, source);
3481             R;
3482           }
3483           if (check_existing_url (source, s2, target) == 1) {
3484             S ("PRIVMSG %s :%s \37%s\37\n", target, EXISTING_ENTRY,
3485                s2);
3486             R;
3487           }
3488 #ifdef  LOG_ADD_DELETES
3489           log (ADD_DELETES,
3490                "[%s] %s!%s ADD %s %s\n", date (), source, userhost,
3491                s2, s3);
3492 #endif
3493           ADDITIONS++;
3494           if (s2[0] == 'i' && s2[1] == 'l' && s2[2] == 'c') {
3495             log (URL2, "%s ([%s] %s!%s): %s\n", s2,
3496                  date (), source, userhost, s3);
3497           }
3498           else
3499             log (URL2, "%s %s\n", s2, s3);
3500           L067 (target, source);
3501 #ifdef  REQ_ACCESS_ADD
3502         }
3503 #endif
3504       }
3505       else if (stricmp (s, "DATE") == 0 || stricmp (s, "TIME") == 0) {
3506         S ("PRIVMSG %s :%s, %s\n", target, source, date ());
3507       }
3508       else if (stricmp (s, "REPLACE") == 0) {
3509 #ifdef  REQ_ACCESS_ADD
3510         if (check_access (userhost, target, 0, source) >= 1) {
3511 #endif
3512           s2 = strtok (NULL, " ");
3513           if (s2 == NULL) {
3514             L068 (target, source);
3515             R;
3516           }
3517           if (strlen (s2) > MAX_TOPIC_SIZE)
3518             s2[MAX_TOPIC_SIZE] = '\0';
3519           s3 = strtok (NULL, "");
3520           if (s3 == NULL) {
3521             L069 (target, source, s2);
3522             R;
3523           }
3524           if (strlen (s3) > MAX_DATA_SIZE)
3525             s3[MAX_DATA_SIZE] = '\0';
3526           strlwr (s2);
3527           if (check_existing_url (source, s2, target) != 1) {
3528             S ("PRIVMSG %s :%s \37%s\37\n", target, NO_ENTRY, s2);
3529             R;
3530           }
3531           delete_url (source, s2, target);
3532 #ifdef  LOG_ADD_DELETES
3533           log (ADD_DELETES,
3534                "[%s] %s!%s REPLACE %s %s\n",
3535                date (), source, userhost, s2, s3);
3536 #endif
3537           ADDITIONS++;
3538           log (URL2, "%s %s\n", s2, s3);
3539           L070 (target, source, s2);
3540 #ifdef  REQ_ACCESS_ADD
3541         }
3542 #endif
3543 #if DO_CHANBOT_CRAP == 1
3544       }
3545       else if (stricmp (s, "PERMBANS?") == 0) {
3546         L071 (target,
3547               (PERMBAN_counter ==
3548                1) ? "is" : "are",
3549               PERMBAN_counter, (PERMBAN_counter == 1) ? "" : "s");
3550 #endif
3551 #ifdef  RANDOM_STUFF
3552       }
3553       else
3554         if (stricmp (s, "RANDOMSTUFF?") == 0
3555             || stricmp (s, "RANDSTUFF?") == 0) {
3556         L073 (target, source, Rand_Stuff);
3557 #endif
3558       }
3559       else if (stricmp (s, "LENGTH") == 0) {
3560         s2 = strtok (NULL, "");
3561         if (s2 == NULL)
3562           R;
3563         L074 (target, source, strlen (s2));
3564       }
3565       else if (stricmp (s, "CHAR") == 0) {
3566         s2 = strtok (NULL, " ");
3567         if (s2 == NULL)
3568           R;
3569         S ("PRIVMSG %s :%s, %c -> %d\n", target, source, s2[0],
3570            s2[0]);
3571       }
3572       else if (stricmp (s, "SEEN") == 0 && SeeN == 1) {
3573         s2 = strtok (NULL, " ");
3574         if (s2 == NULL)
3575           R;
3576         show_seen (s2, source, target);
3577       }
3578       else if (stricmp (s, "SENDQ?") == 0 || stricmp (s, "QUE?") == 0) {
3579         L075 (target, source,
3580               get_sendq_count (2),
3581               (get_sendq_count (2) == 1) ? "" : "s");
3582       }
3583       else if (stricmp (s, "JOINS?") == 0) {
3584         L076 (target, JOINs);
3585       }
3586       else if (stricmp (s, "LOCATION?") == 0) {
3587         L077 (target, (snr == 1) ? "is" : "are",
3588               snr, (snr == 1) ? "" : "s", spr);
3589       }
3590       else if (stricmp (s, "CMDCHAR?") == 0) {
3591         L078 (target, source, *CMDCHAR);
3592       }
3593       else
3594         if (stricmp (s, "DATASEARCH") == 0
3595             || stricmp (s, "DSEARCH") == 0 ||
3596             stricmp (s, "DFIND") == 0) {
3597         s2 = strtok (NULL, "");
3598         if (s2 == NULL) {
3599           L079 (target, s, source);
3600           R;
3601         }
3602         datasearch (source, s2, target);
3603       }
3604       else
3605         if (stricmp (s, "SEARCH") == 0
3606             || stricmp (s, "LOOK") == 0 || stricmp (s, "FIND") == 0) {
3607         s2 = strtok (NULL, " ");
3608         if (s2 == NULL) {
3609           if (stricmp (s, "FIND") == 0) {
3610             S ("PRIVMSG %s :%s, %s?\n", target, TRY_FIND, source);
3611           }
3612           else
3613             L079 (target, s, source);
3614           R;
3615         }
3616         find_url (source, s2, target);
3617       }
3618       else if (stricmp (s, "INFO2") == 0) {
3619         show_info2 (target, source);
3620       }
3621       else if (stricmp (s, "INFO") == 0) {
3622         info (source, target);
3623 #ifdef  DO_MATH_STUFF
3624       }
3625       else if (stricmp (s, "CALC") == 0 || stricmp (s, "MATH") == 0) {
3626         s2 = strtok (NULL, "");
3627         if (s2 == NULL)
3628           R;
3629         if (strlen (s2) > 200)
3630           s2[200] = '\0';
3631         do_math (source, target, s2);
3632 #endif
3633       }
3634       else if (stricmp (s, "SLEEP") == 0 || stricmp (s, "HUSH") == 0) {
3635         if (check_access (userhost, target, 0, source) >= SLEEP_LEVEL) {
3636           Sleep_Toggle = 1;
3637           S ("PRIVMSG %s :%s\n", target, GOSLEEP_ACTION);
3638           strncpy (sleep_chan, target, sizeof(sleep_chan));
3639         }
3640       }
3641       else if (stricmp (s, "UNIXTIME") == 0) {
3642         s2 = strtok (NULL, " ");
3643         if (s2 == NULL)
3644           R;
3645         unixtime = atoi (s2) - time (NULL);
3646         if (unixtime > 86400)
3647           S
3648             ("PRIVMSG %s :%s, %d day%s, %02d:%02d\n",
3649              target, source, unixtime / 86400,
3650              (unixtime / 86400 == 1) ? "" : "s",
3651              (unixtime / 3600) % 24, (unixtime / 60) % 60);
3652         else if (unixtime > 3600)
3653           S
3654             ("PRIVMSG %s :%s, %d hour%s, %d min%s\n",
3655              target, source, unixtime / 3600,
3656              unixtime / 3600 == 1 ? "" : "s",
3657              (unixtime / 60) % 60,
3658              (unixtime / 60) % 60 == 1 ? "" : "s");
3659         else
3660           S
3661             ("PRIVMSG %s :%s, %d minute%s, %d sec%s\n",
3662              target, source, unixtime / 60,
3663              unixtime / 60 == 1 ? "" : "s",
3664              unixtime % 60, unixtime % 60 == 1 ? "" : "s");
3665       }
3666       else if (stricmp (s, "CPU?") == 0) {
3667         getrusage (RUSAGE_SELF, &r_usage);
3668         S
3669           ("PRIVMSG %s :CPU usage: %ld.%06ld, System = %ld.%06ld\n",
3670            target, r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
3671       }
3672       else if (stricmp (s, "DISPLAY") == 0) {
3673         s2 = strtok (NULL, " ");
3674         if (s2 == NULL)
3675           R;
3676         display_url (target, source, s2);
3677 #ifndef WIN32
3678         }
3679         else if (stricmp (s, "UPTIME") == 0) {
3680         snprintf (temp,sizeof(temp), "uptime\n");
3681         S ("PRIVMSG %s :Uptime: %s\n", target, run_program (temp));
3682         }
3683         else if (stricmp (s, "OS") == 0) {
3684         snprintf (temp,sizeof(temp), "uname\n");
3685         S ("PRIVMSG %s :I am running %s\n", target,
3686            run_program (temp));
3687         }
3688         else if (stricmp (s, "MEM") == 0 || stricmp (s, "RAM") == 0) {
3689         snprintf (temp, sizeof(temp),"ps -ux | grep %s\n", DARKBOT_BIN);
3690         S ("PRIVMSG %s :ps: %s\n", target, run_program (temp));
3691         }
3692         else if (stricmp (s, "RDB") == 0) {
3693         s2 = strtok (NULL, "");
3694         if (s2 == NULL) {
3695           snprintf (temp,sizeof(temp), "ls dat/*.rdb | wc\n");
3696           S ("PRIVMSG %s :RDB: %s\n", target, run_program (temp));
3697         }
3698         else {
3699           if (strspn (s2, SAFE_LIST) != strlen (s2)) {
3700             S
3701               ("PRIVMSG %s :%s, rdb files are made up of letters and or numbers, no other text is accepted.\n",
3702                target, source);
3703             R;
3704           }
3705           snprintf (temp,sizeof(temp),"ls -la dat/*.rdb | grep %s | tail 3\n", s2);
3706           S ("PRIVMSG %s :%s\n", target, run_program (temp));
3707         }
3708 #endif
3709       }
3710       else
3711         if (stricmp (s, "DELETE") == 0
3712             || stricmp (s, "REMOVE") == 0
3713             || stricmp (s, "FORGET") == 0 || stricmp (s, "DEL") == 0) {
3714 #ifdef  REQ_ACCESS_DEL
3715         if (check_access (userhost, target, 0, source) >= 1) {
3716 #endif
3717           s2 = strtok (NULL, " ");
3718           if (s2 == NULL) {
3719             S ("PRIVMSG %s :%s what, %s?\n", target, s, source);
3720             R;
3721           }
3722           if (strlen (s2) > MAX_TOPIC_SIZE)
3723             s2[MAX_TOPIC_SIZE] = '\0';
3724 #ifdef  LOG_ADD_DELETES
3725           log (ADD_DELETES, "[%s] %s!%s DEL %s\n",
3726                date (), source, userhost, s2);
3727 #endif
3728           if (*s2 == '~') {     /* need level 2 to delete .rdb files */
3729             if (check_access (userhost, target, 0, source) >= 2) {
3730               delete_url (source, s2, target);
3731             }
3732             R;
3733           }
3734           delete_url (source, s2, target);
3735 #ifdef  REQ_ACCESS_DEL
3736         }
3737 #endif
3738       }
3739       else if (stricmp (s, "TELL") == 0) {
3740         s2 = strtok (NULL, " ");
3741         if (s2 == NULL) {
3742           L085 (target, source);
3743           R;
3744         }
3745         s3 = strtok (NULL, " ");
3746         if (s3 == NULL) {
3747           L083 (target, source, s2);
3748           R;
3749         }
3750         if (stricmp (s3, Mynick) == 0)
3751           R;                    /* don't bother telling
3752                                  * myself about stuff */
3753         if (stricmp (s3, "ABOUT") == 0) {
3754           s4 = strtok (NULL, " ");
3755           if (s4 == NULL) {
3756             L084 (target, source, s2);
3757             R;
3758           }
3759           strlwr (s4);
3760           show_url (s2, get_multiword_topic (s4), target, 1, 0,
3761                     userhost, 1);
3762         }
3763         else {
3764           strlwr (s3);
3765           show_url (s2, get_multiword_topic (s3), target, 1, 0,
3766                     userhost, 1);
3767         }
3768       }
3769       else
3770         if (stricmp (s, "WHERE") == 0
3771             || stricmp (s, "WHO") == 0 || stricmp (s, "WHAT") == 0) {
3772         s2 = strtok (NULL, " ");
3773         if (s2 == NULL) {
3774           L086 (target, source);
3775           R;
3776         }
3777         s3 = strtok (NULL, " ");
3778         if (s3 == NULL)
3779           R;
3780         strlwr (s3);
3781         ptr3 = strchr (s3, '?');
3782         if (ptr3 != NULL)
3783           memmove (ptr3, ptr3 + 1, strlen (ptr3 + 1) + 1);
3784         ptr3 = strchr (s3, '!');
3785         if (ptr3 != NULL)
3786           memmove (ptr3, ptr3 + 1, strlen (ptr3 + 1) + 1);
3787         if (stricmp (s3, "A") == 0 || stricmp (s3, "AN") == 0) {
3788           s4 = strtok (NULL, " ");
3789           if (s4 == NULL) {
3790             L087 (target, s, s2, s3, *CMDCHAR);
3791             R;
3792           }
3793           show_url (source,
3794                     get_multiword_topic (s4), target, 1, 0, userhost,
3795                     0);
3796         }
3797         else
3798           show_url (source,
3799                     get_multiword_topic (s3), target, 1, 0, userhost,
3800                     0);
3801       }
3802       else
3803         show_url (source,
3804                   get_multiword_topic (s), target, 1, 0, userhost, 0);
3805     }
3806     else
3807       S ("PRIVMSG %s :%s\n", target, WHUT);
3808 #if GENERAL_QUESTIONS == 1
3809   }
3810   else {
3811     if (Sleep_Toggle == 1)
3812       R;
3813     show_url (source, get_multiword_topic (cmd), target, 0, 1,
3814               userhost, 0);
3815 #endif
3816     i = 0;
3817   }
3818 }
3819 
3820 void
gs26()3821 gs26 ()
3822 {
3823   long i = 0;
3824   struct sl124 *c;
3825   c = sh124;
3826   spr++;
3827   if (spr > snr)
3828     spr = 1;
3829   while (c != NULL) {
3830     i++;
3831     if (i == spr) {
3832       strncpy (BS, c->name, sizeof(BS));
3833       BP = c->port;
3834     }
3835     c = c->next;
3836   }
3837 }
3838 
3839 void
add_s25(char * server,long port)3840 add_s25 (char *server, long port)
3841 {
3842   struct sl124 *n;
3843   n = (struct sl124 *)
3844     malloc (sizeof (struct sl124));
3845   if (n == NULL) {
3846     log ("error.log", "AHHH! No ram left! in add_s25!\n");
3847     R;
3848   }
3849   memset (n, 0, sizeof (struct sl124));
3850   snr++;
3851   if (n != NULL) {
3852     strncpy (n->name, server, sizeof(n->name));
3853     n->port = port;
3854     n->next = sh124;
3855     sh124 = n;
3856   }
3857 }
3858 
3859 void
show_url(char * nick,char * topic,char * target,long donno,long floodpro,char * uh,long no_pipe)3860 show_url (char *nick, char *topic,
3861           char *target, long donno,
3862           long floodpro, char *uh, long no_pipe)
3863 {
3864   FILE *fp;
3865   long x = 0, length = 0, toggle = 0, A =
3866     0, gotit = 0, D = 0, F = 0, Tog = 0;
3867   char b[STRING_LONG], *subj, *ptr,
3868     temp[STRING_LONG] = "", Data[STRING_LONG] = "", *ptr8 = "";
3869   char crm1[STRING_LONG], crm2[STRING_LONG], bFirst = 1;
3870 
3871   strlwr (topic);
3872 
3873   /* removes the question mark */
3874   if ((ptr = strchr (topic, '?')) != NULL)
3875     memmove (ptr, ptr + 1, strlen (ptr + 1) + 1);
3876 
3877   if ((fp = fopen (URL2, "r")) == NULL) {
3878     if (donno == 1)
3879       L003 (nick, URL2);
3880     R;
3881   }
3882   while (fgets (b, STRING_LONG, fp)) {
3883     x++;
3884     stripline (b);
3885     subj = strtok (b, " ");
3886     if (subj == NULL)
3887       continue;
3888     ptr = strtok (NULL, "");
3889     if (ptr == NULL)
3890       continue;
3891     if (stricmp (subj, topic) == 0 || !match_wild (subj, topic) == 0) {
3892       QUESTIONS++;
3893       if (floodpro == 1)
3894         if (cf (uh, nick, nick)) {
3895           fclose (fp);
3896           R;
3897         }
3898       gotit = 1;
3899       if (*ptr == '+') {
3900         ptr++;
3901         A = 1;
3902       }
3903       else if (*ptr == '-') {
3904         if (strstr (nick, "|") != NULL)
3905           R;
3906         if (no_pipe == 1) {
3907           fclose (fp);
3908           R;
3909         }
3910         ptr++;
3911         D = 1;
3912       }
3913       else if (*ptr == '~') {
3914         ptr++;
3915         fclose (fp);
3916         do_randomtopic (target, ptr, nick, topic);
3917         return;
3918       }
3919       length = strlen (ptr);
3920       if (length > 3) {
3921         if (ptr[0] == 'i' && ptr[1] == 'l' && ptr[2] == 'c') {
3922           toggle++;
3923         }
3924       }
3925       while (length > 0) {
3926         length--;
3927         if (Tog == 1) {
3928           Tog = 0;
3929           if (ptr[length] == 'N') {     /* nick */
3930             toggle++;
3931 #ifdef WIN32
3932                 sprintf (temp,"%s%s", nick, Data);
3933           }
3934           else if (ptr[length] == 'C') {        /* chan */
3935             toggle++;
3936             sprintf (temp,"%s%s", target, Data);
3937 #else
3938             snprintf (temp,sizeof(temp), "%s%s", nick, Data);
3939           }
3940           else if (ptr[length] == 'C') {        /* chan */
3941             toggle++;
3942             snprintf (temp,sizeof(temp), "%s%s", target, Data);
3943 #endif
3944           }
3945           else
3946             if (ptr[length] == '1'
3947                 || ptr[length] == '2'
3948                 || ptr[length] == '3'
3949                 || ptr[length] == '4'
3950                 || ptr[length] == '5'
3951                 || ptr[length] == '6'
3952                 || ptr[length] == '7'
3953                 || ptr[length] == '8' || ptr[length] == '9') {
3954             toggle++;
3955             /* The first time around, we just store the topic in a
3956                "safe place" */
3957             if (bFirst == 1) {
3958               strncpy (crm1, topic, sizeof(crm1));
3959               bFirst = 0;
3960             }
3961             /* Each time around, get a new copy from the "safe place." */
3962             strncpy (crm2, crm1, sizeof(crm2));
3963 #ifdef WIN32
3964                 sprintf (temp,"%s%s", get_word (ptr[length], crm2),
3965                      Data);
3966           }
3967           else if (ptr[length] == 'H') {        /* u@h of user */
3968             toggle++;
3969             sprintf (temp,"%s%s", uh, Data);
3970           }
3971           else if (ptr[length] == 'h') {        /* u@h (no ident) */
3972             toggle++;
3973             if (*uh == '~') {
3974               *uh++;
3975             }
3976             sprintf (temp,"%s%s", uh, Data);
3977           }
3978           else if (ptr[length] == 'T') {        /* time */
3979             toggle++;
3980             sprintf (temp,"%s%s", date (), Data);
3981           }
3982           else if (ptr[length] == 't') {        /* unixtime */
3983             toggle++;
3984             sprintf (temp,"%d%s", time (NULL), Data);
3985           }
3986           else if (ptr[length] == 'W') {        /* WWW page */
3987             toggle++;
3988             sprintf (temp,"http://darkbot.net%s", Data);
3989           }
3990           else if (ptr[length] == 'S') {        /* server */
3991             toggle++;
3992             sprintf (temp,"%s%s", BS, Data);
3993           }
3994 #else
3995             snprintf (temp, sizeof(temp), "%s%s", get_word (ptr[length], crm2),
3996                      Data);
3997           }
3998           else if (ptr[length] == 'H') {        /* u@h of user */
3999             toggle++;
4000             snprintf (temp, sizeof(temp), "%s%s", uh, Data);
4001           }
4002           else if (ptr[length] == 'h') {        /* u@h (no ident) */
4003             toggle++;
4004             if (*uh == '~') {
4005               *uh++;
4006             }
4007             snprintf (temp, sizeof(temp), "%s%s", uh, Data);
4008           }
4009           else if (ptr[length] == 'T') {        /* time */
4010             toggle++;
4011             snprintf (temp,sizeof(temp), "%s%s", date (), Data);
4012           }
4013           else if (ptr[length] == 't') {        /* unixtime */
4014             toggle++;
4015             snprintf (temp,sizeof(temp), "%d%s", time (NULL), Data);
4016           }
4017           else if (ptr[length] == 'W') {        /* WWW page */
4018             toggle++;
4019             snprintf (temp,sizeof(temp), "http://darkbot.net%s", Data);
4020           }
4021           else if (ptr[length] == 'S') {        /* server */
4022             toggle++;
4023             snprintf (temp,sizeof(temp), "%s%s", BS, Data);
4024           }
4025 #endif
4026           else if (ptr[length] == 'R') {        /* rand */
4027             toggle++;
4028             /* The first time around, we just store the topic in a
4029                "safe place" */
4030             if (bFirst == 1) {
4031               strncpy (crm1, topic, sizeof(crm1));
4032               bFirst = 0;
4033             }
4034 #ifdef Win32
4035                 sprintf (temp,"%s%s", get_rand_nick (target),
4036 Data);
4037           }
4038           else if (ptr[length] == 'P') {        /* port */
4039             toggle++;
4040             sprintf (temp,"%d%s", (int) BP, Data);
4041           }
4042           else if (ptr[length] == 'Q') {        /* question */
4043             toggle++;
4044             sprintf (temp,"%s%s", revert_topic (topic),
4045 Data);
4046           }
4047           else if (ptr[length] == 'V') {        /* version */
4048             toggle++;
4049             sprintf (temp,"%s%s", dbVersion, Data);
4050           }
4051           else if (ptr[length] == '!') {        /* cmdchar */
4052             toggle++;
4053             sprintf (temp,"%c%s", *CMDCHAR, Data);
4054           }
4055           else if (ptr[length] == 'B') {        /* mynick */
4056             toggle++;
4057             sprintf (temp,"%s%s", Mynick, Data);
4058           }
4059           else
4060             sprintf (temp,"%c~%s", ptr[length], Data);
4061         }
4062         else if (ptr[length] == '~') {
4063           Tog = 1;
4064         }
4065         else
4066           sprintf (temp,"%c%s", ptr[length], Data);
4067 #else
4068       snprintf (temp,sizeof(temp), "%s%s", get_rand_nick (target),
4069 Data);
4070           }
4071           else if (ptr[length] == 'P') {        /* port */
4072             toggle++;
4073             snprintf (temp,sizeof(temp), "%d%s", (int) BP, Data);
4074           }
4075           else if (ptr[length] == 'Q') {        /* question */
4076             toggle++;
4077             snprintf (temp,sizeof(temp), "%s%s", revert_topic (topic),
4078 Data);
4079           }
4080           else if (ptr[length] == 'V') {        /* version */
4081             toggle++;
4082             snprintf (temp,sizeof(temp), "%s%s", dbVersion, Data);
4083           }
4084           else if (ptr[length] == '!') {        /* cmdchar */
4085             toggle++;
4086             snprintf (temp,sizeof(temp), "%c%s", *CMDCHAR, Data);
4087           }
4088           else if (ptr[length] == 'B') {        /* mynick */
4089             toggle++;
4090             snprintf (temp,sizeof(temp), "%s%s", Mynick, Data);
4091           }
4092           else
4093             snprintf (temp,sizeof(temp), "%c~%s", ptr[length], Data);
4094         }
4095         else if (ptr[length] == '~') {
4096           Tog = 1;
4097         }
4098         else
4099           snprintf (temp,sizeof(temp), "%c%s", ptr[length], Data);
4100 #endif
4101         strncpy (Data, temp, sizeof(Data));
4102       }                         /* While */
4103       if (D == 1) {
4104         ptr8 = strtok (Data, "|");
4105         while (ptr8 != NULL) {
4106           if (ptr8[0] == ' ')
4107             ptr8++;
4108           if (ptr8[0] == 'B' && ptr8[1] == 'A' && ptr8[2] == 'N') {     /* ban user */
4109             S ("MODE %s +b *%s\n", target, uh);
4110           }
4111           if (ptr8[0] == 'T' && ptr8[1] == 'E' && ptr8[2] == 'M' &&
4112               ptr8[3] == 'P' && ptr8[4] == 'B' && ptr8[5] == 'A' &&
4113               ptr8[6] == 'N') { /* temp ban user for 60 sec */
4114             S ("MODE %s +b *%s\n", target, uh);
4115 #ifdef WIN32
4116                 sprintf (temp,"%s/%d", DBTIMERS_PATH, time (NULL) + 60);
4117 #else
4118             snprintf (temp, sizeof(temp),"%s/%d", DBTIMERS_PATH, time (NULL) + 60);
4119 #endif
4120             log (temp, "MODE %s -b *%s\n", target, uh);
4121           }
4122           ptr8[0] = tolower (ptr8[0]);
4123           ptr8[1] = tolower (ptr8[1]);
4124           if (ptr8[0] == 'p' && ptr8[1] == 'r')
4125             F = 1;
4126           if (ptr8[0] == 'k' && ptr8[1] == 'i')
4127             F = 1;
4128           if (ptr8[0] == 'n' && ptr8[1] == 'o')
4129             F = 1;
4130           if (ptr8[0] == 't' && ptr8[1] == 'o')
4131             F = 1;
4132           if (F == 1)
4133             S ("%s\n", ptr8);
4134           F = 0;
4135           ptr8 = strtok (NULL, "|");
4136         }
4137         fclose (fp);
4138         R;
4139       }
4140       if (toggle == 0) {
4141         if (A == 0) {
4142           S ("PRIVMSG %s :%s%s\n", target, rand_reply (nick), Data);
4143         }
4144         else
4145           S ("PRIVMSG %s :\1ACTION %s\1\n", target, Data);
4146       }
4147       else if (A == 0) {
4148         S ("PRIVMSG %s :%s\n", target, Data);
4149       }
4150       else
4151         S ("PRIVMSG %s :\1ACTION %s\1\n", target, Data);
4152       fclose (fp);
4153       R;
4154     }                           /* Subject match */
4155   }
4156   fclose (fp);
4157   if (donno == 1) {
4158     if (strlen (topic) > 3) {
4159       strlwr (topic);
4160       if (topic[0] == 'i' && topic[1] == 'l' && topic[2] == 'c') {
4161         S
4162           ("PRIVMSG %s :%s, I found no matching ILC for that channel.\n",
4163            target, nick);
4164         R;
4165       }
4166     }
4167     S ("PRIVMSG %s :%s, %s\n", target, nick, DONNO_Q);
4168   }
4169 }
4170 
4171 /**
4172  * 6/23/00 Dan:
4173  * - Moved declaration of newact into #ifdef
4174  */
4175 int
main(int argc,char ** argv)4176 main (int argc, char **argv)
4177 {
4178   char temp[STRING_SHORT];
4179   struct timeval timeout;
4180   fd_set fdvar;
4181 #if (SGI == 1) || (NEED_LIBC5 == 1)
4182   struct sigaction newact;
4183 #endif
4184 #ifdef  DEBUG
4185   DebuG = 1;
4186 #endif
4187 #ifndef WIN32                   /* not win32 */
4188 #endif
4189   get_s ();
4190   srand (time (0));
4191   uptime = time (NULL);
4192   if (argv[1] != NULL) {
4193     if (stricmp (argv[1], "-SEEN") == 0) {
4194       SeeN = 1;
4195       printf ("\nSEEN ENABLED.\n\n");
4196     }
4197     else if (stricmp (argv[1], "-DEBUG") == 0) {
4198       DebuG = 1;
4199       printf ("\nDEBUG ENABLED.\n\n");
4200     }
4201     else {
4202       printf ("\n\n%s HELP:\n\n", dbVersion);
4203       printf ("%s          (Launches Darkbot to IRC)\n", argv[0]);
4204       printf
4205         ("%s -SEEN    (Enables SEEN [Even if SEEN is undefined])\n",
4206          argv[0]);
4207       printf ("%s -DEBUG   (Launch in debug mode)\n", argv[0]);
4208       exit (0);
4209     }
4210   }
4211   strncpy (DARKBOT_BIN, argv[0], sizeof(DARKBOT_BIN));
4212 #if (SGI == 1) || (NEED_LIBC5 == 1)
4213   newact.sa_handler = sig_alrm;
4214   sigemptyset (&newact.sa_mask);
4215   newact.sa_flags = 0;
4216   sigaction (SIGALRM, &newact, NULL);
4217   newact.sa_handler = sig_segv;
4218   sigemptyset (&newact.sa_mask);
4219   newact.sa_flags = 0;
4220   sigaction (SIGSEGV, &newact, NULL);
4221   newact.sa_handler = sig_hup;
4222   sigemptyset (&newact.sa_mask);
4223   newact.sa_flags = 0;
4224   sigaction (SIGHUP, &newact, NULL);
4225 #else /* ----------------------- */
4226   signal (SIGALRM, sig_alrm);
4227   signal (SIGSEGV, sig_segv);
4228   signal (SIGHUP, sig_hup);
4229 #endif
4230 #ifndef WIN32
4231 #ifdef  FORK
4232   if (fork ())
4233     exit (0);
4234 #endif
4235 #endif
4236 #ifdef  RANDOM_STUFF
4237   get_rand_stuff_time ();
4238 #endif
4239   printf ("\n\n\n\n\n");
4240   printf (" ,-----------------------------------------------,\n");
4241   printf (" | Darkbot (C) Jason Hamilton http://darkbot.net |\n");
4242   printf (" `-----------------------------------------------'\n\n");
4243 #ifndef WIN32
4244 #ifndef DISALLOW_COUNT
4245   snprintf (temp,sizeof(temp), "lynx -source http://darkbot.net/cgi/laun.cgi?%s &",
4246            dbVersion);
4247   system (temp);
4248 #endif
4249   sprintf (temp,"echo \"%d\" > %s.pid", getpid (),
4250 DARKBOT_BIN);
4251   system (temp);
4252 #endif
4253 #ifndef WIN32
4254   db_sleep (2);
4255 #endif
4256 #ifndef WIN32
4257 #ifdef  SORT
4258   printf ("\nSorting database...\n");
4259   snprintf (temp, sizeof(temp), "sort %s -o %s\n", URL2, URL2);
4260   system (temp);
4261 #endif
4262 #endif
4263   load_helpers ();
4264   raw_now ("SERVERS");
4265   raw_now ("SETUP");
4266   raw_now ("PERMBAN");
4267   gs26 ();
4268 #ifndef WIN32
4269 #endif
4270   alarm (AIL);
4271   printf ("\nConnecting to %s:%d ...\n", BS, (int) BP);
4272   socketfd = get_connection (BS, VHOST, BP);
4273   if (socketfd == -1) {
4274     exit (0);
4275   }
4276   init_bot ();
4277   while (1) {
4278     timeout.tv_sec = WSEC;
4279     timeout.tv_usec = USEC;
4280     FD_ZERO (&fdvar);
4281     FD_SET (socketfd, &fdvar);
4282     switch (select
4283             (NFDBITS, &fdvar, (fd_set *) 0, (fd_set *) 0, &timeout)) {
4284     case 0:
4285       break;
4286     case -1:
4287       if (!alarmed) {
4288         db_sleep (RECHECK);
4289       }
4290       else
4291         alarmed = 0;
4292       break;
4293     default:
4294       parse_server_msg (&fdvar);
4295       break;
4296     }
4297   }
4298 }
4299 
4300 void
sig_hup(int notUsed)4301 sig_hup (int notUsed)
4302 {
4303   char temp[STRING_LONG];
4304 #ifdef  WIN32
4305   S ("QUIT :Window killed - %s terminating\n", dbVersion);
4306   sprintf (temp,"sleep 2; %s", DARKBOT_BIN);
4307 #else
4308   S ("QUIT :SIGHUP - Restarting %s ...\n", dbVersion);
4309   snprintf (temp, sizeof(temp), "sleep 2; %s", DARKBOT_BIN);
4310 #endif
4311   system (temp);
4312   db_sleep (1);
4313   exit (0);
4314 }
4315 
4316 void
sig_alrm(int notUsed)4317 sig_alrm (int notUsed)
4318 {
4319   alarmed = 1;
4320   alarm (AIL);
4321   check_dbtimers ();            /* timers :) */
4322   AIL8 += AIL;
4323   if (AIL8 >= SEND_DELAY) {
4324     AIL8 = 0;
4325     Send ();
4326   }
4327   LastInput += AIL;
4328   if (LastInput >= 500) {
4329     LastInput = 0;
4330 #if CHECK_STONED == 1
4331     L088 (BS);
4332 #ifdef  WIN32
4333     printf ("\nNo responce from %s in 5 mins, reconnecting...\n", BS);
4334 #endif
4335     gs26 ();
4336     socketfd = get_connection (BS, VHOST, BP);
4337     init_bot ();
4338 #endif
4339   }
4340   AIL10 += AIL;
4341   if (AIL10 >= 900) {           /* 15 mins */
4342     AIL10 = 0;
4343     if (MARK_CHANGE == 1) {
4344       MARK_CHANGE = 0;
4345       save_setup ();            /* save settings */
4346     }
4347   }
4348   AIL666 += AIL;
4349   if (AIL666 >= 60) {           /* 60 sec timer */
4350     AIL666 = 0;
4351     S ("PING :%s\n", BS);
4352   }
4353   AIL9 += AIL;
4354   if (AIL9 >= 30) {
4355     AIL9 = 0;
4356     if (stricmp (s_Mynick, Mynick) != 0) {
4357       S ("NICK %s\n", s_Mynick);
4358       strncpy (Mynick, s_Mynick, sizeof(Mynick));
4359 #ifdef WIN32
4360       sprintf (NICK_COMMA,"%s,", Mynick);
4361       sprintf (COLON_NICK,"%s:", Mynick);
4362       sprintf (BCOLON_NICK,"%s\2:\2", Mynick);
4363 #else
4364       snprintf (NICK_COMMA,sizeof(NICK_COMMA), "%s,", Mynick);
4365       snprintf (COLON_NICK,sizeof(COLON_NICK), "%s:", Mynick);
4366       snprintf (BCOLON_NICK,sizeof(BCOLON_NICK), "%s\2:\2", Mynick);
4367 #endif
4368     }
4369   }
4370   if (Sleep_Toggle == 1) {
4371     AIL4 += AIL;
4372     if (AIL4 >= SLEEP_TIME) {
4373       Sleep_Toggle = 0;
4374       AIL4 = 0;
4375       L089 (sleep_chan);
4376     }
4377   }
4378   AIL2 += AIL;
4379   AIL3 += AIL;
4380 #ifdef  RANDOM_STUFF
4381   Rand_Idle++;
4382   if (RAND_IDLE <= Rand_Idle) {
4383     Rand_Idle = 0;
4384     do_random_stuff ();
4385     get_rand_stuff_time ();
4386   }
4387   Rand_Stuff -= AIL;
4388   if (Rand_Stuff <= 0) {
4389     if (Sleep_Toggle != 1)
4390       do_random_stuff ();
4391     get_rand_stuff_time ();
4392   }
4393 #endif
4394   if (AIL3 >= AUTOTOPIC_TIME) {
4395     AIL3 = 0;
4396     do_autotopics ();
4397   }
4398   AIL5 += AIL;
4399   if (AIL5 >= 600) {
4400 #ifdef  ANTI_IDLE
4401     S ("PRIVMSG ! :\2\n");
4402 #endif
4403     AIL5 = 0;
4404   }
4405   if (AIL2 >= 300) {
4406     AIL2 = 0;
4407 #if STATUS == 1
4408     S ("LUSERS\n");
4409 #endif
4410     S ("JOIN %s\n", CHAN);
4411     S ("MODE %s %s\n", Mynick, DEFAULT_UMODE);
4412     reset_ ();
4413     save_changes ();
4414   }
4415 }
4416 
4417 void
sig_segv(int notUsed)4418 sig_segv (int notUsed)
4419 {
4420   long uptime2 = 0, p = 0;
4421   uptime2 = time (NULL) - uptime;
4422   printf
4423     ("ERROR! Aborting program. (SIG_SEGV) Uptime: %d hour%s, %d min%s\n",
4424      (int) (uptime2 / 3600),
4425      (uptime2 / 3600 == 1) ? "" : "s",
4426      (int) ((uptime2 / 60) % 60),
4427      ((uptime2 / 60) % 60) == 1 ? "" : "s");
4428   Snow
4429     ("QUIT :Caught SIG_SEGV! Aborting connection. Uptime: %d hour%s, %d min%s\n",
4430      uptime2 / 3600,
4431      uptime2 / 3600 == 1 ? "" : "s",
4432      (uptime2 / 60) % 60, (uptime2 / 60) % 60 == 1 ? "" : "s");
4433   db_sleep (2);
4434   p = getpid ();
4435   if (fork () > 0) {
4436     log ("error.log",
4437          "Caught SIGSEGV.. Sent kill -3 and kill -9...\n");
4438     kill (p, 3);
4439     kill (p, 9);
4440   }
4441   db_sleep (1);
4442   exit (0);
4443 }
4444 
4445 int
get_sendq_count(long toggle)4446 get_sendq_count (long toggle)
4447 {
4448   struct sendq *c;
4449   long i = 0, x = 0;
4450   c = sendqhead;
4451   while (c != NULL) {
4452     i++;
4453     if (c->data[0] == 'P' && c->data[1] == 'R' && c->data[2] == 'I')
4454       x++;
4455     else
4456       if (c->data[0] == 'N'
4457           && c->data[1] == 'O' && c->data[2] == 'T') x++;
4458     c = c->next;
4459   }
4460   if (toggle == 1)
4461     clear_sendq (i, 1);
4462   if (toggle == 2)
4463     R i;
4464   if (i < OUTPUT1_COUNT)
4465     SEND_DELAY = OUTPUT1_DELAY;
4466   else if (i < OUTPUT2_COUNT)
4467     SEND_DELAY = OUTPUT2_DELAY;
4468   else
4469     SEND_DELAY = OUTPUT3_DELAY;
4470   if (x > OUTPUT_PURGE_COUNT)
4471     clear_sendq (x, 0);
4472   R i;
4473 }
4474 
4475 void
clear_sendq(long count,long toggle)4476 clear_sendq (long count, long toggle)
4477 {
4478   long i = 0;
4479   i = count;
4480   while (i > 1) {
4481     i--;
4482     del_sendq (1);
4483   }
4484   send_tog = 1;
4485   if (toggle != 1)
4486     L090 (CHAN, count);
4487 }
4488 
4489 void
init_bot()4490 init_bot ()
4491 {
4492   get_sendq_count (1);
4493   Snow ("NICK %s\n", Mynick);
4494   strlwr (UID);
4495   Snow ("USER %s %d %d :%s \2%d\2\n", UID,
4496         time (NULL), time (NULL), REALNAME, NUM_HELPER);
4497 }
4498 
4499 /**
4500  * TODO: No function should ever be this long...move to the Command Pattern
4501  */
4502 void
parse(char * line)4503 parse (char *line)
4504 {
4505   char *s, *s1, *s2, *s3, *cmd, *ptr, *s4;
4506   long TOG = 0, seen_value = 0;
4507   LastInput = 0;
4508   if (DebuG == 1)
4509     printf ("IN :%s\n", line);
4510 #ifdef  DEBUG2
4511   log ("darkbot_debug.log", "IN :%s\n", line);
4512 #endif
4513   stripline (line);
4514   s = strtok (line, " ");
4515   if (stricmp (s, "PING") == 0) {
4516     s1 = strtok (NULL, " ");
4517     Snow ("PONG %s\n", s1);
4518   }
4519   else if (stricmp (s, "ERROR") == 0) {
4520     s1 = strtok (NULL, "");
4521     if (s1 != NULL) {
4522       if (strstr (s1, "Excess Flood") != NULL) {
4523         socketfd = get_connection (BS, VHOST, BP);
4524         init_bot ();
4525       }
4526       else if (strstr (s1, "throttled") != NULL) {
4527         gs26 ();
4528         socketfd = get_connection (BS, VHOST, BP);
4529         init_bot ();
4530       }
4531       else if (strstr (s1, "oo many c") != NULL) {
4532         gs26 ();
4533         socketfd = get_connection (BS, VHOST, BP);
4534         init_bot ();
4535       }
4536       else if (strstr (s1, "o more c") != NULL) {
4537         gs26 ();
4538         socketfd = get_connection (BS, VHOST, BP);
4539         init_bot ();
4540       }
4541       else {
4542         S ("QUIT :Caught ERROR from %s :(\n", BS);
4543         db_sleep (5);
4544         gs26 ();
4545         socketfd = get_connection (BS, VHOST, BP);
4546         init_bot ();
4547       }
4548     }
4549   }
4550   else if (strstr (s, "!") == NULL) {   /* From Server */
4551     cmd = strtok (NULL, " ");
4552     if (stricmp (cmd, "004") == 0) {    /* Connected! */
4553       save_changes ();
4554       s2 = strtok (NULL, " ");  /* Copy the current nick */
4555       strncpy (Mynick, s2, sizeof(Mynick));
4556 #ifdef WIN32
4557       sprintf (NICK_COMMA, "%s,", Mynick);
4558       sprintf (COLON_NICK,"%s:", Mynick);
4559       sprintf (BCOLON_NICK,"%s\2:\2", Mynick);
4560 #else
4561       snprintf (NICK_COMMA,sizeof(NICK_COMMA), "%s,", Mynick);
4562       snprintf (COLON_NICK,sizeof(COLON_NICK), "%s:", Mynick);
4563       snprintf (BCOLON_NICK,sizeof(BCOLON_NICK), "%s\2:\2", Mynick);
4564 #endif
4565       S ("JOIN %s\n", CHAN);
4566       db_sleep (2);
4567       s2 = strtok (NULL, " ");  /* Got server name */
4568       printf
4569         ("%s has connected to %s! [%d pid]\n", Mynick, s2, getpid ());}
4570     else if (stricmp (cmd, "315") == 0) {
4571 #if DISPLAY_SYNC == 1
4572       s2 = strtok (NULL, " ");  /*mynick */
4573       strncpy (Mynick, s2, sizeof(Mynick));
4574       s2 = strtok (NULL, " ");  /* chan */
4575       S ("PRIVMSG %s :Sync with %s completed.\n", s2, s2);
4576 #endif
4577     }
4578     else if (stricmp (cmd, "311") == 0) {
4579       s1 = strtok (NULL, " ");
4580       s1 = strtok (NULL, " ");
4581       s1 = strtok (NULL, " ");
4582       s1 = strtok (NULL, " ");
4583       strncpy (g_host, s1, sizeof(g_host));
4584     }
4585     else if (stricmp (cmd, "319") == 0) {
4586       s1 = strtok (NULL, " ");
4587       s1 = strtok (NULL, " ");
4588       s2 = strtok (NULL, "");
4589       if (*s2 == ':')
4590         s2++;
4591       strlwr (s2);
4592       if (strstr (s2, "arez") != NULL)
4593         TOG = 1;
4594       if (strstr (s2, "kidd") != NULL)
4595         TOG = 1;
4596       if (strstr (s2, "hack") != NULL)
4597         TOG = 1;
4598       if (strstr (s2, "sex") != NULL)
4599         TOG = 1;
4600       if (strstr (s2, "fuck") != NULL)
4601         TOG = 1;
4602       if (strstr (s2, "porn") != NULL)
4603         TOG = 1;
4604       if (strstr (s2, "pic") != NULL)
4605         TOG = 1;
4606       if (TOG == 1) {
4607         S ("NOTICE @%s :%s is on \2%s\2\n", g_chan, s1, s2);
4608         R;
4609       }
4610     }
4611     else
4612       if (stricmp (cmd, "432") == 0
4613           || stricmp (cmd, "468") == 0) {  /* Invalid nick/user */
4614       s2 = strtok (NULL, "");
4615       printf ("Server Reported error %s\n\nDarkbot exiting.\n", s2);
4616       db_sleep (2);
4617       exit (0);
4618     }
4619     else if (stricmp (cmd, "376") == 0) {
4620       raw_now ("PERFORM");      /* End of MOTD, run
4621                                  * perform_now() */
4622     }
4623     else if (stricmp (cmd, "482") == 0) {
4624 #if BITCH_ABOUT_DEOP == 1
4625       s2 = strtok (NULL, " ");  /* mynick */
4626       strncpy (Mynick, s2, sizeof(Mynick));
4627       s2 = strtok (NULL, " ");  /* chan */
4628       S ("PRIVMSG %s :%s\n", s2, BITCH_DEOP_REASON);
4629 #endif
4630       raw_now ("DEOP");         /* Deoped, run list of
4631                                  * commands.. */
4632     }
4633     else if (stricmp (cmd, "352") == 0) {
4634       s2 = strtok (NULL, "");
4635       parse_who (s2);
4636 #if STATUS == 1
4637     }
4638     else if (stricmp (cmd, "252") == 0) {
4639       s2 = strtok (NULL, "");
4640       parse_252 (s2);
4641     }
4642     else
4643       if (stricmp (cmd, "404") == 0
4644           || stricmp (cmd, "475") == 0
4645           || stricmp (cmd, "474") == 0 || stricmp (cmd, "473") == 0) {  /* Can't join? */
4646       s2 = strtok (NULL, " ");
4647       s2 = strtok (NULL, " ");
4648       db_sleep (5);
4649       S ("JOIN %s\n", s2);
4650     }
4651     else if (stricmp (cmd, "251") == 0) {
4652       s2 = strtok (NULL, "");
4653       parse_251 (s2);
4654     }
4655     else if (stricmp (cmd, "255") == 0) {
4656       s2 = strtok (NULL, "");
4657       parse_255 (s2);
4658 #endif
4659     }
4660     else if (stricmp (cmd, "433") == 0) {
4661       s2 = strtok (NULL, " ");
4662       if (*s2 != '*') {
4663         strncpy (Mynick, s2, sizeof(Mynick));
4664 #ifdef WIN32
4665       sprintf (NICK_COMMA, "%s,", Mynick);
4666       sprintf (COLON_NICK,"%s:", Mynick);
4667       sprintf (BCOLON_NICK,"%s\2:\2", Mynick);
4668 #else
4669       snprintf (NICK_COMMA,sizeof(NICK_COMMA), "%s,", Mynick);
4670       snprintf (COLON_NICK,sizeof(COLON_NICK), "%s:", Mynick);
4671       snprintf (BCOLON_NICK,sizeof(BCOLON_NICK), "%s\2:\2", Mynick);
4672 #endif
4673           s3 = strtok (NULL, " ");
4674       }
4675       else {
4676         Snow ("NICK %s%d\n", Mynick, xtried);
4677         xtried++;
4678         if (xtried > 15)
4679           Snow ("NICK _`^%s%d\n", Mynick, xtried);
4680         if (xtried > 5)
4681           Snow ("NICK _%s%d\n", Mynick, xtried);
4682       }
4683     }
4684   }
4685   else {                        /* Info from user */
4686     if (*s == ':')              /* Remove the colon prefix */
4687       s++;
4688     cmd = strtok (NULL, " ");   /* Read in command  */
4689     if (stricmp (cmd, "NOTICE") == 0) {
4690       s2 = strtok (NULL, " ");  /* target */
4691 #if KICK_ON_CHANNEL_NOTICE == ON
4692       if (*s2 == '#') {
4693         s3 = strtok (s, "!");
4694 #if BAN_ON_CHANNEL_NOTICE == ON
4695 #if BAN_BY_HOST == ON
4696         s4 = strtok (NULL, "@");
4697         s4 = strtok (NULL, "");
4698         S ("MODE %s +b *!*@%s\n", s2, s4);
4699 #else /* ban just by u@h */
4700         S ("MODE %s +b *%s\n", s2, strtok (NULL, ""));
4701 #endif
4702 #endif
4703         S ("KICK %s %s :Punt\n", s2, s3);
4704       }
4705 #endif
4706     }
4707     else if (stricmp (cmd, "PRIVMSG") == 0) {   /* PRIVMSG  */
4708       s1 = strtok (NULL, " ");  /* Target */
4709       s2 = strtok (NULL, "");   /* Rest  */
4710 #if     LOG_PRIVMSG == 1
4711       if (*s1 != '#' && *s1 != '&') {
4712         log (privmsg_log, "[%s] %s %s %s\n", date (), s, s1, s2);
4713       }
4714 #endif
4715       if (*s1 == '#' || *s1 == '&' || *s1 == '+')
4716         if (do_lastcomm (s, s1, s2)
4717             == 1)
4718           R;
4719       chanserv (s, s1, s2);     /* Process PRIVMSG commands */
4720     }
4721     else if (stricmp (cmd, "KILL") == 0) {
4722       s1 = strtok (NULL, " ");  /* Kill nick */
4723       if (stricmp (s1, Mynick) == 0) {
4724         do_quit (s1, 3);        /* delete all users from ram since I'm gone */
4725         gs26 ();
4726         socketfd = get_connection (BS, VHOST, BP);
4727         init_bot ();
4728       }
4729     }
4730     else if (stricmp (cmd, "KICK") == 0) {
4731       s1 = strtok (NULL, " ");  /* #chan */
4732       s2 = strtok (NULL, " ");  /* Who got kicked? */
4733       if (stricmp (s2, Mynick) == 0) {  /* Rejoin if I was
4734                                          * kicked */
4735         do_quit (s1, 2);
4736         db_sleep (5);
4737         S ("JOIN %s\n", s1);
4738         S ("PRIVMSG %s :%s\n", s1, COMPLAIN_REASON);
4739       }
4740       else
4741         delete_user (s2, s1);
4742     }
4743     else if (stricmp (cmd, "INVITE") == 0) {
4744       s1 = strtok (NULL, " ");  /* Mynick */
4745       s2 = strtok (NULL, " ");  /* Target */
4746       if (*s2 == ':')
4747         s2++;
4748       if (stricmp (s2, CHAN) == 0)
4749         S ("JOIN %s\n", s2);
4750     }
4751     else if (stricmp (cmd, "PART") == 0) {
4752       s1 = strtok (NULL, " ");  /* Target */
4753       if ((ptr = strchr (s, '!')) != NULL)
4754         *ptr++ = '\0';
4755       strlwr (ptr);
4756       if (stricmp (s, Mynick) != 0)
4757         delete_user (s, s1);
4758       else                      /* I left, so delete all */
4759         do_quit (s1, 2);
4760     }
4761     else if (stricmp (cmd, "QUIT") == 0) {
4762       if ((ptr = strchr (s, '!')) != NULL)
4763         *ptr++ = '\0';
4764       do_quit (s, 1);
4765     }
4766     else if (stricmp (cmd, "MODE") == 0) {
4767       do_modes (s, strtok (NULL, ""));
4768     }
4769     else if (stricmp (cmd, "NICK") == 0) {
4770       if ((ptr = strchr (s, '!')) != NULL)
4771         *ptr++ = '\0';
4772       s1 = strtok (NULL, " ");
4773       process_nick (s, s1);
4774     }
4775     else if (stricmp (cmd, "JOIN") == 0) {
4776       JOINs++;
4777       s1 = strtok (NULL, " ");  /* TARGET */
4778       if (*s1 == ':')
4779         s1++;
4780       if ((ptr = strchr (s, '!')) != NULL)
4781         *ptr++ = '\0';
4782       strlwr (ptr);
4783       if (SeeN == 1 && *s1 == '#')
4784         seen_value = save_seen (s, ptr, s1);
4785       if (stricmp (s, Mynick) != 0) {
4786         if (check_permban (ptr, s1, s) == 1)
4787           R;
4788         add_user (s1, s, ptr, 1);
4789 #if DO_WHOIS == 1
4790         strncpy (g_chan, s1, sizeof(g_chan));
4791         S ("WHOIS %s\n", s);
4792 #endif
4793         if (check_access (ptr, s1, 0, s) >= 4) {
4794           S ("MODE %s +o %s\n", s1, s);
4795         }
4796         else if (check_access (ptr, s1, 1, s) >= 1) {
4797           S ("MODE %s +v %s\n", s1, s);
4798 #if HELP_GREET == 1
4799         }
4800         else if (check_access (ptr, s1, 0, s) >= 1) {
4801           return;               /* don't greet if the guy has
4802                                  * access (and no setinfo) */
4803         }
4804         else if (stricmp (s1, CHAN) == 0) {
4805           if (SeeN == 1) {
4806             if (seen_value == 0)        /* don't show people the
4807                                            * notice every join */
4808               if (setinfo_lastcomm (s1) == 0)   /* don't do it if you just did it! */
4809                 L102 (s, s1, s, *CMDCHAR);
4810           }
4811           else {
4812             if (setinfo_lastcomm (s1) == 0)
4813               L102 (s, s1, s, *CMDCHAR);
4814           }
4815         }
4816 #else
4817         }
4818 #endif
4819       }
4820       else
4821         S ("WHO %s\n", s1);     /* Check who is in the
4822                                  * chan */
4823     }                           /* JOIN */
4824   }
4825 }
4826 
4827 
4828 long
setinfo_lastcomm(char * rest)4829 setinfo_lastcomm (char *rest)
4830 {                               /* Disallows joins to more than one channel (or the same chan)
4831                                  * to artifically raise join counters */
4832   long c_uptime = 0;
4833   if (stricmp (rest, slc1) == 0)
4834     R 1;                        /* don't reply if already asked in LASTCOMM_TIME sec */
4835   if (stricmp (rest, slc2) == 0)
4836     R 1;
4837   if (stricmp (rest, slc3) == 0)
4838     R 1;
4839   if (stricmp (rest, slc4) == 0)
4840     R 1;
4841   if (*slc1 == '0') {           /* init lastcomms */
4842     strncpy (slc1, rest, sizeof(slc1));
4843     slcn1 = time (NULL);
4844   }
4845   if (*slc2 == '0') {
4846     strncpy (slc2, rest, sizeof(slc2));
4847     slcn2 = time (NULL);
4848   }
4849   if (*slc3 == '0') {
4850     strncpy (slc3, rest, sizeof(slc3));
4851     slcn3 = time (NULL);
4852   }
4853   if (*slc4 == '0') {
4854     strncpy (slc4, rest, sizeof(slc4));
4855     slcn4 = time (NULL);
4856   }
4857   if ((c_uptime = time (NULL) - slcn1) > SLASTCOMM_TIME) {      /* reinit old data */
4858     slcn1 = 0;
4859     *slc1 = '0';
4860   }
4861   if ((c_uptime = time (NULL) - slcn2) > SLASTCOMM_TIME) {
4862     slcn2 = 0;
4863     *slc2 = '0';
4864   }
4865   if ((c_uptime = time (NULL) - slcn3) > SLASTCOMM_TIME) {
4866     slcn3 = 0;
4867     *slc3 = '0';
4868   }
4869   if ((c_uptime = time (NULL) - slcn4) > SLASTCOMM_TIME) {
4870     slcn4 = 0;
4871     *slc4 = '0';
4872   }
4873   strncpy (slc4, slc3, sizeof(slc4));           /* no matches, move em on
4874 down */
4875   strncpy (slc3, slc2, sizeof(slc3));
4876   strncpy (slc2, slc1, sizeof(slc2));
4877   strncpy (slc1, rest, sizeof(slc1));
4878   slcn4 = slcn3;
4879   slcn3 = slcn2;
4880   slcn2 = slcn1;
4881   slcn1 = time (NULL);
4882   R 0;
4883 }
4884 
4885 long
do_lastcomm(char * nick,char * target,char * rest)4886 do_lastcomm (char *nick, char *target, char *rest)
4887 {
4888   long c_uptime = 0;
4889   if (stricmp (rest, lc1) == 0)
4890     R 1;                        /* don't reply if already asked in LASTCOMM_TIME sec */
4891   if (stricmp (rest, lc2) == 0)
4892     R 1;
4893   if (stricmp (rest, lc3) == 0)
4894     R 1;
4895   if (stricmp (rest, lc4) == 0)
4896     R 1;
4897   if (*lc1 == '0') {            /* init lastcomms */
4898     strncpy (lc1, rest, sizeof(lc1));
4899     lcn1 = time (NULL);
4900   }
4901   if (*lc2 == '0') {
4902     strncpy (lc2, rest, sizeof(lc2));
4903     lcn2 = time (NULL);
4904   }
4905   if (*lc3 == '0') {
4906     strncpy (lc3, rest, sizeof(lc3));
4907     lcn3 = time (NULL);
4908   }
4909   if (*lc4 == '0') {
4910     strncpy (lc4, rest, sizeof(lc4));
4911     lcn4 = time (NULL);
4912   }
4913   if ((c_uptime = time (NULL) - lcn1) > LASTCOMM_TIME) {        /* reinit old data */
4914     lcn1 = 0;
4915     *lc1 = '0';
4916   }
4917   if ((c_uptime = time (NULL) - lcn2) > LASTCOMM_TIME) {
4918     lcn2 = 0;
4919     *lc2 = '0';
4920   }
4921   if ((c_uptime = time (NULL) - lcn3) > LASTCOMM_TIME) {
4922     lcn3 = 0;
4923     *lc3 = '0';
4924   }
4925   if ((c_uptime = time (NULL) - lcn4) > LASTCOMM_TIME) {
4926     lcn4 = 0;
4927     *lc4 = '0';
4928   }
4929   strncpy (lc4, lc3, sizeof(lc4));              /* no matches, move em on
4930 down */
4931   strncpy (lc3, lc2, sizeof(lc3));
4932   strncpy (lc2, lc1, sizeof(lc2));
4933   strncpy (lc1, rest, sizeof(lc1));
4934   lcn4 = lcn3;
4935   lcn3 = lcn2;
4936   lcn2 = lcn1;
4937   lcn1 = time (NULL);
4938   R 0;
4939 }
4940 
4941 #if STATUS == 1
4942 void
parse_252(char * s)4943 parse_252 (char *s)
4944 {
4945   char *tmp;
4946   int numb = 0;
4947   tmp = strtok (s, " ");
4948   tmp = strtok (NULL, " ");
4949   sscanf (tmp, "%d", &numb);
4950   IRCOPS = numb;
4951 }
4952 #endif
4953 
4954 #if STATUS == 1
4955 void
parse_251(char * s)4956 parse_251 (char *s)
4957 {
4958   char *tmp;
4959   int numb = 0, r = 0, i = 0;
4960   /*- Read and chuck useless data from line 'b' -*/
4961   tmp = strtok (s, " ");
4962   tmp = strtok (NULL, " ");
4963   tmp = strtok (NULL, " ");
4964   tmp = strtok (NULL, " ");
4965   sscanf (tmp, "%d", &r);
4966   tmp = strtok (NULL, " ");
4967   tmp = strtok (NULL, " ");
4968   tmp = strtok (NULL, " ");
4969   sscanf (tmp, "%d", &i);
4970   tmp = strtok (NULL, " ");
4971   tmp = strtok (NULL, " ");
4972   tmp = strtok (NULL, " ");
4973   sscanf (tmp, "%d", &numb);
4974   NUM_SERV = numb;
4975   G_USERS = r + i;
4976 }
4977 #endif
4978 
4979 #if STATUS == 1
4980 void
parse_255(char * s)4981 parse_255 (char *s)
4982 {
4983   char *tmp, Stat[1];
4984   int numb = 0, pre_CLIENTS = 0;
4985   /* test321 :I have 1313 clients and 1 servers */
4986   strlwr (s);
4987   tmp = strtok (s, " ");
4988   tmp = strtok (NULL, " ");
4989   tmp = strtok (NULL, " ");
4990   tmp = strtok (NULL, " ");
4991   numb = atoi (tmp);
4992   pre_CLIENTS = L_CLIENTS;
4993   L_CLIENTS = numb;
4994   if (L_CLIENTS < pre_CLIENTS) {
4995     strncpy (Stat, "-", sizeof(Stat));
4996     pre_CLIENTS = pre_CLIENTS - L_CLIENTS;
4997   }
4998   else {
4999     strncpy (Stat, "+", sizeof(Stat));
5000     pre_CLIENTS = L_CLIENTS - pre_CLIENTS;
5001   }
5002 #ifdef WIN32
5003   sprintf (tmp,"%3.2f",
5004 #else
5005   snprintf (tmp, sizeof(tmp),"%3.2f",
5006 #endif
5007                 (float) (((float) L_CLIENTS / (float) G_USERS) * 100));
5008 #if PLAY == 1
5009   if (pre_CLIENTS == 0 || pre_CLIENTS == L_CLIENTS) {
5010     S
5011       ("PRIVMSG %s :!SENDQ %d srvs, %d ops, %d users (%s%% of %d, %ld avg)\n",
5012        PBOT, NUM_SERV, IRCOPS, L_CLIENTS, tmp,
5013        G_USERS, G_USERS / NUM_SERV);}
5014   else
5015     S
5016       ("PRIVMSG %s :!SENDQ %d srvs, %d ops, %d users [%c%2d] (%s%% of %d, %ld avg)\37\n",
5017        PBOT, NUM_SERV, IRCOPS, L_CLIENTS,
5018        Stat[0], pre_CLIENTS, tmp, G_USERS, G_USERS / NUM_SERV);
5019   log (".ubcount", "%d\n%d\n0\n0\n", L_CLIENTS, L_CLIENTS);
5020   rename (".ubcount",
5021           "/usr/local/apache/htdocs/usage/userbase/userbase.dat");
5022   log (".glcount", "%d\n%d\n0\n0\n", G_USERS, G_USERS);
5023   rename (".glcount",
5024           "/usr/local/apache/htdocs/usage/global/global.dat");
5025 #else
5026   if (pre_CLIENTS == 0 || pre_CLIENTS == L_CLIENTS) {
5027     S
5028       ("PRIVMSG %s :\1ACTION \37(\37%2d servers\37)\37: %2d opers + \2%4d\2 users \37(\37%s%% %5d global \2!\2 %3ld avg\37)\37\1\n",
5029        CHAN, NUM_SERV, IRCOPS, L_CLIENTS, tmp,
5030        G_USERS, G_USERS / NUM_SERV);}
5031   else
5032     S
5033       ("PRIVMSG %s :\1ACTION \37(\37%2d servers\37)\37: %2d opers + \2%4d\2 users [\37%c%2d\37] \37(\37%s%% %5d global \2!\2 %3ld avg\37)\37\1\n",
5034        CHAN, NUM_SERV, IRCOPS, L_CLIENTS,
5035        Stat[0], pre_CLIENTS, tmp, G_USERS, G_USERS / NUM_SERV);
5036 #endif
5037 }
5038 #endif
5039 
5040 void
load_helpers()5041 load_helpers ()
5042 {
5043   FILE *fp;
5044   char b[STRING_LONG], *user_host,
5045     *greetz, *numb_join, *chan, *w_level, *pass;
5046   long num_join = 0, i = 0, level = 0;
5047   if ((fp = fopen (HELPER_LIST, "r")) == NULL) {
5048     printf ("Unable to open %s! Aborting connection.\n", HELPER_LIST);
5049     printf ("Please run /usr/local/etc/darkbot/configure to setup your darkbot.\n");
5050     exit (0);
5051   }
5052 #ifndef WIN32
5053   printf ("Loading %s file ", HELPER_LIST);
5054 #endif
5055   while (fgets (b, STRING_LONG, fp)) {
5056     if (b == NULL)
5057       continue;
5058     stripline (b);
5059     if (*b == '/')
5060       continue;
5061     i++;
5062     printf (".");
5063     fflush (stdout);
5064     chan = strtok (b, " ");
5065     if (chan == NULL)
5066       continue;
5067     user_host = strtok (NULL, " ");
5068     if (user_host == NULL)
5069       continue;
5070     w_level = strtok (NULL, " ");
5071     if (w_level == NULL)
5072       continue;
5073     numb_join = strtok (NULL, " ");
5074     if (numb_join == NULL)
5075       continue;
5076     pass = strtok (NULL, " ");
5077     if (pass == NULL) {
5078       pass = "0";               /* duh */
5079     }
5080     greetz = strtok (NULL, "");
5081     if (greetz == NULL)
5082       greetz = "I haven't used \2SETINFO\2 yet!";
5083     if (w_level != NULL)
5084       level = atoi (w_level);
5085     else
5086       level = 1;
5087     if (numb_join != NULL)
5088       num_join = atoi (numb_join);
5089     else
5090       num_join = 0;
5091     if (strlen (pass) > 25)
5092       pass[25] = '\0';
5093     if (DebuG == 1)
5094       printf
5095         ("loading helperlist: %s %s l:%d j:%d %s\n",
5096          chan, user_host, (int) level, (int) num_join, greetz);
5097     add_helper (chan, user_host, level, num_join, greetz, pass);
5098   }
5099   printf ("done(%d).\n", (int) i);
5100   fclose (fp);
5101   save_changes ();
5102   if (DebuG == 1)
5103     db_sleep (2);
5104 }
5105 
5106 /**
5107  * Add a channel helper.
5108  * 6/22/00 Dan
5109  * n now initialized where declared
5110  * All pointer arguments now received as pointer to const data.
5111  */
5112 void
add_helper(const char * chan,const char * uh,long level,size_t num_join,const char * greetz,const char * pass)5113 add_helper (const char *chan,
5114             const char *uh, long level,
5115             size_t num_join, const char *greetz, const char *pass)
5116 {
5117   struct helperlist *n = 0;
5118   n = (struct helperlist *)
5119     malloc (sizeof (struct helperlist));
5120   if (n == NULL) {
5121     log ("error.log", "AHHH! No ram left! in add_helper!\n");
5122     R;
5123   }
5124 
5125   memset (n, 0, sizeof (struct helperlist));
5126   NUM_HELPER++;
5127   if (chan[0] == '#') {
5128     strncpy (n->chan, chan, sizeof(n->chan));
5129   }
5130   else {
5131     strncpy (n->chan, "#*", sizeof(n->chan));
5132   }
5133 
5134   strncpy (n->uh, uh, sizeof(n->uh));
5135   strlwr (n->uh);
5136   strncpy (n->pass, pass, sizeof(n->pass));
5137   n->num_join = num_join;
5138   n->level = level;
5139   strncpy (n->greetz, greetz,
5140            min (sizeof (n->greetz) - 1, strlen (greetz)));
5141   n->next = helperhead;
5142   helperhead = n;
5143 }
5144 
5145 
5146 /**
5147  * 6/22 Dan
5148  * - Changed DATA to be 512 bytes, a power of 2
5149  * - DATA now initialized properly
5150  * - c is now a pointer to const, this is a read only method
5151  * - c is now initialized where declared
5152  * - Changed type of i, x to size_t, these variables should be
5153  *   unsigned.
5154  * - Changed while loop to for loop.
5155  * - Changed reinitialization of DATA to use memset()
5156  */
5157 void
show_banlist(const char * nick)5158 show_banlist (const char *nick)
5159 {
5160   char DATA[STRING_SHORT] = {
5161     0
5162   };
5163   size_t i = 0;
5164   size_t x = 0;
5165   const struct permbanlist *c = 0;
5166   for (c = permbanhead; c != NULL; c = c->next) {
5167     i++;
5168     ++x;
5169 #ifdef WIN32
5170     sprintf (DATA,"%s %s:%d", DATA, c->uh, (int)
5171 #else
5172     snprintf (DATA,sizeof(DATA), "%s %s:%d", DATA, c->uh, (int)
5173 #endif
5174         c->counter);
5175     if (i > 8) {
5176       S ("NOTICE %s :%s\n", nick, DATA);
5177       i = 0;
5178       memset (DATA, 0, sizeof (DATA));
5179       db_sleep (2);
5180     }
5181   }
5182   S ("NOTICE %s :%s\n", nick, DATA);
5183   S
5184     ("NOTICE %s :End of PERMBAN list; %d ban%s found.\n",
5185      nick, x, (x == 1) ? "" : "s");
5186 }
5187 
5188 /**
5189  * Output the helper list to a nickname.
5190  * 6/22, Dan:
5191  * - Changed helperlist* c to be a pointer to const data
5192  * - Changed initialization of DATA, and size to be a
5193  *   power of 2
5194  * - Added initialization of c
5195  * - Changed while loop to for loop
5196  * - Changed types of i, x to size_t since they should be
5197  *   unsigned.
5198  * - Added reinitialization of DATA using memset() (changed from
5199  *   strcpy(DATA,""))
5200  */
5201 void
show_helper_list(const char * nick,long level)5202 show_helper_list (const char *nick, long level)
5203 {
5204   char DATA[STRING_SHORT] = {
5205     0
5206   };
5207   size_t i = 0, x = 0;
5208   const struct helperlist *c = 0;
5209   for (c = helperhead; c != NULL; c = c->next) {
5210     i++;
5211     x++;
5212     if (level == 0) {
5213       i++;
5214 #ifdef   LINUX
5215          sprintf (DATA, "%s %s[%s:%d:%d]", DATA, c->uh, c->chan,
5216                   c->level, c->num_join);
5217 #else
5218          snprintf (DATA, sizeof(DATA), "%s %s[%s:%d:%d]", DATA,
5219                 c->uh, c->chan, c->level,  c->num_join);
5220 #endif
5221     }
5222     else {
5223       if (level == c->level) {
5224 #ifdef   LINUX
5225          sprintf (DATA, "%s %s[%s:%d:%d]", DATA, c->uh, c->chan,
5226                   c->level, c->num_join);
5227 #else
5228         snprintf (DATA, sizeof(DATA), "%s %s[%s:%d:%d]", DATA,
5229                 c->uh, c->chan, c->level, c->num_join);
5230 #endif
5231       }
5232     }
5233     if (i > 6) {
5234       S ("NOTICE %s :%s\n", nick, DATA);
5235       i = 0;
5236       memset (DATA, 0, sizeof (DATA));
5237       db_sleep (2);
5238     }
5239   }                             /* for() */
5240 
5241   S ("NOTICE %s :%s\n", nick, DATA);
5242   S
5243     ("NOTICE %s :End of Helper Userlist; %d user%s found.\n",
5244      nick, x, (x == 1) ? "" : "s");
5245 }
5246 
5247 int
match_wild(const char * pattern,const char * str)5248 match_wild (const char *pattern, const char *str)
5249 {
5250   char c;
5251   const char *s;
5252   for (;;) {
5253     switch (c = *pattern++) {
5254     case 0:
5255       if (!*str)
5256         R 1;
5257       R 0;
5258     case '?':
5259       ++str;
5260       break;
5261     case '*':
5262       if (!*pattern)
5263         R 1;
5264       s = str;
5265       while (*s) {
5266         if (*s == *pattern && match_wild (pattern, s))
5267           R 1;
5268         ++s;
5269       }
5270       break;
5271     default:
5272       if (*str++ != c)
5273         R 0;
5274       break;
5275     }                           /* switch */
5276   }
5277 }
5278 
5279 
5280 #ifndef WIN32
5281 int
stricmp(const char * s1,const char * s2)5282 stricmp (const char *s1, const char *s2)
5283 {
5284   return strcasecmp (s1, s2);
5285 }
5286 #else
5287 int
stricmp(const char * s1,const char * s2)5288 stricmp (const char *s1, const char *s2)
5289 {
5290   register int c;
5291   while ((c = tolower (*s1)) == tolower (*s2)) {
5292     if (c == 0)
5293       return 0;
5294     s1++;
5295     s2++;
5296   }
5297   if (c < tolower (*s2))
5298     return -1;
5299   return 1;
5300 }
5301 #endif
5302 
5303 
5304 /**
5305  * Removed trailing newline and carriage returns.
5306  * 6/22/00 Dan
5307  * Rewrote to be more efficient, reduced from O(2n) to O(n)
5308  */
5309 void
stripline(char * ptr)5310 stripline (char *ptr)
5311 {
5312   for (; ptr && *ptr; ++ptr) {
5313     if ('\r' == *ptr || '\n' == *ptr) {
5314       *ptr = 0;
5315       return;
5316     }
5317   }
5318 }
5319 
5320 
5321 int
Send()5322 Send ()
5323 {
5324   struct sendq *c;
5325   char output[STRING_LONG];
5326   c = sendqhead;
5327   get_sendq_count (0);
5328   if (c == NULL) {
5329     send_tog = 0;
5330     R - 1;
5331   }
5332   if (DebuG == 1)
5333     printf ("OUT: %s\n", c->data);
5334 #ifdef  DEBUG2
5335   log ("darkbot_debug.log", "OUT: %s\n", c->data);
5336 #endif
5337   strncpy (output, c->data, sizeof(output));
5338   del_sendq (0);
5339   R (writeln (output));
5340 }
5341 
5342 
5343 /**
5344  * Write a character array to a socket connection.
5345  * 6/22/00 Dan
5346  * Method argument now pointer to const data.
5347  */
5348 int
writeln(const char * b)5349 writeln (const char *b)
5350 {
5351   return (write (socketfd, b, strlen (b))
5352           < 0) ? 0 : 1;
5353 }
5354 
5355 
5356 int
get_connection(const char * hostname,const char * vhostname,int port)5357 get_connection (const char *hostname, const char *vhostname, int port)
5358 {
5359   struct sockaddr_in sa;
5360   struct hostent *hp;
5361   int sckfd, f = 1;
5362   if (vhostname == NULL)
5363     f = 0;
5364   else if (strlen (vhostname) < 1)
5365     f = 0;
5366   if ((sckfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
5367     R (-1);
5368   memset (&sa, 0, sizeof (struct sockaddr_in));
5369   sa.sin_family = AF_INET;
5370   sa.sin_addr.s_addr = (f ? inet_addr (vhostname) : INADDR_ANY);
5371   if ((INADDR_NONE == sa.sin_addr.s_addr)
5372       && f) {
5373     hp = gethostbyname (vhostname);
5374     if (hp) {
5375       bcopy (hp->h_addr, (char *) &sa.sin_addr, hp->h_length);
5376     }
5377     else {
5378       sa.sin_addr.s_addr = INADDR_ANY;
5379     }
5380   }
5381   if (bind
5382       (sckfd, (struct sockaddr *) &sa,
5383        sizeof (struct sockaddr_in)) < 0) {
5384     R (-9);
5385   }
5386   memset (&sa, 0, sizeof (struct sockaddr_in));
5387   sa.sin_family = AF_INET;
5388   sa.sin_port = htons (port);
5389   sa.sin_addr.s_addr = inet_addr (hostname);
5390   setsockopt (sckfd, SOL_SOCKET, SO_LINGER, 0, 0);
5391   setsockopt (sckfd, SOL_SOCKET, SO_REUSEADDR, 0, 0);
5392   setsockopt (sckfd, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
5393   if (INADDR_NONE == sa.sin_addr.s_addr) {
5394     if ((hp = gethostbyname (hostname)) == NULL) {
5395       errno = ECONNREFUSED;
5396       printf ("Can't find hostname: %s\n", hostname);
5397       R (-1);
5398     }
5399     memcpy (&sa.sin_addr, hp->h_addr, hp->h_length);
5400   }
5401   if (connect (sckfd, (struct sockaddr *) &sa, sizeof (sa)) < 0) {
5402     close (sckfd);
5403     printf
5404       ("\nUnable to make connection to host `%s:%d'\n\n",
5405        BS, (int) BP); R (-1);
5406   }
5407   R (sckfd);
5408 }
5409 
5410 int
readln()5411 readln ()
5412 {
5413   char ch;
5414   int i = 0;
5415   do {
5416     if (read (socketfd, &ch, 1) < 1)
5417       R (0);
5418     if (ch >= 32 || ch <= 126)
5419       if (i < 524 - 1)
5420         L[i++] = ch;
5421   }
5422   while (ch != '\n');
5423   L[i] = '\0';
5424   R 1;
5425 }
5426 
5427 void
log(const char * filename,const char * format,...)5428 log (const char *filename, const char *format, ...)
5429 {
5430   va_list arglist;
5431   FILE *fp;
5432   fp = fopen (filename, "a");
5433   if (NULL == fp) {
5434     /* I guess there's no sense in trying to log the error :) */
5435     return;
5436   }
5437 
5438   va_start (arglist, format);
5439   vfprintf (fp, format, arglist);
5440   va_end (arglist);
5441   fclose (fp);
5442 }
5443 
5444 /**
5445  * Convert a character array to all lowercase.
5446  * 6/23/00 Dan:
5447  * - Rewrote to be more compact and a bit more efficient
5448  */
5449 char *
strlwr(char * buf)5450 strlwr (char *buf)
5451 {
5452   char *ptr = buf;
5453   for (; ptr && *ptr; ++ptr) {
5454     *ptr = tolower (*ptr);
5455   }
5456   return buf;
5457 }
5458 
5459 void
trailing_blanks(char * str)5460 trailing_blanks (char *str)
5461 {
5462   int i;
5463   if (str == NULL)
5464     R;
5465   for (i = strlen (str); i > 0; i--) {
5466     if (isspace (str[i - 1]))
5467       str[i - 1] = '\0';
5468     else
5469       R;
5470   }
5471 }
5472 
5473 
5474 void
parse_server_msg(fd_set * read_fds)5475 parse_server_msg (fd_set * read_fds)
5476 {
5477   if (FD_ISSET (socketfd, read_fds)) {
5478     if (readln () > 0) {
5479       NUMLINESSEEN++;
5480       parse (L);
5481     }
5482     else {
5483       close (socketfd);
5484     }
5485   }
5486 }
5487 
5488 
5489 long
f_f(char * host)5490 f_f (char *host)
5491 {
5492   int i;
5493   for (i = 0; i < fc; i++)
5494     if (!strcasecmp (ood[i].host, host))
5495       R i;
5496   R - 1;
5497 }
5498 
5499 void
get_s()5500 get_s ()
5501 {
5502   char temp[20];
5503   long i = 0;
5504   i = strlen (rp391);
5505   while (i > 0) {
5506     i--;
5507 #ifdef WIN32
5508     sprintf (temp,"%s%c", dbVersion, rp391[i]);
5509 #else
5510     snprintf (temp,sizeof(temp), "%s%c", dbVersion, rp391[i]);
5511 #endif
5512     strncpy (dbVersion, temp, sizeof(dbVersion));
5513   }
5514 }
5515 
5516 void
a_f(char * host)5517 a_f (char *host)
5518 {
5519   if (++fc > 100)
5520     fc = 0;
5521   fc--;
5522   strncpy (ood[fc].host, host, sizeof(ood[fc].host));
5523   ood[fc].time = time (NULL);
5524   ood[fc].count = 0;
5525   ood[fc].value = false;
5526   fc++;
5527 }
5528 
5529 void
reset_()5530 reset_ ()
5531 {
5532   int i;
5533   for (i = 0; i < fc; i++) {
5534     if (ood[i].value && (time (NULL) - ood[i].time) > rt) {
5535       ood[i].count = 0;
5536       ood[i].time = time (NULL);
5537       ood[i].value = false;
5538       ood[i].kick = 0;
5539     }
5540   }
5541 }
5542 
5543 char *
date()5544 date ()
5545 {
5546   time_t timer;
5547   time (&timer);
5548   strncpy (strbuff, ctime (&timer), sizeof(strbuff));
5549   stripline (strbuff);
5550   return strbuff;
5551 }
5552 
5553 /**
5554  * Allocate a new character array.  Copy into it at most
5555  * maxBytes bytes.
5556  */
5557 char *
db_strndup(const char * dupMe,size_t maxBytes)5558 db_strndup (const char *dupMe, size_t maxBytes)
5559 {
5560   char *ptr = 0;
5561   char *retMe = 0;
5562   /* Configure maxBytes to be the number of bytes to copy */
5563   maxBytes = min (strlen (dupMe), maxBytes);
5564   /* Allocate the return buffer. */
5565   retMe = (char *) malloc (maxBytes + 1);
5566   /* Was the allocation successful? */
5567   if (NULL == retMe) {
5568     return NULL;
5569   }
5570 
5571   /*
5572    * ptr will point to the byte to which to copy the next
5573    * source byte.
5574    */
5575   ptr = retMe;
5576   /*
5577    * Continue while dupMe is valid and we are < maxBytes number
5578    * of bytes copied. This is typecase here because size_t is
5579    * unsigned, so comparing against > 0 *should* produce a
5580    * warning :)
5581    */
5582   while (dupMe && (int) maxBytes-- > 0) {
5583     *ptr++ = *dupMe++;
5584   }
5585 
5586   /* Be sure to NULL terminate the array */
5587   *ptr = 0;
5588   return retMe;
5589 }
5590 
5591 /**
5592  * Output information about the bot's database to a target.
5593  * 6/22 Dan:
5594  * - Changed both method arguments to be pointers to const data,
5595  *   this is a read only method.
5596  */
5597 void
show_info2(const char * target,const char * source)5598 show_info2 (const char *target, const char *source)
5599 {
5600   S
5601     ("PRIVMSG %s :%s, src: %s (%d lines of code), compiled @ %s. "
5602      "I have processed %ld lines of text since startup...\n",
5603      target, source, __FILE__, __LINE__, __DATE__, NUMLINESSEEN);
5604 }
5605 
5606