home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / d / d-linux.zip / dm-dist / comm.c < prev    next >
C/C++ Source or Header  |  1992-11-24  |  25KB  |  1,201 lines

  1. /* ************************************************************************
  2. *  file: comm.c , Communication module.                   Part of DIKUMUD *
  3. *  Usage: Communication, central game loop.                               *
  4. *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
  5. *  All Rights Reserved                                                    *
  6. *  Using *any* part of DikuMud without having read license.doc is         *
  7. *  violating our copyright.
  8. ************************************************************************* */
  9.  
  10. #include <errno.h>
  11. #include <stdio.h>
  12. #include <ctype.h>
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <sys/wait.h>
  16. #include <netinet/in.h>
  17. #include <netdb.h>
  18. #include <string.h>
  19. #include <sys/time.h>
  20. #include <fcntl.h>
  21. #include <signal.h>
  22.  
  23. #include "structs.h"
  24. #include "utils.h"
  25. #include "comm.h"
  26. #include "interpreter.h"
  27. #include "handler.h"
  28. #include "db.h"
  29.  
  30. #define DFLT_PORT 4000        /* default port */
  31. #define MAX_NAME_LENGTH 15
  32. #define MAX_HOSTNAME   256
  33. #define OPT_USEC 250000       /* time delay corresponding to 4 passes/sec */
  34.  
  35.  
  36.  
  37. extern int errno;    /* Why isn't this done in errno.h on alfa??? */
  38.  
  39. /* externs */
  40.  
  41. /* extern struct char_data *character_list; */
  42.  
  43. extern struct room_data *world;      /* In db.c */
  44. extern int top_of_world;            /* In db.c */
  45. extern struct time_info_data time_info;  /* In db.c */
  46. extern char help[];
  47.  
  48. /* local globals */
  49.  
  50. struct descriptor_data *descriptor_list, *next_to_process;
  51.  
  52. int lawful = 0;        /* work like the game regulator */
  53. int slow_death = 0;  /* Shut her down, Martha, she's sucking mud */
  54. int diku_shutdown = 0;    /* clean shutdown */
  55. int reboot = 0;      /* reboot the game after a shutdown */
  56. int no_specials = 0; /* Suppress ass. of special routines */
  57.  
  58. int maxdesc, avail_descs;
  59. int tics = 0;        /* for extern checkpointing */
  60.  
  61. int get_from_q(struct txt_q *queue, char *dest);
  62. /* write_to_q is in comm.h for the macro */
  63. int run_the_game(int port);
  64. int game_loop(int s);
  65. int init_socket(int port);
  66. int new_connection(int s);
  67. int new_descriptor(int s);
  68. int process_output(struct descriptor_data *t);
  69. int process_input(struct descriptor_data *t);
  70. void close_sockets(int s);
  71. void close_socket(struct descriptor_data *d);
  72. struct timeval timediff(struct timeval *a, struct timeval *b);
  73. void flush_queues(struct descriptor_data *d);
  74. void nonblock(int s);
  75. void parse_name(struct descriptor_data *desc, char *arg);
  76.  
  77.  
  78. /* extern fcnts */
  79.  
  80. struct char_data *make_char(char *name, struct descriptor_data *desc);
  81. void boot_db(void);
  82. void zone_update(void);
  83. void affect_update( void ); /* In spells.c */
  84. void point_update( void );  /* In limits.c */
  85. void free_char(struct char_data *ch);
  86. void log(char *str);
  87. void mobile_activity(void);
  88. void string_add(struct descriptor_data *d, char *str);
  89. void perform_violence(void);
  90. void stop_fighting(struct char_data *ch);
  91. void show_string(struct descriptor_data *d, char *input);
  92. void gr(int s);
  93.  
  94. void check_reboot(void);
  95.  
  96. /* *********************************************************************
  97. *  main game loop and related stuff                       *
  98. ********************************************************************* */
  99.  
  100.  
  101.  
  102.  
  103. int main(int argc, char **argv)
  104. {
  105.     int port;
  106.     char buf[512];
  107.     int pos = 1;
  108.     char *dir;
  109.  
  110.     port = DFLT_PORT;
  111.     dir = DFLT_DIR;
  112.  
  113.     while ((pos < argc) && (*(argv[pos]) == '-'))
  114.     {
  115.         switch (*(argv[pos] + 1))
  116.         {
  117.             case 'l':
  118.                 lawful = 1;
  119.                 log("Lawful mode selected.");
  120.             break;
  121.             case 'd':
  122.                 if (*(argv[pos] + 2))
  123.                     dir = argv[pos] + 2;
  124.                 else if (++pos < argc)
  125.                     dir = argv[pos];
  126.                 else
  127.                 {
  128.                     log("Directory arg expected after option -d.");
  129.                     exit(0);
  130.                 }
  131.             break;
  132.             case 's':
  133.                 no_specials = 1;
  134.                 log("Suppressing assignment of special routines.");
  135.             break;
  136.             default:
  137.                 sprintf(buf, "Unknown option -% in argument string.",
  138.                     *(argv[pos] + 1));
  139.                 log(buf);
  140.             break;
  141.         }
  142.         pos++;
  143.     }
  144.     
  145.     if (pos < argc)
  146.         if (!isdigit(*argv[pos]))
  147.         {
  148.             fprintf(stderr, "Usage: %s [-l] [-s] [-d pathname] [ port # ]\n", 
  149.                 argv[0]);
  150.             exit(0);
  151.         }
  152.         else if ((port = atoi(argv[pos])) <= 1024)
  153.         {
  154.             printf("Illegal port #\n");
  155.             exit(0);
  156.         }
  157.  
  158.     sprintf(buf, "Running game on port %d.", port);
  159.     log(buf);
  160.  
  161.     if (chdir(dir) < 0)
  162.     {
  163.         perror("chdir");
  164.         exit(0);
  165.     }
  166.  
  167.     sprintf(buf, "Using %s as data directory.", dir);
  168.     log(buf);
  169.  
  170.     srandom(time(0));
  171.     run_the_game(port);
  172.     return(0);
  173. }
  174.  
  175.  
  176.  
  177.  
  178.  
  179. #define PROFILE(x)
  180.  
  181.  
  182. /* Init sockets, run game, and cleanup sockets */
  183. int run_the_game(int port)
  184. {
  185.     int s; 
  186.     PROFILE(extern etext();)
  187.  
  188.     void signal_setup(void);
  189.     int load(void);
  190.     void coma(void);
  191.  
  192.     PROFILE(monstartup((int) 2, etext);)
  193.  
  194.     descriptor_list = NULL;
  195.  
  196.     log("Signal trapping.");
  197.     signal_setup();
  198.  
  199.     log("Opening mother connection.");
  200.     s = init_socket(port);
  201.  
  202.     if (lawful && load() >= 6)
  203.     {
  204.         log("System load too high at startup.");
  205.         coma();
  206.     }
  207.  
  208.     boot_db();
  209.  
  210.     log("Entering game loop.");
  211.  
  212.     game_loop(s);
  213.  
  214.     close_sockets(s); 
  215.  
  216.     PROFILE(monitor(0);)
  217.  
  218.     if (reboot)
  219.     {
  220.         log("Rebooting.");
  221.         exit(52);            /* what's so great about HHGTTG, anyhow? */
  222.     }
  223.  
  224.     log("Normal termination of game.");
  225. }
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232. /* Accept new connects, relay commands, and call 'heartbeat-functs' */
  233. int game_loop(int s)
  234. {
  235.     int tmp_room, old_len;
  236.     fd_set input_set, output_set, exc_set;
  237.     struct timeval last_time, now, timespent, timeout, null_time;
  238.     static struct timeval opt_time;
  239.     char comm[MAX_INPUT_LENGTH];
  240.     struct descriptor_data *t, *point, *next_point;
  241.     int pulse = 0, mask;
  242.  
  243.     null_time.tv_sec = 0;
  244.     null_time.tv_usec = 0;
  245.  
  246.     opt_time.tv_usec = OPT_USEC;  /* Init time values */
  247.     opt_time.tv_sec = 0;
  248.     gettimeofday(&last_time, (struct timezone *) 0);
  249.  
  250.     maxdesc = s;
  251.     avail_descs = getdtablesize() - 2; /* !! Change if more needed !! */
  252.  
  253.     mask = sigmask(SIGUSR1) | sigmask(SIGUSR2) | sigmask(SIGINT) |
  254.         sigmask(SIGPIPE) | sigmask(SIGALRM) | sigmask(SIGTERM) |
  255.         sigmask(SIGURG) | sigmask(SIGXCPU) | sigmask(SIGHUP);
  256.  
  257.     /* Main loop */
  258.     while (!diku_shutdown)
  259.     {
  260.         /* Check what's happening out there */
  261.         FD_ZERO(&input_set);
  262.         FD_ZERO(&output_set);
  263.         FD_ZERO(&exc_set);
  264.         FD_SET(s, &input_set);
  265.         for (point = descriptor_list; point; point = point->next)
  266.         {
  267.             FD_SET(point->descriptor, &input_set);
  268.             FD_SET(point->descriptor, &exc_set);
  269.             FD_SET(point->descriptor, &output_set);
  270.         }
  271.  
  272.         /* check out the time */
  273.         gettimeofday(&now, (struct timezone *) 0);
  274.         timespent = timediff(&now, &last_time);
  275.         timeout = timediff(&opt_time, ×pent);
  276.         last_time.tv_sec = now.tv_sec + timeout.tv_sec;
  277.         last_time.tv_usec = now.tv_usec + timeout.tv_usec;
  278.         if (last_time.tv_usec >= 1000000)
  279.         {
  280.             last_time.tv_usec -= 1000000;
  281.             last_time.tv_sec++;
  282.         }
  283.  
  284.         sigsetmask(mask);
  285.  
  286.         if (select(maxdesc + 1, &input_set, &output_set, &exc_set, &null_time) 
  287.             < 0)
  288.         {
  289.             perror("Select poll");
  290.             return(-1);
  291.         }
  292.  
  293.         if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &timeout) < 0)
  294.         {
  295.             perror("Select sleep");
  296.             exit(1);
  297.         }
  298.  
  299.         sigsetmask(0);
  300.  
  301.         /* Respond to whatever might be happening */
  302.         
  303.         /* New connection? */
  304.          if (FD_ISSET(s, &input_set))
  305.             if (new_descriptor(s) < 0)
  306.                 perror("New connection");
  307.  
  308.         /* kick out the freaky folks */
  309.         for (point = descriptor_list; point; point = next_point)
  310.         {
  311.             next_point = point->next;   
  312.             if (FD_ISSET(point->descriptor, &exc_set))
  313.             {
  314.                 FD_CLR(point->descriptor, &input_set);
  315.                 FD_CLR(point->descriptor, &output_set);
  316.                 close_socket(point);
  317.             }
  318.         }
  319.  
  320.         for (point = descriptor_list; point; point = next_point) 
  321.         {
  322.             next_point = point->next;
  323.             if (FD_ISSET(point->descriptor, &input_set))
  324.                  if (process_input(point) < 0) 
  325.             close_socket(point);
  326.          }
  327.  
  328.         /* process_commands; */
  329.         for (point = descriptor_list; point; point = next_to_process)
  330.         {
  331.             next_to_process = point->next;
  332.  
  333.             if ((--(point->wait) <= 0) && get_from_q(&point->input, comm))
  334.             {
  335.                 if (point->character && point->connected == CON_PLYNG &&
  336.                     point->character->specials.was_in_room !=    NOWHERE)
  337.                 {
  338.                     if (point->character->in_room != NOWHERE)
  339.                         char_from_room(point->character);
  340.                     char_to_room(point->character, 
  341.                         point->character->specials.was_in_room);
  342.                     point->character->specials.was_in_room = NOWHERE;
  343.                     act("$n has returned.",    TRUE, point->character, 0, 0, TO_ROOM);
  344.                 }
  345.  
  346.                 point->wait = 1;
  347.                 if (point->character)
  348.                     point->character->specials.timer = 0;
  349.                 point->prompt_mode = 1;
  350.  
  351.                 if (point->str)
  352.                     string_add(point, comm);
  353.                 else if (!point->connected) 
  354.                     if (point->showstr_point)
  355.                         show_string(point, comm);
  356.                     else
  357.                         command_interpreter(point->character, comm);
  358.                 else 
  359.                     nanny(point, comm); 
  360.             }
  361.         }
  362.  
  363.  
  364.         for (point = descriptor_list; point; point = next_point) 
  365.         {
  366.             next_point = point->next;
  367.             if (FD_ISSET(point->descriptor, &output_set) && point->output.head)
  368.                 if (process_output(point) < 0)
  369.                     close_socket(point);
  370.                 else
  371.                     point->prompt_mode = 1;
  372.          }
  373.  
  374.         /* give the people some prompts */
  375.         for (point = descriptor_list; point; point = point->next)
  376.             if (point->prompt_mode)
  377.             {
  378.                 if (point->str)
  379.                     write_to_descriptor(point->descriptor, "] ");
  380.                 else if (!point->connected)
  381.                     if (point->showstr_point)
  382.                         write_to_descriptor(point->descriptor,
  383.                             "*** Press return ***");
  384.                     else                    
  385.                         write_to_descriptor(point->descriptor, "> ");
  386.                 point->prompt_mode = 0;
  387.             }
  388.  
  389.  
  390.  
  391.         /* handle heartbeat stuff */
  392.         /* Note: pulse now changes every 1/4 sec  */
  393.  
  394.         pulse++;
  395.  
  396.         if (!(pulse % PULSE_ZONE))
  397.         {
  398.             zone_update();
  399.             if (lawful)
  400.                 gr(s);
  401.         }
  402.  
  403.  
  404.         if (!(pulse % PULSE_MOBILE))
  405.             mobile_activity();
  406.  
  407.         if (!(pulse % PULSE_VIOLENCE))
  408.             perform_violence();
  409.  
  410.         if (!(pulse % (SECS_PER_MUD_HOUR*4))){
  411.             weather_and_time(1);
  412.             affect_update();
  413.             point_update();
  414.             if ( time_info.hours == 1 )
  415.                 update_time();
  416.         }
  417.  
  418.         if (pulse >= 2400) {
  419.             pulse = 0;
  420.             if (lawful)
  421.                 night_watchman();
  422.             check_reboot();
  423.         }
  424.  
  425.         tics++;        /* tics since last checkpoint signal */
  426.     }
  427. }
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434. /* ******************************************************************
  435. *  general utility stuff (for local use)                                     *
  436. ****************************************************************** */
  437.  
  438.  
  439.  
  440.  
  441. int get_from_q(struct txt_q *queue, char *dest)
  442. {
  443.     struct txt_block *tmp;
  444.  
  445.      /* Q empty? */
  446.     if (!queue->head)
  447.         return(0);
  448.  
  449.     tmp = queue->head;
  450.     strcpy(dest, queue->head->text);
  451.     queue->head = queue->head->next;
  452.  
  453.     free(tmp->text);
  454.     free(tmp);
  455.  
  456.     return(1);
  457. }
  458.  
  459.  
  460.  
  461.  
  462. void write_to_q(char *txt, struct txt_q *queue)
  463. {
  464.     struct txt_block *new;
  465.  
  466.     CREATE(new, struct txt_block, 1);
  467.     CREATE(new->text, char, strlen(txt) + 1);
  468.  
  469.     strcpy(new->text, txt);
  470.  
  471.     /* Q empty? */
  472.     if (!queue->head)
  473.     {
  474.         new->next = NULL;
  475.         queue->head = queue->tail = new;
  476.     }
  477.     else
  478.     {
  479.         queue->tail->next = new;
  480.         queue->tail = new;
  481.         new->next = NULL;
  482.     }
  483. }
  484.         
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491. struct timeval timediff(struct timeval *a, struct timeval *b)
  492. {
  493.     struct timeval rslt, tmp;
  494.  
  495.     tmp = *a;
  496.  
  497.     if ((rslt.tv_usec = tmp.tv_usec - b->tv_usec) < 0)
  498.     {
  499.         rslt.tv_usec += 1000000;
  500.         --(tmp.tv_sec);
  501.     }
  502.     if ((rslt.tv_sec = tmp.tv_sec - b->tv_sec) < 0)
  503.     {
  504.         rslt.tv_usec = 0;
  505.         rslt.tv_sec =0;
  506.     }
  507.     return(rslt);
  508. }
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515. /* Empty the queues before closing connection */
  516. void flush_queues(struct descriptor_data *d)
  517. {
  518.     char dummy[MAX_STRING_LENGTH];
  519.  
  520.     while (get_from_q(&d->output, dummy));
  521.     while (get_from_q(&d->input, dummy));
  522. }
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529. /* ******************************************************************
  530. *  socket handling                             *
  531. ****************************************************************** */
  532.  
  533.  
  534.  
  535.  
  536. int init_socket(int port)
  537. {
  538.     int s;
  539.     char *opt;
  540.     char hostname[MAX_HOSTNAME+1];
  541.     struct sockaddr_in sa;
  542.     struct hostent *hp;
  543. /*    struct linger ld;  */
  544. /*  linger stuff not supported by Linux.... Taken out bsp 11/22/92 */
  545.  
  546.     bzero(&sa, sizeof(struct sockaddr_in));
  547.     gethostname(hostname, MAX_HOSTNAME);
  548. /*    hp = gethostbyname(hostname);
  549.     if (hp == NULL)
  550.     {
  551.         perror("gethostbyname");
  552.         exit(1);
  553.     }
  554. */
  555. /* The gethostbyname function call returns NULL all the time.  I have not */
  556. /* gotten this to work without this, however, the only reason it is called */
  557. /* is to get the h_addrtype constant.  The value AF_INET is used in other */
  558. /* operating systems so I figure it is reasonable for here....     (bsp) */
  559. /*    sa.sin_family = hp->h_addrtype; */
  560.     sa.sin_family = AF_INET;
  561.     sa.sin_port    = htons(port);
  562.     s = socket(AF_INET, SOCK_STREAM, 0);
  563.     if (s < 0) 
  564.     {
  565.         perror("Init-socket");
  566.         exit(1);
  567.      }
  568.     if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR,
  569.         (char *) &opt, sizeof (opt)) < 0) 
  570.     {
  571.         perror ("setsockopt REUSEADDR");
  572.         exit (1);
  573.     }
  574. /*
  575.     ld.l_onoff = 1;
  576.     ld.l_linger = 1000;
  577.     if (setsockopt(s, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) < 0)
  578.     {
  579.         perror("setsockopt LINGER");
  580.         exit(1);
  581.     }
  582. */
  583. /* linger stuff taken out by bsp */
  584.     if (bind(s,(struct sockaddr *)&sa, sizeof(sa)) < 0)
  585.     {
  586.         perror("bind");
  587.         close(s);
  588.         exit(1);
  589.     }
  590.     listen(s, 3);
  591.     return(s);
  592. }
  593.  
  594.  
  595.  
  596.  
  597.  
  598. int new_connection(int s)
  599. {
  600. /*    struct sockaddr_in isa;*/
  601.     struct sockaddr isa;
  602.     /* struct sockaddr peer; */
  603.     int i;
  604.     int t;
  605.     char buf[100];
  606.  
  607.     i = sizeof(isa);
  608.     getsockname(s, &isa, &i);
  609.  
  610.  
  611.     if ((t = accept(s, &isa, &i)) < 0)
  612.     {
  613.         perror("Accept");
  614.         return(-1);
  615.     }
  616.     nonblock(t);
  617.  
  618.     /*
  619.  
  620.     i = sizeof(peer);
  621.     if (!getpeername(t, &peer, &i))
  622.     {
  623.         *(peer.sa_data + 49) = '\0';
  624.         sprintf(buf, "New connection from addr %s.\n", peer.sa_data);
  625.         log(buf);
  626.     }
  627.  
  628.     */
  629.  
  630.     return(t);
  631. }
  632.  
  633.  
  634.  
  635.  
  636.  
  637. int new_descriptor(int s)
  638. {
  639.     int desc;
  640.     struct descriptor_data *newd;
  641.     int size;
  642.     struct sockaddr_in sock;
  643.     struct hostent *from;
  644.     char buf[10];
  645.  
  646.     if ((desc = new_connection(s)) < 0)
  647.         return (-1);
  648.     
  649.  
  650.     if ((maxdesc + 1) >= avail_descs)
  651.     {
  652.         write_to_descriptor(desc, "Sorry.. The game is full...\n\r");
  653.         close(desc);
  654.         return(0);
  655.     }
  656.     else
  657.         if (desc > maxdesc)
  658.             maxdesc = desc;
  659.  
  660.     CREATE(newd, struct descriptor_data, 1);
  661.  
  662.     /* find info */
  663.     size = sizeof(sock);
  664.     if (getpeername(desc, (struct sockaddr *) &sock, &size) < 0)
  665.     {
  666.         perror("getpeername");
  667.         *newd->host = '\0';
  668.     }
  669.     else if (!(from = gethostbyaddr((char*)&sock.sin_addr,
  670.         sizeof(sizeof(sock.sin_addr)), AF_INET)))
  671.     {
  672.         perror("gethostbyaddr");
  673.         *newd->host = '\0';
  674.     }
  675.     else
  676.     {
  677.         strncpy(newd->host, from->h_name, 49);
  678.         *(newd->host + 49) = '\0';
  679.     }
  680.         
  681.     
  682.     /* init desc data */
  683.     newd->descriptor = desc;
  684.     newd->connected  = 1;
  685.     newd->wait = 1;
  686.     newd->prompt_mode = 0;
  687.     *newd->buf = '\0';
  688.     newd->str = 0;
  689.     newd->showstr_head = 0;
  690.     newd->showstr_point = 0;
  691.     *newd->last_input= '\0';
  692.     newd->output.head = NULL;
  693.     newd->input.head = NULL;
  694.     newd->next = descriptor_list;
  695.     newd->character = 0;
  696.     newd->original = 0;
  697.     newd->snoop.snooping = 0;
  698.     newd->snoop.snoop_by = 0;
  699.  
  700.     /* prepend to list */
  701.  
  702.     descriptor_list = newd;
  703.  
  704.     SEND_TO_Q(GREETINGS, newd);
  705.     SEND_TO_Q("By what name do you wish to be known? ", newd);
  706.  
  707.     return(0);
  708. }
  709.     
  710.  
  711.  
  712.  
  713.  
  714. int process_output(struct descriptor_data *t)
  715. {
  716.     char i[MAX_STRING_LENGTH + 1];
  717.  
  718.     if (!t->prompt_mode && !t->connected)
  719.         if (write_to_descriptor(t->descriptor, "\n\r") < 0)
  720.             return(-1);
  721.  
  722.  
  723.     /* Cycle thru output queue */
  724.     while (get_from_q(&t->output, i))
  725.     {  
  726.         if(t->snoop.snoop_by)
  727.         {
  728.             write_to_q("% ",&t->snoop.snoop_by->desc->output);
  729.             write_to_q(i,&t->snoop.snoop_by->desc->output);
  730.         }
  731.         if (write_to_descriptor(t->descriptor, i))
  732.             return(-1);
  733.     }
  734.     
  735.     if (!t->connected && !(t->character && !IS_NPC(t->character) && 
  736.                                   IS_SET(t->character->specials.act, PLR_COMPACT)))
  737.         if (write_to_descriptor(t->descriptor, "\n\r") < 0)
  738.             return(-1);
  739.  
  740.     return(1);
  741. }
  742.  
  743.  
  744. int write_to_descriptor(int desc, char *txt)
  745. {
  746.     int sofar, thisround, total;
  747.  
  748.     total = strlen(txt);
  749.     sofar = 0;
  750.  
  751.     do
  752.     {
  753.         thisround = write(desc, txt + sofar, total - sofar);
  754.         if (thisround < 0)
  755.         {
  756.             perror("Write to socket");
  757.             return(-1);
  758.         }
  759.         sofar += thisround;
  760.     } 
  761.     while (sofar < total);
  762.  
  763.     return(0);
  764. }
  765.  
  766.  
  767.  
  768.  
  769.  
  770. int process_input(struct descriptor_data *t)
  771. {
  772.     int sofar, thisround, begin, squelch, i, k, flag;
  773.     char tmp[MAX_INPUT_LENGTH+2], buffer[MAX_INPUT_LENGTH + 60];
  774.  
  775.     sofar = 0;
  776.     flag = 0;
  777.     begin = strlen(t->buf);
  778.  
  779.     /* Read in some stuff */
  780.     do
  781.     {
  782.         if ((thisround = read(t->descriptor, t->buf + begin + sofar, 
  783.             MAX_STRING_LENGTH - (begin + sofar) - 1)) > 0)
  784.             sofar += thisround;        
  785.         else
  786.             if (thisround < 0)
  787.                 if(errno != EWOULDBLOCK)
  788.                      {
  789.                     perror("Read1 - ERROR");
  790.                     return(-1);
  791.                 }
  792.                 else
  793.                     break;
  794.             else
  795.             {
  796.                 log("EOF encountered on socket read.");
  797.                 return(-1);
  798.             }
  799.     }
  800.     while (!ISNEWL(*(t->buf + begin + sofar - 1)));    
  801.  
  802.     *(t->buf + begin + sofar) = 0;
  803.  
  804.     /* if no newline is contained in input, return without proc'ing */
  805.     for (i = begin; !ISNEWL(*(t->buf + i)); i++)
  806.         if (!*(t->buf + i))
  807.             return(0);
  808.  
  809.     /* input contains 1 or more newlines; process the stuff */
  810.     for (i = 0, k = 0; *(t->buf + i);)
  811.     {
  812.         if (!ISNEWL(*(t->buf + i)) && !(flag = (k >= (MAX_INPUT_LENGTH - 2))))
  813.             if(*(t->buf + i) == '\b')     /* backspace */
  814.                 if (k)  /* more than one char ? */
  815.                 {
  816.                     if (*(tmp + --k) == '$')
  817.                         k--;                
  818.                     i++;
  819.                   }
  820.                 else
  821.                      i++;  /* no or just one char.. Skip backsp */
  822.             else
  823.                 if (isascii(*(t->buf + i)) && isprint(*(t->buf + i)))
  824.                 {
  825.                     /* trans char, double for '$' (printf)    */
  826.                     if ((*(tmp + k) = *(t->buf + i)) == '$')
  827.                         *(tmp + ++k) = '$';
  828.                     k++;
  829.                     i++;
  830.                   }
  831.                 else
  832.                      i++;
  833.         else
  834.         {
  835.             *(tmp + k) = 0;
  836.             if(*tmp == '!')
  837.                 strcpy(tmp,t->last_input);
  838.             else
  839.                 strcpy(t->last_input,tmp);
  840.  
  841.             write_to_q(tmp, &t->input);
  842.  
  843.             if(t->snoop.snoop_by)
  844.                 {
  845.                     write_to_q("% ",&t->snoop.snoop_by->desc->output);
  846.                     write_to_q(tmp,&t->snoop.snoop_by->desc->output);
  847.                     write_to_q("\n\r",&t->snoop.snoop_by->desc->output);
  848.                 }
  849.  
  850.             if (flag)
  851.             {
  852.                 sprintf(buffer, 
  853.                     "Line too long. Truncated to:\n\r%s\n\r", tmp);
  854.                 if (write_to_descriptor(t->descriptor, buffer) < 0)
  855.                     return(-1);
  856.  
  857.                 /* skip the rest of the line */
  858.                 for (; !ISNEWL(*(t->buf + i)); i++);
  859.             }
  860.  
  861.             /* find end of entry */
  862.             for (; ISNEWL(*(t->buf + i)); i++);
  863.  
  864.             /* squelch the entry from the buffer */
  865.             for (squelch = 0;; squelch++)
  866.                 if ((*(t->buf + squelch) = 
  867.                     *(t->buf + i + squelch)) == '\0')
  868.                       break;
  869.             k = 0;
  870.             i = 0;
  871.         }
  872.     }
  873.     return(1);
  874. }
  875.  
  876.  
  877.  
  878.  
  879. void close_sockets(int s)
  880. {
  881.     log("Closing all sockets.");
  882.  
  883.     while (descriptor_list)
  884.         close_socket(descriptor_list);
  885.  
  886.     close(s);
  887. }
  888.  
  889.  
  890.  
  891.  
  892.  
  893. void close_socket(struct descriptor_data *d)
  894. {
  895.     struct affected_type *af;
  896.     struct descriptor_data *tmp;
  897.     char buf[100];
  898.  
  899.     close(d->descriptor);
  900.     flush_queues(d);
  901.     if (d->descriptor == maxdesc)
  902.         --maxdesc;
  903.  
  904.     /* Forget snooping */
  905.     if (d->snoop.snooping)
  906.         d->snoop.snooping->desc->snoop.snoop_by = 0;
  907.  
  908.     if (d->snoop.snoop_by)
  909.         {
  910.             send_to_char("Your victim is no longer among us.\n\r",d->snoop.snoop_by);
  911.             d->snoop.snoop_by->desc->snoop.snooping = 0;
  912.         }
  913.  
  914.     if (d->character)
  915.         if (d->connected == CON_PLYNG)
  916.         {
  917.             save_char(d->character, NOWHERE);
  918.             act("$n has lost $s link.", TRUE, d->character, 0, 0, TO_ROOM);
  919.             sprintf(buf, "Closing link to: %s.", GET_NAME(d->character));
  920.             log(buf);
  921.             d->character->desc = 0;
  922.         }
  923.         else
  924.         {
  925.             sprintf(buf, "Losing player: %s.", GET_NAME(d->character));
  926.             log(buf);
  927.  
  928.             free_char(d->character);
  929.         }
  930.     else
  931.         log("Losing descriptor without char.");
  932.         
  933.  
  934.     if (next_to_process == d)        /* to avoid crashing the process loop */
  935.         next_to_process = next_to_process->next;   
  936.  
  937.     if (d == descriptor_list) /* this is the head of the list */
  938.         descriptor_list = descriptor_list->next;
  939.     else  /* This is somewhere inside the list */
  940.     {
  941.         /* Locate the previous element */
  942.         for (tmp = descriptor_list; (tmp->next != d) && tmp; 
  943.             tmp = tmp->next);
  944.         
  945.         tmp->next = d->next;
  946.     }
  947.     if (d->showstr_head)
  948.         free(d->showstr_head);
  949.     free(d);
  950. }
  951.  
  952.  
  953.  
  954.  
  955.  
  956. void nonblock(int s)
  957. {
  958.     if (fcntl(s, F_SETFL, O_NDELAY) == -1)
  959.     {
  960.         perror("Noblock");
  961.         exit(1);
  962.     }
  963. }
  964.  
  965.  
  966.  
  967.  
  968. #define COMA_SIGN \
  969. "\n\r\
  970. DikuMUD is currently inactive due to excessive load on the host machine.\n\r\
  971. Please try again later.\n\r\n
  972. \n\r\
  973.    Sadly,\n\r\
  974. \n\r\
  975.     the DikuMUD system operators\n\r\n\r"
  976.  
  977.  
  978. /* sleep while the load is too high */
  979. void coma(int s)
  980. {
  981.     fd_set input_set;
  982.     static struct timeval timeout =
  983.     {
  984.         60, 
  985.         0
  986.     };
  987.     int conn;
  988.  
  989.     int workhours(void);
  990.     int load(void);
  991.  
  992.     log("Entering comatose state.");
  993.  
  994.     sigsetmask(sigmask(SIGUSR1) | sigmask(SIGUSR2) | sigmask(SIGINT) |
  995.         sigmask(SIGPIPE) | sigmask(SIGALRM) | sigmask(SIGTERM) |
  996.         sigmask(SIGURG) | sigmask(SIGXCPU) | sigmask(SIGHUP));
  997.  
  998.  
  999.     while (descriptor_list)
  1000.         close_socket(descriptor_list);
  1001.  
  1002.     FD_ZERO(&input_set);
  1003.     do
  1004.     {
  1005.         FD_SET(s, &input_set);
  1006.         if (select(64, &input_set, 0, 0, &timeout) < 0)
  1007.         {
  1008.             perror("coma select");
  1009.             exit(1);
  1010.         }
  1011.         if (FD_ISSET(s, &input_set))
  1012.         {
  1013.             if (load() < 6)
  1014.             {
  1015.                 log("Leaving coma with visitor.");
  1016.                 sigsetmask(0);
  1017.                 return;
  1018.             }
  1019.             if ((conn = new_connection(s)) >= 0)
  1020.             {
  1021.                 write_to_descriptor(conn, COMA_SIGN);
  1022.                 sleep(2);
  1023.                 close(conn);
  1024.             }
  1025.         }            
  1026.  
  1027.         tics = 1;
  1028.         if (workhours())
  1029.         {
  1030.             log("Working hours collision during coma. Exit.");
  1031.             exit(0);
  1032.         }
  1033.     }
  1034.     while (load() >= 6);
  1035.  
  1036.     log("Leaving coma.");
  1037.     sigsetmask(0);
  1038. }
  1039.  
  1040.  
  1041.  
  1042. /* ****************************************************************
  1043. *    Public routines for system-to-player-communication                *
  1044. **************************************************************** */
  1045.  
  1046.  
  1047.  
  1048. void send_to_char(char *messg, struct char_data *ch)
  1049. {
  1050.         
  1051.     if (ch->desc && messg)
  1052.         write_to_q(messg, &ch->desc->output);
  1053. }
  1054.  
  1055.  
  1056.  
  1057.  
  1058. void send_to_all(char *messg)
  1059. {
  1060.     struct descriptor_data *i;
  1061.  
  1062.     if (messg)
  1063.         for (i = descriptor_list; i; i = i->next)
  1064.             if (!i->connected)
  1065.                 write_to_q(messg, &i->output);
  1066. }
  1067.  
  1068.  
  1069. void send_to_outdoor(char *messg)
  1070. {
  1071.     struct descriptor_data *i;
  1072.  
  1073.     if (messg)
  1074.         for (i = descriptor_list; i; i = i->next)
  1075.             if (!i->connected)
  1076.                 if (OUTSIDE(i->character))
  1077.                     write_to_q(messg, &i->output);
  1078. }
  1079.  
  1080.  
  1081. void send_to_except(char *messg, struct char_data *ch)
  1082. {
  1083.     struct descriptor_data *i;
  1084.  
  1085.     if (messg)
  1086.         for (i = descriptor_list; i; i = i->next)
  1087.             if (ch->desc != i && !i->connected)
  1088.                 write_to_q(messg, &i->output);
  1089. }
  1090.  
  1091.  
  1092.  
  1093. void send_to_room(char *messg, int room)
  1094. {
  1095.     struct char_data *i;
  1096.  
  1097.     if (messg)
  1098.         for (i = world[room].people; i; i = i->next_in_room)
  1099.             if (i->desc)
  1100.                 write_to_q(messg, &i->desc->output);
  1101. }
  1102.  
  1103.  
  1104.  
  1105.  
  1106. void send_to_room_except(char *messg, int room, struct char_data *ch)
  1107. {
  1108.     struct char_data *i;
  1109.  
  1110.     if (messg)
  1111.         for (i = world[room].people; i; i = i->next_in_room)
  1112.             if (i != ch && i->desc)
  1113.                 write_to_q(messg, &i->desc->output);
  1114. }
  1115.  
  1116. void send_to_room_except_two
  1117.     (char *messg, int room, struct char_data *ch1, struct char_data *ch2)
  1118. {
  1119.           struct char_data *i;
  1120.  
  1121.             if (messg)
  1122.               for (i = world[room].people; i; i = i->next_in_room)
  1123.                   if (i != ch1 && i != ch2 && i->desc)
  1124.                       write_to_q(messg, &i->desc->output);
  1125. }
  1126.  
  1127.  
  1128.  
  1129. /* higher-level communication */
  1130.  
  1131.  
  1132. void act(char *str, int hide_invisible, struct char_data *ch,
  1133.     struct obj_data *obj, void *vict_obj, int type)
  1134. {
  1135.     register char *strp, *point, *i;
  1136.     struct char_data *to;
  1137.     char buf[MAX_STRING_LENGTH];
  1138.  
  1139.     if (!str)
  1140.         return;
  1141.     if (!*str)
  1142.         return;
  1143.  
  1144.     if (type == TO_VICT)
  1145.         to = (struct char_data *) vict_obj;
  1146.     else if (type == TO_CHAR)
  1147.         to = ch;
  1148.     else
  1149.         to = world[ch->in_room].people;
  1150.  
  1151.     for (; to; to = to->next_in_room)
  1152.     {
  1153.         if (to->desc && ((to != ch) || (type == TO_CHAR)) &&  
  1154.             (CAN_SEE(to, ch) || !hide_invisible) && AWAKE(to) &&
  1155.             !((type == TO_NOTVICT) && (to == (struct char_data *) vict_obj)))
  1156.         {
  1157.             for (strp = str, point = buf;;)
  1158.                 if (*strp == '$')
  1159.                 {
  1160.                     switch (*(++strp))
  1161.                     {
  1162.                         case 'n': i = PERS(ch, to); break;
  1163.                         case 'N': i = PERS((struct char_data *) vict_obj, to); break;
  1164.                         case 'm': i = HMHR(ch); break;
  1165.                         case 'M': i = HMHR((struct char_data *) vict_obj); break;
  1166.                         case 's': i = HSHR(ch); break;
  1167.                         case 'S': i = HSHR((struct char_data *) vict_obj); break;
  1168.                         case 'e': i = HSSH(ch); break;
  1169.                         case 'E': i = HSSH((struct char_data *) vict_obj); break;
  1170.                         case 'o': i = OBJN(obj, to); break;
  1171.                         case 'O': i = OBJN((struct obj_data *) vict_obj, to); break;
  1172.                         case 'p': i = OBJS(obj, to); break;
  1173.                         case 'P': i = OBJS((struct obj_data *) vict_obj, to); break;
  1174.                         case 'a': i = SANA(obj); break;
  1175.                         case 'A': i = SANA((struct obj_data *) vict_obj); break;
  1176.                         case 'T': i = (char *) vict_obj; break;
  1177.                         case 'F': i = fname((char *) vict_obj); break;
  1178.                         case '$': i = "$"; break;
  1179.                         default:
  1180.                             log("Illegal $-code to act():");
  1181.                             log(str);
  1182.                             break;
  1183.                     }
  1184.                     while (*point = *(i++))
  1185.                         ++point;
  1186.                     ++strp;
  1187.                 }
  1188.                 else if (!(*(point++) = *(strp++)))
  1189.                     break;
  1190.  
  1191.             *(--point) = '\n';
  1192.             *(++point) = '\r';
  1193.             *(++point) = '\0';
  1194.  
  1195.             write_to_q(CAP(buf), &to->desc->output);
  1196.         }
  1197.         if ((type == TO_VICT) || (type == TO_CHAR))
  1198.             return;
  1199.     }
  1200. }
  1201.