home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / doom_i / program / tcpsrv12.exe / TCPSRV12.TAR / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-30  |  15.7 KB  |  646 lines

  1. /* server.c */
  2. /*
  3.  
  4.  * Copyright 1994 A.Oliver De Guzman
  5.  * All rights reserved
  6.  
  7.  *   Permission is granted to any individual to copy, use, and/or
  8.  * distribute this software provided that the distribution retains this
  9.  * entire copyright notice. No part of this software may be used and/or
  10.  * sold for profit or used with any commercial product.
  11.  
  12.  * DISCLAIMER:
  13.  *   This software comes with NO WARRANTIES of any kind. In no event
  14.  * will the author be liable for any financial, physical, moral, and/or
  15.  * mental damages incurred directly or indirectly by the use or intent
  16.  * to use of this software.
  17.  
  18.  */
  19.  
  20. #define DEBUG
  21.  
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <setjmp.h>
  25. #include <signal.h>
  26. #include <sys/time.h>
  27. #include <sys/types.h>
  28. #include "dfcss.h"
  29. #include "sock.h"
  30. #include "node.h"
  31. #include "config.h"
  32. #include "log.h"
  33.  
  34. #define CONFIGFILE                "server.cfg"
  35. #define EMAILLEN                30
  36. #define NAMELEN                    20
  37. #define ALIASLEN                12
  38. #define WAITASEC                5
  39. #define DEFAULT_DELAY            60
  40.  
  41. #define printIP(str, peer)    sprintf(str, "%d.%d.%d.%d",\
  42.                                 (htonl(peer.sin_addr.s_addr) >> 24) & 0xFF,\
  43.                                 (htonl(peer.sin_addr.s_addr) >> 16) & 0xFF,\
  44.                                 (htonl(peer.sin_addr.s_addr) >>  8) & 0xFF,\
  45.                                 (htonl(peer.sin_addr.s_addr)      ) & 0xFF)
  46.      
  47.  
  48. char slog[1024];
  49. int sd, newfd = -1;
  50. char banner[MAXMSG+1];
  51. int port = PORT_NUMBER;
  52. jmp_buf mainloop;
  53. FILE *fp;
  54. int timeron=0;
  55.  
  56. char MESSAGEFILE[128] = "server.msg";
  57. char SERVERLIST[128] = "server.lst";
  58. Config sconfigs[] = {
  59.     { "msgfile", CFG_STR, MESSAGEFILE },
  60.     { "serverlist", CFG_STR, SERVERLIST },
  61. };
  62. #define SNUMCONFIGS        (sizeof(sconfigs)/sizeof(Config))
  63.  
  64. char NAME[128] = "", EMAIL[128] = "", ALIAS[128];
  65. Config cconfigs[] = {
  66.     { "name", CFG_STR, NAME },
  67.     { "alias", CFG_STR, ALIAS },
  68.     { "email", CFG_STR, EMAIL },
  69. };
  70. #define CNUMCONFIGS        (sizeof(cconfigs)/sizeof(Config))
  71.  
  72. /*char COMMAND[1024] = "tcpsetup";*/
  73. char MODE[128] = "-deathmatch";
  74. int PORT = 0x869c;
  75. int SKILL = 4;
  76. int EPISODE = 1;
  77. int MISSION = 1;
  78. int TIMER = 0;
  79. char MONSTERS[128] = "";
  80. char WADFILES[1024] = "";
  81. char EXTENSIONS[1024] = "";
  82.  
  83. int DELAY = DEFAULT_DELAY;
  84. int NUMPLAYERS = 3;
  85. Config configs[] = {
  86. /*    { "command", CFG_STR, COMMAND }, */
  87.     { "mode", CFG_STR, MODE },
  88.     { "port", CFG_INT, &PORT },
  89.     { "skill", CFG_INT, &SKILL },
  90.     { "episode", CFG_INT, &EPISODE },
  91.     { "mission", CFG_INT, &MISSION },
  92.     { "timer", CFG_INT, &TIMER },
  93.     { "monsters", CFG_STR, MONSTERS },
  94.     { "wadfiles", CFG_STR, WADFILES },
  95.     { "extensions", CFG_STR, EXTENSIONS },
  96.     { "delay", CFG_INT, &DELAY },
  97.     { "numplayers", CFG_INT, &NUMPLAYERS }
  98. };
  99. #define NUMCONFIGS        (sizeof(configs)/sizeof(Config))
  100.  
  101. char sethelp[] =
  102. "\n\
  103. * Help on setting game parameters\n\
  104. * Type \"/set <parameter> <value>\" where <parameter> is any of:\n\
  105. *   mode [-deathmatch|-altdeath]      regular deathmatch or deathmatch v2.0\n\
  106. *   port <portnum>                   port number to use, 0=do not use -port\n\
  107. *   skill [0-5]                            skill level, 0=do not use -skill\n\
  108. *   episode [0-3]                               episode number, 0 for DOOM2\n\
  109. *   mission [1-9]                         mission number, 1-32 if episode=0\n\
  110. *   timer <minutes>                               time, 0=do not use -timer\n\
  111. *   monsters [-nomonsters|-respawn|-fast]                  monster behavior\n\
  112. *   wadfiles [first.wad [second.wad ...]]                   wadfiles to use\n\
  113. *   extensions <string>                        put undocumented params here\n\
  114. *   delay <seconds>                          delay before starting the game\n\
  115. *   numplayers [2-4]                                      number of players";
  116.  
  117. void HelpSet()
  118. {
  119.     ASockWrite(nodes[nodeidx].sd, sethelp);
  120.  
  121. }
  122.  
  123. char *PlayStat()
  124. {
  125.     static char msg[MAXMSG+1];
  126.     char buff[128];;
  127.  
  128.     sprintf(msg,  "* Current Setting:");
  129.     sprintf(buff, "\n*  Number of Players:%2d     Delay: %4d second(s)", NUMPLAYERS, DELAY); strcat(msg, buff);
  130.     sprintf(buff, "\n*  Skill:%2d                 Port: 0x%X", SKILL, PORT); strcat(msg, buff);
  131.     sprintf(buff, "\n*  Episode:%2d               Mission:%2d", EPISODE, MISSION); strcat(msg, buff);
  132.     sprintf(buff, "\n*  Mode: %s %*sMonsters: %s", MODE, 18-strlen(MODE), " ", MONSTERS); strcat(msg, buff);
  133.     sprintf(buff, "\n*  Wadfiles: %s", WADFILES); strcat(msg, buff);
  134.     sprintf(buff, "\n*  Extensions: %s", EXTENSIONS); strcat(msg, buff);
  135.     sprintf(buff, "\n*  Timer: %d minute(s)", TIMER); strcat(msg, buff);
  136.     return(msg);
  137. }
  138.  
  139.  
  140. int CheckSettings()
  141. {
  142.     StripWhite(MODE);
  143.     if (strcmp(MODE, "-deathmatch") && strcmp(MODE, "-altdeath") && MODE[0])
  144.         MODE[0] = '\0';
  145.     SKILL = MAX(0, MIN(SKILL, 5));
  146.     EPISODE = MAX(0, MIN(EPISODE, 3));
  147.     if (EPISODE) MISSION = MAX(1, MIN(MISSION, 9));
  148.     else MISSION = MAX(1, MIN(MISSION, 32));
  149.  
  150.     TIMER = MAX(0, MIN(TIMER, 60*48));  /* Max of 2 days play time :) */
  151.     StripWhite(MONSTERS);
  152.     if (strcmp(MONSTERS, "-nomonsters") && strcmp(MONSTERS, "-respawn")
  153.         && strcmp(MONSTERS, "-fast") && MONSTERS[0])
  154.         MONSTERS[0] = '\0';
  155.     /* WADFILES not checked */
  156.     StripWhite(WADFILES);
  157.     StripWhite(EXTENSIONS);
  158.  
  159.     DELAY = MAX(0, MIN(DELAY, 60*60));  /* Max delay of 1 hour */
  160.     NUMPLAYERS = MAX(2, MIN(NUMPLAYERS, 4)); /* 2-4 players */
  161. }
  162.  
  163. void Shutdown()
  164. {
  165.     int i;
  166.  
  167.     sprintf(slog, "%d shutdown", port); logger(fp, slog);
  168. #ifdef DEBUG
  169.     printf("\nServer_ShutDown.\n");
  170. #endif
  171.  
  172.     WriteNodes(ABORT);
  173.     for (i=0; i<MAX_NODES; i++){
  174.         if (!IsUnused(nodes[i]))
  175.         close(nodes[i].sd);
  176.     }
  177.  
  178.     close(sd);
  179.     closelog(fp);
  180.     exit(3);
  181. }
  182.  
  183. void Ignore()
  184. {
  185. #ifdef DEBUG
  186.     printf("Ignore");
  187. #endif
  188.     signal(SIGPIPE, Ignore);
  189. }
  190.  
  191. void ResetNode()
  192. {
  193. #ifdef DEBUG
  194.     printf("ResetNode[%d]", nodeidx);
  195. #endif
  196.     if (newfd != -1) close(newfd);
  197.     signal(SIGPIPE, ResetNode);
  198.     longjmp(mainloop, 1);
  199. }
  200.  
  201. void ResetServer()
  202. {
  203. #ifdef DEBUG
  204.     printf("ResetServer");
  205. #endif
  206.     logger(fp, "ResetServer");
  207.     signal(SIGPIPE, ResetServer);
  208.     longjmp(mainloop, 2);
  209. }
  210.  
  211. int setfds(rfds)
  212. fd_set *rfds;
  213. {
  214.     int i;
  215.     int maxfd = 0;
  216.  
  217.     FD_ZERO(rfds);
  218.     FD_SET(sd, rfds);
  219.     maxfd = sd;
  220.  
  221.     for (i=0; i<MAX_NODES; i++){
  222.         if (!IsUnused(nodes[i])){
  223.             FD_SET(nodes[i].sd, rfds);
  224.             if (nodes[i].sd > maxfd)
  225.                 maxfd = nodes[i].sd;
  226.         }
  227.     }
  228.  
  229.     return(maxfd+1);
  230. }
  231.  
  232.  
  233. int helpme(sd)
  234. int sd;
  235. {
  236.     ASockWrite(sd, "* type /help for commands");
  237. }
  238.  
  239.  
  240. #define SET        "set"
  241.  
  242. int ExecuteCommand(cmd)
  243. char cmd[];
  244. {
  245.     char buff[MAXMSG+1], *msg;
  246.     int n;
  247.  
  248.     StripWhite(cmd);
  249.     msg = cmd;
  250.     if (DoCommand(nodeidx, msg) < 0){
  251.         int ch;
  252.  
  253.         msg++;
  254.         ch = msg[strlen(SET)];
  255.         msg[strlen(SET)] = '\0';
  256.         if (!strcmp(SET, msg)){
  257.             msg[strlen(SET)] = ch;
  258.             if (strlen(msg+strlen(SET)) > 0){
  259.                 if (IsPlayer(nodes[nodeidx]) || IsGod(nodes[nodeidx])){
  260.                     if ((n = configline(msg+strlen(SET)+1, configs, NUMCONFIGS)) >= 0 && n < NUMCONFIGS){
  261.                         CheckSettings();    
  262.                         sprintf(buff, "#%s> %s", nodes[nodeidx].alias, msg);
  263.                         WriteNodes(buff);
  264.                     }
  265.                     else{
  266.                         strcpy(buff, "* type /help set");
  267.                         ASockWrite(nodes[nodeidx].sd, buff);
  268.                     }
  269.                 }
  270.                 else ASockWrite(nodes[nodeidx].sd,
  271.                     "! Cannot use /set <var> <value> while in guest mode.");
  272.             }
  273.             else{
  274.                 sprintf(buff, "%s", PlayStat());
  275.                 ASockWrite(nodes[nodeidx].sd, buff);
  276.             }
  277.         }
  278.         else helpme(nodes[nodeidx].sd);
  279.     }
  280. }
  281.  
  282. main(argc, argv)
  283. int argc;
  284. char *argv[];
  285. {
  286.     char msg[MAXMSG+1], msg2[MAXMSG+1];
  287.     char commandline[MAXMSG+1];
  288.     struct sockaddr_in peer;
  289.     int peersize = sizeof(peer);
  290.     char IPstr[4*4+10];
  291.     fd_set rfds, trfds;
  292.     struct timeval tv;
  293.     int maxfd;
  294.     int i, j;
  295.     char configfile[1024];
  296.     char tmpfname[1024], serverlog[1024];
  297.     int type = PLAYER;
  298.     int idx, playernum;
  299.  
  300.     strcpy(configfile, CONFIGFILE);
  301.     if ((i = CheckParm("-nodes", argc, argv)) && (i < argc-1))
  302.         NUMPLAYERS = MIN(MAX_PLAYERS, atoi(argv[i+1]));
  303.  
  304.     if ((i = CheckParm("-port", argc, argv)) && (i < argc-1))
  305.         port = atoi(argv[i+1]);
  306.  
  307.     sprintf(serverlog, "%d.log", port);
  308.     if ((i = CheckParm("-log", argc, argv)) && (i < argc-1))
  309.         strcpy(serverlog, argv[i+1]);
  310.  
  311.     if ((i = CheckParm("-config", argc, argv)) && (i < argc-1))
  312.         strcpy(configfile, argv[i+1]);
  313.  
  314.     fp = openlog(serverlog);
  315.     sprintf(slog, "%d start %d nodes", port, NUMPLAYERS);
  316.     logger(fp, slog);
  317.  
  318.     /* Read the Filenames */
  319.     if (readconfig(configfile, sconfigs, SNUMCONFIGS) < 0){
  320. #ifdef DEBUG
  321.         printf("Cannot open config file [%s]. Using defaults.\n", configfile);
  322. #endif
  323.     }
  324.  
  325.     /* Read Initial Settings */
  326.     readconfig(configfile, configs, NUMCONFIGS);
  327.     CheckSettings();
  328.  
  329.     StripWhite(MESSAGEFILE);
  330.     StripWhite(SERVERLIST);
  331.  
  332. #ifdef DEBUG
  333.     printf("Listener_Start[%d] on port [0x%x]\n", NUMPLAYERS, port);
  334. #endif
  335.     sd = SockOpen(NULL, port);
  336.     if (sd == -1) exit(2);
  337.  
  338.     sprintf(tmpfname, "%d.tmp", port);
  339.     signal(SIGPIPE, ResetNode);
  340.     signal(SIGINT, Shutdown);
  341.     InitNodes();
  342.     switch (setjmp(mainloop)){
  343.         case 2:
  344.         case 1:
  345.             if (nodeidx != -1){
  346.                 sprintf(slog, "%d reset node %d", port, nodeidx);
  347.                 logger(fp, slog);
  348.                 sprintf(msg, "! %s %s left.",
  349.                     StrNodeType(nodes[nodeidx].type), NodeStat(nodeidx));
  350.  
  351.                 close(nodes[nodeidx].sd);
  352.                 InitNode(nodeidx);
  353.                 WriteNodes(msg);
  354.             }
  355.         case 0:
  356.             while (1){
  357.  
  358. #ifdef DEBUG
  359.             printf("\nListener_Listen[%d] port[%d]...", NumPlayers(), port);
  360.             fflush(stdout);
  361. #endif
  362.  
  363.             while (NumPlayers() < NUMPLAYERS || (DELAY > 0)){
  364.  
  365.                 /* select timeout interval */
  366.                 tv.tv_sec = 1;
  367.  
  368.                 /* wait for and then accept a connect request */
  369.                 if (listen(sd, 5) == -1){
  370.                      perror("Listener: listen failed");
  371.                     continue;
  372.                 }
  373.  
  374.                 maxfd = setfds(&rfds);
  375.                 trfds = rfds;
  376.                 if (select(maxfd, &trfds, NULL, NULL, &tv) < 0){
  377.                     perror("Listener: select");
  378.                     ResetServer();
  379.                 }
  380.  
  381.                 if (FD_ISSET(sd, &trfds)){
  382.                     if ((newfd = accept(sd, NULL, NULL)) == -1){
  383.                          perror("Listener: accept failed");
  384.                         continue;
  385.                     }
  386.                 }
  387.                 else{
  388.                     /* Check if any sd is ready for read/write */
  389.                     for (i=0; i<MAX_NODES; i++){
  390.                         if (!IsUnused(nodes[i]) && FD_ISSET(nodes[i].sd, &trfds)){
  391.                             nodeidx = i;
  392.                             ASockRead(nodes[nodeidx].sd, msg);
  393.  
  394.                             if (msg[0] == '/'){
  395.                                 ExecuteCommand(msg);
  396.                             }
  397.                             else {
  398.                                 sprintf(msg2, "#%s> %s", nodes[i].alias, msg);
  399.                                 WriteNodes(msg2);
  400.                             }
  401.                         }
  402.                     }
  403.  
  404. #ifdef DEBUG
  405.                     printf("."); fflush(stdout);
  406. #endif
  407.  
  408.                     if (NumPlayers() == NUMPLAYERS){
  409.                         if (!timeron) WriteNodes("* Number of Players Satisfied. Starting delay timer.\n* Type \"/set delay <seconds>\" to shorten/lenghten delay.");
  410.                         DELAY--;
  411.                         if (DELAY==10 || DELAY==30 || DELAY==45){
  412.                             sprintf(msg, "* %d seconds delay left", DELAY);
  413.                             WriteNodes(msg);
  414.                         }
  415.                         timeron = 1;
  416.                     }
  417.                     else if (timeron){
  418.                         WriteNodes("* Stoping delay timer.");
  419.                         timeron = 0;
  420.                     }
  421.  
  422.                     continue;
  423.                 }
  424.  
  425.                 getpeername(newfd, (struct sockaddr *)&peer, &peersize);
  426.                 printIP(IPstr, peer);
  427.                 if (!strcmp(IPstr, "127.0.0.1")){
  428.                     getsockname(newfd, (struct sockaddr *)&peer, &peersize);
  429.                     printIP(IPstr, peer);
  430.                 }
  431. #ifdef DEBUG
  432.                 printf("connect[%s].\n", IPstr); fflush(stdout);
  433. #endif
  434.  
  435.                 nodeidx = -1;
  436.                 idx = NewNodeIndex();
  437.                 sprintf(slog, "%d node %d %s", port, idx, IPstr);
  438.                 logger(fp, slog);
  439.             
  440. #ifdef DEBUG
  441.                 printf("Listener_WriteServerID[%d]...", idx); fflush(stdout);
  442. #endif
  443.                 SockWrite(newfd, SERVERID, IDLEN);
  444. #ifdef DEBUG
  445.                 printf("done.\n");
  446.  
  447.                 printf("Listener_ReadNodeType..."); fflush(stdout);
  448. #endif
  449.                 ASockRead(newfd, msg);
  450.                 type = GetNodeType(msg);
  451. #ifdef DEBUG
  452.                 printf("done[%d].\n", type);
  453.                 printf("Listener_ReadOptions[%s]...", msg); fflush(stdout);
  454. #endif
  455.                 if (type == STATUS){
  456. #ifdef DEBUG
  457.                     printf("Status Connection..."); fflush(stdout);
  458. #endif
  459.                     ServerStat(newfd);
  460.                     sprintf(slog, "%d %s %d", port, StrNodeType(type), idx);
  461.                     logger(fp, slog);
  462. #ifdef DEBUG
  463.                     printf("serviced.\n");
  464. #endif
  465.                     longjmp(mainloop, 0);                    
  466.                 }
  467.  
  468.                 /* read options from client */
  469.                 ASockRead(newfd, msg);
  470.  
  471.                 /* set variables from read msg */
  472.                 writefile(tmpfname, msg, strlen(msg));
  473.                 readconfig(tmpfname, cconfigs, CNUMCONFIGS);
  474.                 if (NumPlayers() == 0){
  475.                     readconfig(tmpfname, configs, NUMCONFIGS);
  476.                     CheckSettings();
  477.                 }
  478. #ifdef DEBUG
  479.                 printf("done.\n");
  480. #endif
  481.  
  482.                 StripWhite(EMAIL);
  483.                 StripWhite(NAME); NAME[NAMELEN] = '\0';
  484.                 StripWhite(ALIAS); ALIAS[ALIASLEN] = '\0';
  485.                 sprintf(slog, "%d %s %d %s %s %s",
  486.                     port, StrNodeType(type), idx, EMAIL, ALIAS, NAME);
  487.                 logger(fp, slog);
  488.     
  489. #ifdef DEBUG
  490.                 printf("Read_MessageFile:[%s]\n", MESSAGEFILE); fflush(stdout);
  491. #endif
  492.                 if (readfile(MESSAGEFILE, banner, MAXMSG) < 0)
  493.                     sprintf(banner, "The Generic Frag Server\n");
  494.  
  495. #ifdef DEBUG
  496.                 printf("done.\n");
  497.                 printf("Sending Server Stat...");
  498. #endif
  499.                 ASockWrite(newfd, banner);
  500.                 ServerStat(newfd);
  501.                 if (type == PLAYER && NumPlayers()==NUMPLAYERS){
  502.                     type = GUEST;
  503.                     ASockWrite(newfd, "* No place for a player, switching to guest.\n* Type /player to join a game.");
  504.                 }
  505.  
  506.                 if (type == GOD && NumGods()==MAX_GODS){
  507.                     type = GUEST;
  508.                     ASockWrite(newfd, "* Too many gods.");
  509.                 }
  510.  
  511.                 idx = NewNode(type, newfd, NAME, EMAIL, ALIAS, IPstr);
  512.                 if (idx < 0){
  513.                     ASockWrite(newfd, "! Sorry. No more room for another victim.");
  514.                     ResetNode();
  515.                 }
  516.                 else {
  517.                     sprintf(msg, "+ %s %s connected.", StrNodeType(type),
  518.                         NodeStat(idx));
  519.                     WriteNodes(msg);
  520.                     helpme(newfd);
  521.                 }
  522.  
  523. #ifdef DEBUG
  524.                 printf("done.\n");
  525.                 printf("Listener_Listen[%d] port[%d]...", NumPlayers(), port);
  526.                 fflush(stdout);
  527. #endif
  528.                 newfd = -1;
  529.             } /* end of while */
  530.  
  531.             sprintf(msg, "\n%s\n%s\n* Prepare to meet you DOOM!\n* Waiting for another %d seconds....",
  532.                 PlayersStat(), PlayStat(), WAITASEC);
  533.             WriteNodes(msg);
  534.             sleep(WAITASEC);
  535.  
  536.             DELAY = DEFAULT_DELAY;
  537.  
  538.             commandline[0] = '\0';
  539.  
  540.             /* coop, deathmatch or altdeath */
  541.             if (strlen(MODE) > 0){
  542.                 strcat(commandline, MODE);
  543.                 strcat(commandline, "\n");
  544.             }
  545.  
  546.             /* skill level */
  547.             if (SKILL){
  548.                 sprintf(msg, "-skill %d\n", SKILL);
  549.                 strcat(commandline, msg);
  550.             }
  551.  
  552.             /* episode and mission number */
  553.             if (EPISODE) sprintf(msg, "-warp %d %d\n", EPISODE, MISSION);
  554.             else sprintf(msg, "-warp %d\n", MISSION);
  555.             strcat(commandline, msg);
  556.  
  557.             /* monsters */
  558.             if (strlen(MONSTERS) > 0){
  559.                 strcat(commandline, MONSTERS);
  560.                 strcat(commandline, "\n");
  561.             }
  562.  
  563.             /* wadfiles */
  564.             if (strlen(WADFILES) > 0){
  565.                 sprintf(msg, "-file %s\n", WADFILES);
  566.                 strcat(commandline, msg);
  567.             }
  568.  
  569.             /* timer */
  570.             if (TIMER){
  571.                 sprintf(msg, "-timer %d\n", TIMER);
  572.                 strcat(commandline, msg);
  573.             }
  574.  
  575.             /* port number */
  576.             if (PORT > 0){
  577.                 sprintf(msg, "-port %d\n", PORT);
  578.                 strcat(commandline, msg);
  579.             }
  580.  
  581.             signal(SIGPIPE, ResetServer);
  582.             sprintf(slog, "%d play %d", port, NumPlayers());
  583.             for (nodeidx=0, playernum=0; nodeidx<MAX_NODES; nodeidx++){
  584.  
  585.                 if (IsPlayer(nodes[nodeidx])){
  586.                     playernum++;
  587.                     ASockWrite(nodes[nodeidx].sd, CONNECT);
  588.  
  589.                     sprintf(msg2, "");
  590.                     if (strlen(EXTENSIONS))
  591.                         sprintf(msg, "%s -net %d ", EXTENSIONS, playernum);
  592.                     else
  593.                         sprintf(msg, "-net %d ", playernum);
  594.  
  595.                     for (j=0; j<MAX_NODES; j++){
  596.                         if ((nodeidx != j) && IsPlayer(nodes[j])){
  597.                             strcat(msg2, NodeStat(j));
  598.  
  599.                             strcat(msg, nodes[j].ip);
  600.                             strcat(msg, " ");
  601.                         }
  602.                     }
  603.  
  604.                     /* write out the someting for the client's log */
  605.                     StripWhite(msg2);
  606.                     ASockWrite(nodes[nodeidx].sd, msg2);
  607.  
  608.                     /* write the parameters for the response file */
  609.                     ASockWrite(nodes[nodeidx].sd, commandline);
  610.  
  611.                     /* send the commandline parameters to node[nodeidx] */
  612.                     StripWhite(msg);
  613.                     ASockWrite(nodes[nodeidx].sd, msg);
  614.  
  615.                     strcat(slog, " ");
  616.                     strcat(slog, IPstr);
  617.                 }
  618.             }
  619.  
  620.             logger(fp, slog);
  621.  
  622.             signal(SIGPIPE, Ignore);
  623.             sprintf(msg, "\n* Go.");
  624.             for (i=0; i<MAX_NODES; i++){
  625.                 if (IsPlayer(nodes[i])){
  626.                     ASockWrite(nodes[i].sd, msg);
  627.                     close(nodes[i].sd);
  628.                     InitNode(i);
  629.                 }
  630.             }
  631.  
  632. #ifdef DEBUG
  633.             printf("%d nodes Connected.\n", NUMPLAYERS);
  634. #endif
  635.             sprintf(msg, "\n* %d nodes Connected.\n", NUMPLAYERS);
  636.             WriteNodes(msg);
  637.             signal(SIGPIPE, ResetNode);
  638.  
  639.             }
  640.             break;
  641.         default:
  642.             break;
  643.     } /* end of switch */
  644. }
  645.  
  646.