home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / tinymud2.zip / INTERFAC.C < prev    next >
C/C++ Source or Header  |  1990-09-02  |  34KB  |  1,505 lines

  1. /* Concentrator upgraded June 1990 Robert Hood */
  2.  
  3. /* modifed Concentrator to match Fuzzy & Randoms 1.5.4 changes = 6/90 Fuzzy */
  4.  
  5. /* modified interface.c to support LOTS of people, using a concentrator */
  6. /* May 1990, Robert Hood */
  7.  
  8. /* #define CHECKC    /* consistency checking */
  9.  
  10. #include <stdio.h>
  11. #include <sys/param.h>
  12. #include <sys/types.h>
  13. #include <sys/file.h>
  14. #include <sys/time.h>
  15. #include <signal.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/wait.h>
  18. #include <fcntl.h>
  19. #include <sys/errno.h>
  20. #include <ctype.h>
  21. #include <sys/socket.h>
  22. #include <netinet/in.h>
  23. #include <netdb.h>
  24.  
  25. #include "config.h"
  26. #include "db.h"
  27. #include "interface.h"
  28.  
  29. #define BUFSIZE 0xFFFF
  30.  
  31. struct text_block
  32. {
  33.   int             nchars;
  34.   struct text_block *nxt;
  35.   char           *start;
  36.   char           *buf;
  37. };
  38.  
  39. struct text_queue
  40. {
  41.   struct text_block *head;
  42.   struct text_block **tail;
  43. };
  44.  
  45. struct descriptor_data
  46. {
  47.   int             descriptor;
  48.   int             num;
  49.   int             connected;
  50.   dbref           player;
  51.   char           *output_prefix;
  52.   char           *output_suffix;
  53.   int             output_size;
  54.   struct text_queue output;
  55.   struct text_queue input;
  56.   char           *raw_input;
  57.   char           *raw_input_at;
  58.   long            connected_at;
  59.   long            last_time;
  60.   int             quota;
  61.   struct sockaddr_in address;           /* added 3/6/90 SCG */
  62.   char           *hostname;           /* 5/18/90 - Fuzzy */
  63.   struct descriptor_data *next;
  64. };
  65.  
  66. #define MALLOC(result, type, number) do {            \
  67.     if (!((result) = (type *) malloc ((number) * sizeof (type))))    \
  68.         panic("Out of memory");                \
  69.     } while (0)
  70.  
  71. #define FREE(x) (free((void *) x))
  72.  
  73. struct message
  74. {
  75.   char           *data;
  76.   short           len;
  77.   struct message *next;
  78. };
  79.  
  80. struct conc_list
  81. {
  82.   struct conc_list *next;
  83.   int             sock, current, status;
  84.   struct descriptor_data *firstd;
  85.   struct message *first, *last;
  86.   char           *incoming, *outgoing;
  87.   int             ilen, olen;
  88. }              *firstc = 0;
  89.  
  90. void            queue_message(struct conc_list * c, char *data, int len);
  91. void            start_log();
  92. struct timeval  timeval_sub(struct timeval now, struct timeval then);
  93. struct timeval  msec_add(struct timeval t, int x);
  94. struct timeval  update_quotas(struct timeval last, struct timeval current);
  95. void            main_loop();
  96. int             notify(dbref player, const char *msg);
  97. void            process_output(struct conc_list * c);
  98. int             process_input(struct descriptor_data * d, char *buf, int got);
  99. void            process_commands();
  100. void            dump_users(struct descriptor_data * e, char *user);
  101. void            free_text_block(struct text_block * t);
  102. void            main(int argc, char **argv);
  103. void            set_signals();
  104. int             msec_diff(struct timeval now, struct timeval then);
  105. void            clearstrings(struct descriptor_data * d);
  106. void            shutdownsock(struct descriptor_data * d);
  107. struct descriptor_data *initializesock(struct sockaddr_in * a);
  108. struct text_block *make_text_block(const char *s, int n);
  109. void            add_to_queue(struct text_queue * q, const char *b, int n);
  110. int             flush_queue(struct text_queue * q, int n);
  111. int             queue_write(struct descriptor_data * d, const char *b, int n);
  112. int             queue_string(struct descriptor_data * d, const char *s);
  113. void            freeqs(struct descriptor_data * d);
  114. void            welcome_user(struct descriptor_data * d);
  115. void            do_motd(dbref);
  116. char           *strsave(const char *s);
  117. void            save_command(struct descriptor_data * d, const char *command);
  118. void            set_userstring(char **userstring, const char *command);
  119. int             do_command(struct descriptor_data * d, char *command);
  120. void            check_connect(struct descriptor_data * d, const char *msg);
  121. void            parse_connect(const char *msg, char *command, char *user, char *pass);
  122. void            close_sockets();
  123. void            emergency_shutdown(void);
  124. void            boot_off(dbref player);
  125. int             bailout(int sig, int code, struct sigcontext * scp);
  126. char           *time_format_1(long dt);
  127. char           *time_format_2(long dt);
  128. #ifdef CONNECT_MESSAGES
  129. void            announce_connect(dbref);
  130. void            announce_disconnect(dbref);
  131. #endif                       /* CONNECT_MESSAGES */
  132. int             sigshutdown(int, int, struct sigcontext *);
  133.  
  134. int             logsynch();
  135. char           *logfile = LOG_FILE;
  136.  
  137. int             debug;
  138. void            chg_userid();
  139. void            file_date(struct descriptor_data * d, const char *file);
  140.  
  141. static const char *connect_fail = "Either that player does not exist, or has a different password.\n";
  142. #ifndef REGISTRATION
  143. static const char *create_fail = "Either there is already a player with that name, or that name is illegal.\n";
  144. #endif                       /* REGISTRATION */
  145. static const char *flushed_message = "<Output Flushed>\n";
  146. static const char *shutdown_message = "Going down - Bye\n";
  147.  
  148. int             sock;
  149. int             shutdown_flag = 0;
  150.  
  151. int             port = TINYPORT;
  152. int             intport = INTERNAL_PORT;
  153.  
  154.  
  155. start_port()
  156. {
  157.   int             temp;
  158.   struct sockaddr_in sin;
  159.  
  160.   sock = socket(AF_INET, SOCK_STREAM, 0);
  161.   if (sock < 1)
  162.   {
  163.     perror("socket");
  164.     exit(-1);
  165.   }
  166.   temp = 1;
  167.   setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&temp, sizeof(temp));
  168.   sin.sin_family = AF_INET;
  169.   sin.sin_port = htons(intport);
  170.   sin.sin_addr.s_addr = htonl(INADDR_ANY);
  171.  
  172.   temp = bind(sock, (struct sockaddr *) & sin, sizeof(sin));
  173.   if (temp < 0)
  174.   {
  175.     perror("bind");
  176.     exit(-1);
  177.   }
  178.   temp = listen(sock, 5);
  179.   if (temp < 0)
  180.   {
  181.     perror("listen");
  182.     exit(-1);
  183.   }
  184. }
  185.  
  186. struct timeval
  187.                 timeval_sub(struct timeval now, struct timeval then)
  188. {
  189.                   now.tv_sec -= then.tv_sec;
  190.   now.tv_usec -= then.tv_usec;
  191.   if (now.tv_usec < 0)
  192.   {
  193.     now.tv_usec += 1000000;
  194.     now.tv_sec--;
  195.   }
  196.   return now;
  197. }
  198.  
  199. struct timeval
  200.                 msec_add(struct timeval t, int x)
  201. {
  202.                   t.tv_sec += x / 1000;
  203.   t.tv_usec += (x % 1000) * 1000;
  204.   if (t.tv_usec >= 1000000)
  205.   {
  206.     t.tv_sec += t.tv_usec / 1000000;
  207.     t.tv_usec = t.tv_usec % 1000000;
  208.   }
  209.   return t;
  210. }
  211.  
  212. struct timeval
  213.                 update_quotas(struct timeval last, struct timeval current)
  214. {
  215.   int             nslices;
  216.   struct descriptor_data *d;
  217.   struct conc_list *c;
  218.  
  219.   nslices = msec_diff(current, last) / COMMAND_TIME_MSEC;
  220.  
  221.   if (nslices > 0)
  222.   {
  223.     for (c = firstc; c; c = c->next)
  224.       for (d = c->firstd; d; d = d->next)
  225.       {
  226.     d->quota += COMMANDS_PER_TIME * nslices;
  227.     if (d->quota > COMMAND_BURST_SIZE)
  228.       d->quota = COMMAND_BURST_SIZE;
  229.       }
  230.   }
  231.   return msec_add(last, nslices * COMMAND_TIME_MSEC);
  232. }
  233.  
  234. int
  235.                 notify(dbref player2, const char *msg)
  236. {
  237.   struct descriptor_data *d;
  238.   struct conc_list *c;
  239.   int             retval = 0;
  240.  
  241. #ifdef COMPRESS
  242.   extern const char *uncompress(const char *);
  243.  
  244.   msg = uncompress(msg);
  245. #endif                       /* COMPRESS */
  246.   for (c = firstc; c; c = c->next)
  247.     for (d = c->firstd; d; d = d->next)
  248.     {
  249.       if (d->connected && d->player == player2)
  250.       {
  251.     queue_string(d, msg);
  252.     queue_write(d, "\n", 1);
  253.     retval++;
  254.       }
  255.     }
  256.   return (retval);
  257. }
  258.  
  259. int
  260.                 process_input(d, buf, got)
  261.   struct descriptor_data *d;
  262.   char           *buf;
  263.   int             got;
  264. {
  265.   char           *p, *pend, *q, *qend;
  266.  
  267.   d->last_time = time(0);
  268.   if (!d->raw_input)
  269.   {
  270.     MALLOC(d->raw_input, char, MAX_COMMAND_LEN);
  271.     d->raw_input_at = d->raw_input;
  272.   }
  273.   p = d->raw_input_at;
  274.   pend = d->raw_input + MAX_COMMAND_LEN - 1;
  275.   for (q = buf, qend = buf + got; q < qend; q++)
  276.   {
  277.     if (*q == '\n')
  278.     {
  279.       *p = '\0';
  280.       if (p > d->raw_input)
  281.     save_command(d, d->raw_input);
  282.       p = d->raw_input;
  283.     } else
  284.     if (p < pend && isascii(*q) && isprint(*q))
  285.     {
  286.       *p++ = *q;
  287.     }
  288.   }
  289.   if (p > d->raw_input)
  290.   {
  291.     d->raw_input_at = p;
  292.   } else
  293.   {
  294.     FREE(d->raw_input);
  295.     d->raw_input = 0;
  296.     d->raw_input_at = 0;
  297.   }
  298.   return 1;
  299. }
  300.  
  301. void            process_commands()
  302. {
  303.   int             nprocessed;
  304.   struct descriptor_data *d, *dnext, *dlast;
  305.   struct conc_list *c;
  306.   struct text_block *t;
  307.   char            header[4];
  308.  
  309.   do
  310.   {
  311.     nprocessed = 0;
  312.     for (c = firstc; c; c = c->next)
  313.     {
  314.       dlast = 0;
  315.       for (d = c->firstd; d; d = dnext)
  316.       {
  317.     dnext = d->next;
  318.     if (d->quota > 0 && (t = d->input.head))
  319.     {
  320.       d->quota--;
  321.       nprocessed++;
  322.       if (!do_command(d, t->start))
  323.       {
  324.         header[0] = 0;
  325.         header[1] = 2;
  326.         header[2] = d->num;
  327.         queue_message(c, header, 3);
  328.         if (dlast)
  329.           dlast->next = dnext;
  330.         else
  331.           c->firstd = dnext;
  332.         shutdownsock(d);
  333.         FREE(d);
  334.         break;
  335.       } else
  336.       {
  337.         d->input.head = t->nxt;
  338.         if (!d->input.head)
  339.           d->input.tail = &d->input.head;
  340.         free_text_block(t);
  341.       }
  342.     }
  343.     dlast = d;
  344.       }
  345.     }
  346.   } while (nprocessed > 0);
  347. }
  348.  
  349. void dump_users(struct descriptor_data * e, char *user)
  350. {
  351.   static struct conc_list *rwclist[NOFILE];
  352.   static struct descriptor_data *rwdlist[NOFILE];
  353.   int             ccount, dcount, dloop, cloop;
  354.  
  355.   struct descriptor_data *d;
  356.   struct conc_list *c;
  357.   long            now;
  358.   int             counter = 0;
  359.   static int      maxcounter = 0;
  360.   int             wizard, reversed, tabular;
  361.   char            buf[1024];
  362.  
  363.  
  364. # ifdef DO_WHOCHECK
  365.   writelog("WHO CHECK %d\n", sizeof(rwclist));
  366.   writelog("WHO CHECK %d\n", sizeof(rwdlist));
  367. # endif
  368.  
  369.   while (*user && isspace(*user))
  370.     user++;
  371.   if (!*user)
  372.     user = NULL;
  373.  
  374.   reversed = e->connected && Flag(e->player, REVERSED_WHO);
  375.   tabular = e->connected && Flag(e->player, TABULAR_WHO);
  376.  
  377.   time(&now);
  378.  
  379.   queue_string(e, tabular ? "Player Name          On For Idle\n" :
  380.            "Current Players:\n");
  381. #ifdef GOD_MODE
  382.   wizard = e->connected && God(e->player);
  383. #else  GOD_MODE
  384.   wizard = e->connected && Wizard(e->player);
  385. #endif GOD_MODE
  386.  
  387.   if (reversed)
  388.   {
  389.     ccount = 0;
  390.     for (c = firstc; c; c = c->next)
  391.       rwclist[ccount++] = c;
  392.     for (cloop = ccount - 1; cloop >= 0; --cloop)
  393.     {
  394.       dcount = 0;
  395.       for (d = rwclist[cloop]->firstd; d; d = d->next)
  396.     rwdlist[dcount++] = d;
  397.       for (dloop = dcount - 1; dloop >= 0; --dloop)
  398.       {
  399.     d = rwdlist[dloop];
  400.     if (d->connected &&
  401.         ++counter && /* Count everyone connected */
  402.         (!user || string_prefix(db[d->player].name, user)))
  403.     {
  404.       if (tabular)
  405.       {
  406.         sprintf(buf, "%-16s %10s %4s",
  407.             db[d->player].name,
  408.             time_format_1(now - d->connected_at),
  409.             time_format_2(now - d->last_time));
  410.  
  411.         if (wizard)
  412.           sprintf(buf, "%s  %s", buf, d->hostname);
  413.       } else
  414.       {
  415.         sprintf(buf, "%s idle %d seconds",
  416.             db[d->player].name, now - d->last_time);
  417.         if (wizard)
  418.           sprintf(buf, "%s from host %s", buf, d->hostname);
  419.       }
  420.       strcat(buf, "\n");
  421.       queue_string(e, buf);
  422.     }
  423.       }
  424.     }
  425.   } else
  426.   {
  427.     for (c = firstc; c; c = c->next)
  428.     {
  429.       for (d = c->firstd; d; d = d->next)
  430.       {
  431.     if (d->connected &&
  432.         ++counter && /* Count everyone connected */
  433.         (!user || string_prefix(db[d->player].name, user)))
  434.     {
  435.       if (tabular)
  436.       {
  437.         sprintf(buf, "%-16s %10s %4s",
  438.             db[d->player].name,
  439.             time_format_1(now - d->connected_at),
  440.             time_format_2(now - d->last_time));
  441.  
  442.         if (wizard)
  443.           sprintf(buf, "%s  %s", buf, d->hostname);
  444.       } else
  445.       {
  446.         sprintf(buf, "%s idle %d seconds",
  447.             db[d->player].name, now - d->last_time);
  448.         if (wizard)
  449.           sprintf(buf, "%s from host %s", buf, d->hostname);
  450.       }
  451.       strcat(buf, "\n");
  452.       queue_string(e, buf);
  453.     }
  454.       }
  455.     }
  456.   }
  457.   
  458.   if (counter > maxcounter)
  459.   { maxcounter = counter;
  460.     if (counter > 30)
  461.     { writelog ("%d users logged in\n", counter); }
  462.   }
  463.   
  464.   sprintf(buf, "%d user%s connected\n", counter,
  465.       counter == 1 ? " is" : "s are");
  466.   queue_string(e, buf);
  467. }
  468.  
  469. void free_text_block(struct text_block * t)
  470. {
  471.                   FREE(t->buf);
  472.   FREE((char *)t);
  473. }
  474.  
  475. #ifndef BOOLEXP_DEBUGGING
  476. void main(int argc, char **argv)
  477. {
  478.   int             pid;
  479.  
  480.   if (argc < 3)
  481.   {
  482.     fprintf(stderr, "Usage: %s infile dumpfile [port iport logfile]\n", *argv);
  483.     exit(1);
  484.  
  485.   }
  486.   if (argc > 3)
  487.     port = atoi(argv[3]);
  488.   if (argc > 4)
  489.     intport = atoi(argv[4]);
  490.   if (argc > 5)
  491.     logfile = argv[5];
  492.  
  493.   start_log();
  494.  
  495.   if (init_game(argv[1], argv[2]) < 0)
  496.   {
  497.     writelog("INIT: Couldn't load %s\n", argv[1]);
  498.     exit(2);
  499.   }
  500.   pid = vfork();
  501.   if (pid < 0)
  502.   {
  503.     perror("fork");
  504.     exit(-1);
  505.   }
  506.   if (pid == 0)
  507.   {
  508.     char            pstr[32], istr[32], clvl[32];
  509.  
  510.     /* Add port argument to concentrator */
  511.     sprintf(pstr, "%d", port);
  512.     sprintf(istr, "%d", intport);
  513.     sprintf(clvl, "%d", 1);
  514.     execl("concentrate", "conc", pstr, istr, clvl, 0);
  515.   }
  516.   set_signals();
  517.   start_port(port);
  518.   main_loop();
  519.   close_sockets();
  520.   dump_database();
  521.   exit(0);
  522. }
  523.  
  524. #endif
  525.  
  526. void start_log()
  527. {
  528. #ifdef DETACH
  529.   if              (!debug)
  530.   {
  531.     int             i;
  532.  
  533.     if (fork() != 0)
  534.       exit(0);
  535.  
  536.     i = open("/dev/tty", O_RDWR, 0);
  537.     if (i != -1)
  538.     {
  539.       ioctl(i, TIOCNOTTY, 0);
  540.       close(i);
  541.     }
  542.   }
  543.   freopen(logfile, "a", stderr);
  544.   setbuf(stderr, NULL);
  545. #endif                       /* DETACH */
  546. }
  547.  
  548. void set_signals(void)
  549. {
  550.   int             dump_status(void);
  551.   signal(SIGPIPE, SIG_IGN);
  552.  
  553.   signal(SIGINT, (void *)sigshutdown);
  554.   signal(SIGTERM, (void *)sigshutdown);
  555.  
  556. #ifdef DETACH
  557.   signal(SIGUSR2, (void *)logsynch);
  558. #else                       /* DETACH */
  559.   signal(SIGUSR2, (void *)bailout);
  560. #endif                       /* DETACH */
  561.  
  562.   if (debug)
  563.     return;
  564.  
  565. # ifdef NOCOREDUMP
  566.   signal(SIGQUIT, (void *)bailout);
  567.   signal(SIGILL, (void *)bailout);
  568.   signal(SIGTRAP, (void *)bailout);
  569.   signal(SIGIOT, (void *)bailout);
  570.   signal(SIGEMT, (void *)bailout);
  571.   signal(SIGFPE, (void *)bailout);
  572.   signal(SIGBUS, (void *)bailout);
  573.   signal(SIGSEGV, (void *)bailout);
  574.   signal(SIGSYS, (void *)bailout);
  575.   signal(SIGTERM, (void *)bailout);
  576.   signal(SIGXCPU, (void *)bailout);
  577.   signal(SIGXFSZ, (void *)bailout);
  578.   signal(SIGVTALRM, (void *)bailout);
  579. # endif
  580. }
  581.  
  582. int
  583.                 msec_diff(struct timeval now, struct timeval then)
  584. {
  585.                   return ((now.tv_sec - then.tv_sec) * 1000
  586.                +               (now.tv_usec - then.tv_usec) / 1000);
  587. }
  588.  
  589. void
  590.                 clearstrings(struct descriptor_data * d)
  591. {
  592.   if              (d->output_prefix)
  593.   {
  594.                     FREE(d->output_prefix);
  595.     d->output_prefix = 0;
  596.   }
  597.   if (d->output_suffix)
  598.   {
  599.     FREE(d->output_suffix);
  600.     d->output_suffix = 0;
  601.   }
  602. }
  603.  
  604. void
  605.                 shutdownsock(struct descriptor_data * d)
  606. {
  607.   if              (d->connected)
  608.   {
  609.                     writelog("DISCONNECT descriptor %d,%d player %s(%d)\n", d->descriptor, d->num, db[d->player].name, d->player);
  610. #ifdef CONNECT_MESSAGES
  611.     announce_disconnect(d->player);
  612. #endif                       /* CONNECT_MESSAGES */
  613.   } else
  614.   {
  615.     writelog("DISCONNECT descriptor %d,%d never connected\n", d->descriptor, d->num);
  616.   }
  617.   clearstrings(d);
  618.   freeqs(d);
  619. }
  620.  
  621. struct descriptor_data *
  622.                 initializesock(struct sockaddr_in * a)
  623. {
  624.   struct descriptor_data *d;
  625.  
  626.   MALLOC(d, struct descriptor_data, 1);
  627.   d->connected = 0;
  628.   d->output_prefix = 0;
  629.   d->output_suffix = 0;
  630.   d->output_size = 0;
  631.   d->output.head = 0;
  632.   d->output.tail = &d->output.head;
  633.   d->input.head = 0;
  634.   d->input.tail = &d->input.head;
  635.   d->raw_input = 0;
  636.   d->raw_input_at = 0;
  637.   d->quota = COMMAND_BURST_SIZE;
  638.   d->last_time = 0;
  639.   d->address = *a;               /* This will be the address of the
  640.                         * concentrator */
  641.   d->hostname = "";               /* This will be set during connect */
  642.  
  643.   welcome_user(d);
  644.   return d;
  645. }
  646.  
  647. struct text_block *
  648.                 make_text_block(const char *s, int n)
  649. {
  650.   struct text_block *p;
  651.  
  652.   MALLOC(p, struct text_block, 1);
  653.   MALLOC(p->buf, char, n);
  654.   bcopy(s, p->buf, n);
  655.   p->nchars = n;
  656.   p->start = p->buf;
  657.   p->nxt = 0;
  658.   return p;
  659. }
  660.  
  661. void
  662.                 add_to_queue(struct text_queue * q, const char *b, int n)
  663. {
  664.   struct text_block *p;
  665.  
  666.   if (n == 0)
  667.     return;
  668.  
  669.   p = make_text_block(b, n);
  670.   p->nxt = 0;
  671.   *q->tail = p;
  672.   q->tail = &p->nxt;
  673. }
  674.  
  675. int
  676.                 flush_queue(struct text_queue * q, int n)
  677. {
  678.   struct text_block *p;
  679.   int             really_flushed = 0;
  680.  
  681.   n += strlen(flushed_message);
  682.  
  683.   while (n > 0 && (p = q->head))
  684.   {
  685.     n -= p->nchars;
  686.     really_flushed += p->nchars;
  687.     q->head = p->nxt;
  688.     free_text_block(p);
  689.   }
  690.   p = make_text_block(flushed_message, strlen(flushed_message));
  691.   p->nxt = q->head;
  692.   q->head = p;
  693.   if (!p->nxt)
  694.     q->tail = &p->nxt;
  695.   really_flushed -= p->nchars;
  696.   return really_flushed;
  697. }
  698.  
  699. int
  700.                 queue_write(struct descriptor_data * d, const char *b, int n)
  701. {
  702.   int             space;
  703.  
  704.   space = MAX_OUTPUT - d->output_size - n;
  705.   if (space < 0)
  706.     d->output_size -= flush_queue(&d->output, -space);
  707.   add_to_queue(&d->output, b, n);
  708.   d->output_size += n;
  709.   return n;
  710. }
  711.  
  712. int
  713.                 queue_string(struct descriptor_data * d, const char *s)
  714. {
  715.                   return queue_write(d, s, strlen(s));
  716. }
  717.  
  718. void
  719.                 freeqs(struct descriptor_data * d)
  720. {
  721.   struct text_block *cur, *next;
  722.  
  723.   cur = d->output.head;
  724.   while (cur)
  725.   {
  726.     next = cur->nxt;
  727.     free_text_block(cur);
  728.     cur = next;
  729.   }
  730.   d->output.head = 0;
  731.   d->output.tail = &d->output.head;
  732.  
  733.   cur = d->input.head;
  734.   while (cur)
  735.   {
  736.     next = cur->nxt;
  737.     free_text_block(cur);
  738.     cur = next;
  739.   }
  740.   d->input.head = 0;
  741.   d->input.tail = &d->input.head;
  742.  
  743.   if (d->raw_input)
  744.     FREE(d->raw_input);
  745.   d->raw_input = 0;
  746.   d->raw_input_at = 0;
  747. }
  748.  
  749. void
  750.                 welcome_user(struct descriptor_data * d)
  751. {
  752.   queue_string(d, WELCOME_MESSAGE);
  753.   file_date(d, NEWS_FILE);
  754. # ifdef CONNECT_FILE
  755.   do_connect_msg(d, CONNECT_FILE);
  756. # endif
  757. }
  758.  
  759. void
  760.                 goodbye_user(struct descriptor_data * d)
  761. {
  762.                   queue_string(d, LEAVE_MESSAGE);
  763. }
  764.  
  765. char           *
  766.                 strsave(const char *s)
  767. {
  768.   char           *p;
  769.  
  770.   MALLOC(p, char, strlen(s) + 1);
  771.  
  772.   if (p)
  773.     strcpy(p, s);
  774.   return p;
  775. }
  776.  
  777. void
  778.                 save_command(struct descriptor_data * d, const char *command)
  779. {
  780.                   add_to_queue(&d->input, command, strlen(command) + 1);
  781. }
  782.  
  783. void
  784.                 set_userstring(char **userstring, const char *command)
  785. {
  786.   if              (*userstring)
  787.   {
  788.                     FREE(*userstring);
  789.     *userstring = 0;
  790.   }
  791.   while (*command && isascii(*command) && isspace(*command))
  792.     command++;
  793.   if (*command)
  794.     *userstring = strsave(command);
  795. }
  796.  
  797. int
  798.                 do_command(struct descriptor_data * d, char *command)
  799. {
  800.   if              (!strcmp(command, QUIT_COMMAND))
  801.   {
  802.                     goodbye_user(d);
  803.     return 0;
  804.   } else
  805.   if (!strncmp(command, WHO_COMMAND, strlen(WHO_COMMAND)))
  806.   {
  807.     if (d->output_prefix)
  808.     {
  809.       queue_string(d, d->output_prefix);
  810.       queue_write(d, "\n", 1);
  811.     }
  812.     dump_users(d, command + strlen(WHO_COMMAND));
  813.     if (d->output_suffix)
  814.     {
  815.       queue_string(d, d->output_suffix);
  816.       queue_write(d, "\n", 1);
  817.     }
  818.   } else
  819.     if (d->connected &&
  820.     !strncmp(command, PREFIX_COMMAND, strlen(PREFIX_COMMAND)))
  821.   {
  822. #ifdef ROBOT_MODE
  823.     if (!Robot(d->player))
  824.     {
  825. #ifndef TINKER
  826.       notify(d->player,
  827.          "Only robots can use OUTPUTPREFIX; contact a Wizard.");
  828. #else TINKER
  829.       notify(d->player,
  830.          "Only robots can use OUTPUTPREFIX; contact a Tinker.");
  831. #endif TINKER
  832.       return 1;
  833.     }
  834.     if (!d->connected)
  835.       return 1;
  836. #endif ROBOT_MODE
  837.     set_userstring(&d->output_prefix, command + strlen(PREFIX_COMMAND));
  838.   } else
  839.     if (d->connected &&
  840.     !strncmp(command, SUFFIX_COMMAND, strlen(SUFFIX_COMMAND)))
  841.   {
  842. #ifdef ROBOT_MODE
  843.     if (!Robot(d->player))
  844.     {
  845. #ifndef TINKER
  846.       notify(d->player,
  847.          "Only robots can use OUTPUTSUFFIX; contact a Wizard.");
  848. #else TINKER
  849.       notify(d->player,
  850.          "Only robots can use OUTPUTSUFFIX; contact a Tinker.");
  851. #endif TINKER
  852.       return 1;
  853.     }
  854. #endif ROBOT_MODE
  855.     set_userstring(&d->output_suffix, command + strlen(SUFFIX_COMMAND));
  856.   } else
  857.   {
  858.     if (d->connected)
  859.     {
  860.       if (d->output_prefix)
  861.       {
  862.     queue_string(d, d->output_prefix);
  863.     queue_write(d, "\n", 1);
  864.       }
  865.       process_command(d->player, command);
  866.       if (d->output_suffix)
  867.       {
  868.     queue_string(d, d->output_suffix);
  869.     queue_write(d, "\n", 1);
  870.       }
  871.     } else
  872.     {
  873.       check_connect(d, command);
  874.     }
  875.   }
  876.   return 1;
  877. }
  878.  
  879. void
  880.                 check_connect(struct descriptor_data * d, const char *msg)
  881. {
  882.   char            command[MAX_COMMAND_LEN];
  883.   char            user[MAX_COMMAND_LEN];
  884.   char            password[MAX_COMMAND_LEN];
  885.   dbref           player;
  886.  
  887.   parse_connect(msg, command, user, password);
  888.  
  889.   if (!strncmp(command, "co", 2))
  890.   {
  891.     player = connect_player(user, password);
  892.     if (player == NOTHING)
  893.     {
  894.       queue_string(d, connect_fail);
  895.       writelog("FAILED CONNECT %s on descriptor %d,%d\n", user, d->descriptor, d->num);
  896.     } else
  897.     {
  898.       writelog("CONNECTED %s(%d) on descriptor %d,%d %s\n",
  899.            db[player].name, player, d->descriptor, d->num, d->hostname);
  900.       d->connected = 1;
  901.       d->connected_at = time(NULL);
  902.       d->player = player;
  903.       do_motd(player);
  904.       do_look_around(player);
  905. #ifdef CONNECT_MESSAGES
  906.       announce_connect(player);
  907. #endif                       /* CONNECT_MESSAGES */
  908.     }
  909.   } else
  910.   if (!strncmp(command, "cr", 2))
  911.   {
  912. #ifndef REGISTRATION
  913.     player = create_player(user, password);
  914.     if (player == NOTHING)
  915.     {
  916.       queue_string(d, create_fail);
  917.       writelog("FAILED CREATE %s on descriptor %d,%d %s\n",
  918.            user, d->descriptor, d->num, d->hostname);
  919.     } else
  920.     {
  921.       writelog("CREATED %s(%d) on descriptor %d,%d %s\n",
  922.            db[player].name, player, d->descriptor, d->num, d->hostname);
  923.       d->connected = 1;
  924.       d->connected_at = time(0);
  925.       d->player = player;
  926.       do_motd(player);
  927.       do_look_around(player);
  928. #ifdef CONNECT_MESSAGES
  929.       announce_connect(player);
  930. #endif                       /* CONNECT_MESSAGES */
  931.     }
  932. #else
  933.     queue_string(d, REGISTER_MESSAGE);
  934. #endif                       /* REGISTRATION */
  935.   } else
  936.   {
  937.     welcome_user(d);
  938.   }
  939. }
  940.  
  941. void
  942.                 parse_connect(const char *msg, char *command, char *user, char *pass)
  943. {
  944.   char           *p;
  945.  
  946.   while (*msg && isascii(*msg) && isspace(*msg))
  947.     msg++;
  948.   p = command;
  949.   while (*msg && isascii(*msg) && !isspace(*msg))
  950.     *p++ = *msg++;
  951.   *p = '\0';
  952.   while (*msg && isascii(*msg) && isspace(*msg))
  953.     msg++;
  954.   p = user;
  955.   while (*msg && isascii(*msg) && !isspace(*msg))
  956.     *p++ = *msg++;
  957.   *p = '\0';
  958.   while (*msg && isascii(*msg) && isspace(*msg))
  959.     msg++;
  960.   p = pass;
  961.   while (*msg && isascii(*msg) && !isspace(*msg))
  962.     *p++ = *msg++;
  963.   *p = '\0';
  964. }
  965.  
  966. void
  967.                 close_sockets(void)
  968. {
  969.   struct descriptor_data *d, *dnext;
  970.   struct conc_list *c;
  971.   char            header[4];
  972.  
  973.   for (c = firstc; c; c = c->next)
  974.   {
  975.     /* conc.c now handles printing the Going Down - Bye message */
  976.     shutdown(c->sock, 0);
  977.     close(c->sock);
  978.   }
  979.   close(sock);
  980. }
  981.  
  982. void
  983.                 emergency_shutdown(void)
  984. {
  985.                   close_sockets();
  986. }
  987.  
  988. int
  989.                 bailout(int sig, int code, struct sigcontext * scp)
  990. {
  991.   long           *ptr;
  992.   int             i;
  993.  
  994.   writelog("BAILOUT: caught signal %d code %d", sig, code);
  995.   ptr = (long *)scp;
  996.   for (i = 0; i < sizeof(struct sigcontext); i++)
  997.     writelog("  %08lx\n", *ptr);
  998.   panic("PANIC on spurious signal");
  999.   _exit(7);
  1000.   return 0;
  1001. }
  1002.  
  1003. char           *
  1004.                 time_format_1(long dt)
  1005. {
  1006.   register struct tm *delta;
  1007.   static char     buf[64];
  1008.  
  1009.   delta = gmtime(&dt);
  1010.   if (delta->tm_yday > 0)
  1011.   {
  1012.     sprintf(buf, "%dd %02d:%02d",
  1013.         delta->tm_yday, delta->tm_hour, delta->tm_min);
  1014.   } else
  1015.   {
  1016.     sprintf(buf, "%02d:%02d",
  1017.         delta->tm_hour, delta->tm_min);
  1018.   }
  1019.   return buf;
  1020. }
  1021.  
  1022. char           *
  1023.                 time_format_2(long dt)
  1024. {
  1025.   register struct tm *delta;
  1026.   static char     buf[64];
  1027.  
  1028.   delta = gmtime(&dt);
  1029.   if (delta->tm_yday > 0)
  1030.   {
  1031.     sprintf(buf, "%dd", delta->tm_yday);
  1032.   } else
  1033.   if (delta->tm_hour > 0)
  1034.   {
  1035.     sprintf(buf, "%dh", delta->tm_hour);
  1036.   } else
  1037.   if (delta->tm_min > 0)
  1038.   {
  1039.     sprintf(buf, "%dm", delta->tm_min);
  1040.   } else
  1041.   {
  1042.     sprintf(buf, "%ds", delta->tm_sec);
  1043.   }
  1044.   return buf;
  1045. }
  1046.  
  1047. #ifdef CONNECT_MESSAGES
  1048. void
  1049.                 announce_connect(dbref player)
  1050. {
  1051.   dbref           loc;
  1052.   char            buf[BUFFER_LEN];
  1053.  
  1054.   if ((loc = getloc(player)) == NOTHING)
  1055.     return;
  1056.   if (Dark(player) || Dark(loc))
  1057.     return;
  1058.  
  1059.   sprintf(buf, "%s has connected.", db[player].name);
  1060.  
  1061.   notify_except(db[loc].contents, player, buf);
  1062. }
  1063.  
  1064. void
  1065.                 announce_disconnect(dbref player)
  1066. {
  1067.   dbref           loc;
  1068.   char            buf[BUFFER_LEN];
  1069.  
  1070.   if ((loc = getloc(player)) == NOTHING)
  1071.     return;
  1072.   if (Dark(player) || Dark(loc))
  1073.     return;
  1074.  
  1075.   sprintf(buf, "%s has disconnected.", db[player].name);
  1076.  
  1077.   notify_except(db[loc].contents, player, buf);
  1078. }
  1079.  
  1080. #endif                       /* CONNECT_MESSAGES */
  1081.  
  1082. int
  1083.                 sigshutdown(int sig, int code, struct sigcontext * scp)
  1084. {
  1085.                   writelog("SHUTDOWN: on signal %d code %d\n", sig, code);
  1086.   shutdown_flag = 1;
  1087.   return 0;
  1088. }
  1089.  
  1090. #ifdef DETACH
  1091. int
  1092.                 logsynch()
  1093. {
  1094.                   freopen(logfile, "a", stderr);
  1095.   setbuf(stderr, NULL);
  1096.   writelog("log file reopened\n");
  1097.   return 0;
  1098. }
  1099.  
  1100. #endif                       /* DETACH */
  1101.  
  1102. #include <sys/stat.h>
  1103.  
  1104. void
  1105.                 file_date(struct descriptor_data * d, char *file)
  1106. {
  1107.   static char     buf[80];
  1108.   extern char    *ctime(long *clock);
  1109.   struct stat     statb;
  1110.   char           *tstring;
  1111.   char           *cp;
  1112.  
  1113.   if (stat(file, &statb) == -1)
  1114.     return;
  1115.  
  1116.   tstring = ctime(&statb.st_mtime);
  1117.   if ((cp = (char *)index(tstring, '\n')) != NULL)
  1118.     *cp = '\0';
  1119.  
  1120.   strcpy(buf, "News last updated ");
  1121.   strcat(buf, tstring);
  1122.   strcat(buf, "\n\n");
  1123.  
  1124.   queue_string(d, (char *)buf);
  1125. }
  1126.  
  1127. void            main_loop()
  1128. {
  1129.   struct message *ptr;
  1130.   int             found, newsock, lastsock, len, loop;
  1131.   int             accepting;
  1132.   struct timeval  tv;
  1133.   struct sockaddr_in sin;
  1134.   fd_set          in, out;
  1135.   char            data[1025], *p1, *p2, buffer[1025], header[4];
  1136.   struct conc_list *c, *tempc, *nextc, *lastc;
  1137.   struct descriptor_data *d, *tempd, *nextd;
  1138.   struct timeval  last_slice, current_time;
  1139.   struct timeval  next_slice;
  1140.   struct timeval  slice_timeout;
  1141.   short           templen;
  1142.  
  1143.   accepting = 1;
  1144.   lastsock = sock + 1;
  1145.   while (!shutdown_flag)
  1146.   {
  1147.     gettimeofday(¤t_time, (struct timezone *) 0);
  1148.     last_slice = update_quotas(last_slice, current_time);
  1149.  
  1150.     process_commands();
  1151.  
  1152.     if (shutdown_flag)
  1153.       break;
  1154.  
  1155.     next_slice = msec_add(last_slice, COMMAND_TIME_MSEC);
  1156.     slice_timeout = timeval_sub(next_slice, current_time);
  1157.  
  1158.     FD_ZERO(&in);
  1159.     FD_ZERO(&out);
  1160.  
  1161.     FD_SET(sock, &in);
  1162.     for (c = firstc; c; c = c->next)
  1163.       process_output(c);
  1164.     for (c = firstc; c; c = c->next)
  1165.       if (c->sock)
  1166.       {
  1167.     if (c->ilen < BUFSIZE)
  1168.       FD_SET(c->sock, &in);
  1169.     len = c->first ? c->first->len : 0;
  1170.     while (c->first && ((c->olen + len + 2) < BUFSIZE))
  1171.     {
  1172.       templen = c->first->len;
  1173.       bcopy(&templen, c->outgoing + c->olen, 2);
  1174.       bcopy(c->first->data, c->outgoing + c->olen + 2, len);
  1175.       c->olen += len + 2;
  1176.       ptr = c->first;
  1177.       c->first = ptr->next;
  1178.       FREE(ptr->data);
  1179.       FREE(ptr);
  1180.       if (c->last == ptr)
  1181.         c->last = 0;
  1182.       len = c->first ? c->first->len : 0;
  1183.     }
  1184.     if (c->olen)
  1185.       FD_SET(c->sock, &out);
  1186.       }
  1187.     tv.tv_sec = 1000;
  1188.     tv.tv_usec = 0;
  1189.  
  1190.     found = select(lastsock, &in, &out, (fd_set *) 0, &tv);
  1191.     if (found < 0)
  1192.       continue;
  1193.     if (accepting && FD_ISSET(sock, &in))
  1194.     {
  1195.       len = sizeof(sin);
  1196.       newsock = accept(sock, (struct sockaddr *) & sin, &len);
  1197.       if (newsock >= 0)
  1198.       {
  1199.     if (newsock >= lastsock)
  1200.       lastsock = newsock + 1;
  1201.     if (fcntl(newsock, F_SETFL, FNDELAY) == -1)
  1202.     {
  1203.       perror("make_nonblocking: fcntl");
  1204.     }
  1205.     MALLOC(tempc, struct conc_list, 1);
  1206.     tempc->next = firstc;
  1207.     tempc->firstd = 0;
  1208.     tempc->first = 0;
  1209.     tempc->last = 0;
  1210.     tempc->status = 0;
  1211.     /* Imcomming and outgoing I/O buffers */
  1212.     MALLOC(tempc->incoming, char, BUFSIZE);
  1213.     tempc->ilen = 0;
  1214.     MALLOC(tempc->outgoing, char, BUFSIZE);
  1215.     tempc->olen = 0;
  1216.     firstc = tempc;
  1217.     firstc->sock = newsock;
  1218.     writelog("CONCENTRATOR CONNECT: sock %d, addr %x\n", newsock, sin.sin_addr.s_addr);
  1219.       }
  1220.     }
  1221.     for (c = firstc; c; c = nextc)
  1222.     {
  1223.       nextc = c->next;
  1224. #ifdef CHECKC
  1225.       if (!(c->sock))
  1226.     writelog("CONSISTENCY CHECK: Concentrator found with null socket #\n");
  1227. #endif
  1228.       if ((FD_ISSET(c->sock, &in)) && (c->ilen < BUFSIZE))
  1229.       {
  1230.     int             i;
  1231.     len = recv(c->sock, c->incoming + c->ilen,
  1232.            BUFSIZE - c->ilen, 0);
  1233.     if (len == 0)
  1234.     {
  1235.       struct message *mptr, *tempm;
  1236.       writelog("CONCENTRATOR DISCONNECT: %d\n", c->sock);
  1237.       close(c->sock);
  1238.       d = c->firstd;
  1239.       while (d)
  1240.       {
  1241.         shutdownsock(d);
  1242.         tempd = d;
  1243.         d = d->next;
  1244.         FREE(tempd);
  1245.       }
  1246.       if (firstc == c)
  1247.         firstc = firstc->next;
  1248.       else
  1249.         lastc->next = c->next;
  1250.       FREE(c->incoming);
  1251.       FREE(c->outgoing);
  1252.       mptr = c->first;
  1253.       while (mptr)
  1254.       {
  1255.         tempm = mptr;
  1256.         mptr = mptr->next;
  1257.         FREE(mptr->data);
  1258.         FREE(mptr);
  1259.       }
  1260.       FREE(c);
  1261.       break;
  1262.     } else
  1263.     if (len < 0)
  1264.     {
  1265.       writelog("recv: %s\n", strerror(errno));
  1266.     } else
  1267.     {
  1268.       int             num;
  1269.  
  1270.       c->ilen += len;
  1271.       while (c->ilen > 2)
  1272.       {
  1273.         bcopy(c->incoming, &templen, 2);
  1274. #ifdef CHECKC
  1275.         if (templen < 1)
  1276.           writelog("CONSISTENCY CHECK: Message recived with lenght < 1\n");
  1277. #endif
  1278.         if (c->ilen >= (templen + 2))
  1279.         {
  1280.           num = *(c->incoming + 2);
  1281.           /* Is it coming from the command user #? */
  1282.           if (num == 0)
  1283.           {
  1284.         /* Proccess commands */
  1285.         switch (*(c->incoming + 3))
  1286.         {
  1287.         case 1:           /* connect */
  1288.           d = initializesock(&sin);
  1289.           d->descriptor = c->sock;
  1290.           d->next = c->firstd;
  1291.           c->firstd = d;
  1292.           d->num = *(c->incoming + 4);
  1293.           MALLOC(d->hostname, char,
  1294.              templen - 5);
  1295.           bcopy(c->incoming + 9, d->hostname,
  1296.             templen - 6);
  1297.           *(d->hostname + templen - 7) = 0;
  1298. #ifdef DEBUG
  1299.           writelog("USER CONNECT %d,%d from host %s\n", c->sock, d->num, d->hostname);
  1300. #endif
  1301.           break;
  1302.         case 2:           /* disconnect */
  1303.           tempd = 0;
  1304.           d = c->firstd;
  1305.           num = *(c->incoming + 4);
  1306.           while (d)
  1307.           {
  1308.             if (d->num == num)
  1309.             {
  1310.               writelog("USER ABORTED CONNECTION %d,%d\n", c->sock, d->num);
  1311.               shutdownsock(d);
  1312.               if (c->firstd == d)
  1313.             c->firstd = d->next;
  1314.               else
  1315.             tempd->next = d->next;
  1316.               FREE(d);
  1317.               break;
  1318.             }
  1319.             tempd = d;
  1320.             d = d->next;
  1321.           }
  1322. #ifdef CHECKC
  1323.           if (!d)
  1324.             writelog("CONSISTENCY CHECK: Disconnect Received for unknown user %d,%d\n", c->sock, num);
  1325. #endif
  1326.           break;
  1327.  
  1328.           /*
  1329.            * This take a message from a concentrator, and logs it in
  1330.            * the log file 
  1331.            */
  1332.         case 4:
  1333.           {
  1334.             char            buffer[2048];
  1335.             bcopy(c->incoming + 4, buffer,
  1336.               templen - 2);
  1337.             *(buffer + templen - 1) = 0;
  1338.             writelog(buffer);
  1339.             break;
  1340.           }
  1341. #ifdef CHECKC
  1342.         default:
  1343.           writelog("CONSISTENCY CHECK: Received unknown command from concentrator\n");
  1344. #endif
  1345.         }
  1346.           } else
  1347.           {
  1348.         d = c->firstd;
  1349.         while (d)
  1350.         {
  1351.           if (d->num == num)
  1352.           {
  1353.             process_input(d, c->incoming + 3,
  1354.                   templen - 1);
  1355.             break;
  1356.           }
  1357.           d = d->next;
  1358.         }
  1359. #ifdef CHECKC
  1360.         if (!d)
  1361.           writelog("CONSISTENCY CHECK: Message received for unknown user %d,%d\n", c->sock, num);
  1362. #endif
  1363.           }
  1364.           bcopy(c->incoming + templen + 2, c->incoming,
  1365.             (c->ilen - templen - 2));
  1366.           c->ilen = c->ilen - templen - 2;
  1367.         } else
  1368.           break;
  1369.       }
  1370.     }
  1371.       }
  1372.       lastc = c;
  1373.     }
  1374.     /* Send data loop */
  1375.     for (c = firstc; c; c = c->next)
  1376.     {
  1377.       if (FD_ISSET(c->sock, &out))
  1378.       {
  1379.     if (c->olen)
  1380.     {
  1381.       len = send(c->sock, c->outgoing, c->olen, 0);
  1382.       if (len > 0)
  1383.       {
  1384.         c->olen -= len;
  1385.         bcopy(c->outgoing + len, c->outgoing, c->olen);
  1386.       }
  1387.     }
  1388.       }
  1389.     }
  1390.   }
  1391. }
  1392.  
  1393. void            process_output(struct conc_list * c)
  1394. {
  1395.   struct descriptor_data *d;
  1396.   struct text_block **qp, *cur;
  1397.   short           templen;
  1398.  
  1399.   for (d = c->firstd; d; d = d->next)
  1400.   {
  1401.     qp = &d->output.head;
  1402.     cur = *qp;
  1403.     if (cur)
  1404.     {
  1405.       if (cur->nchars < 512)
  1406.       {
  1407.     if ((c->olen + cur->nchars + 3) < BUFSIZE)
  1408.     {
  1409.       templen = cur->nchars + 1;
  1410.       bcopy(&templen, c->outgoing + c->olen, 2);
  1411.       *(c->outgoing + c->olen + 2) = d->num;
  1412.       strncpy(c->outgoing + c->olen + 3, cur->start, cur->nchars);
  1413.       d->output_size -= cur->nchars;
  1414.       c->olen += cur->nchars + 3;
  1415.       if (!cur->nxt)
  1416.         d->output.tail = qp;
  1417.       *qp = cur->nxt;
  1418.       free_text_block(cur);
  1419.     }
  1420.       } else
  1421.       {
  1422.     if ((c->olen + 512 + 3) < BUFSIZE)
  1423.     {
  1424.       templen = 512 + 1;
  1425.       bcopy(&templen, c->outgoing + c->olen, 2);
  1426.       *(c->outgoing + c->olen + 2) = d->num;
  1427.       strncpy(c->outgoing + c->olen + 3, cur->start, 512);
  1428.       d->output_size -= 512;
  1429.       c->olen += 512 + 3;
  1430.       cur->nchars -= 512;
  1431.       cur->start += 512;
  1432.     }
  1433.       }
  1434.     }
  1435.   }
  1436. }
  1437.  
  1438. void            boot_off(dbref player)
  1439. {
  1440.   struct conc_list *c;
  1441.   struct descriptor_data *d, *lastd;
  1442.   char            header[4];
  1443.  
  1444.   for (c = firstc; c; c = c->next)
  1445.   {
  1446.     lastd = 0;
  1447.     for (d = c->firstd; d; d = d->next)
  1448.     {
  1449.       if (d->connected && d->player == player)
  1450.       {
  1451.     header[0] = 0;
  1452.     header[1] = 2;
  1453.     header[2] = d->num;
  1454.     queue_message(c, header, 3);
  1455.     process_output(c);
  1456.     if (lastd)
  1457.       lastd->next = d->next;
  1458.     else
  1459.       c->firstd = d->next;
  1460.     shutdownsock(d);
  1461.     FREE(d);
  1462.     return;
  1463.       }
  1464.       lastd = d;
  1465.     }
  1466.   }
  1467. }
  1468.  
  1469. void            queue_message(struct conc_list * c, char *data, int len)
  1470. {
  1471.   struct message *ptr;
  1472.  
  1473.   MALLOC(ptr, struct message, 1);
  1474.   MALLOC(ptr->data, char, len);
  1475.   ptr->len = len;
  1476.   bcopy(data, ptr->data, len);
  1477.   ptr->next = 0;
  1478.   if (c->last == 0)
  1479.     c->first = ptr;
  1480.   else
  1481.     c->last->next = ptr;
  1482.   c->last = ptr;
  1483. }
  1484.  
  1485. int do_connect_msg(struct descriptor_data * d, const char *filename)
  1486. {
  1487.   FILE           *f;
  1488.   char            buf[BUFFER_LEN];
  1489.   char           *p;
  1490.  
  1491.   if ((f = fopen(filename, "r")) == NULL)
  1492.   {
  1493.     return (0);
  1494.   } else
  1495.   {
  1496.     while (fgets(buf, sizeof buf, f))
  1497.     {
  1498.       queue_string(d, (char *)buf);
  1499.  
  1500.     }
  1501.     fclose(f);
  1502.     return (1);
  1503.   }
  1504. }
  1505.