home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / t / toaster.zip / Compat / comm1.c < prev    next >
C/C++ Source or Header  |  1992-02-26  |  43KB  |  1,786 lines

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <sys/stream.h>
  4. #include <sys/inetioctl.h>
  5. #include <sys/fcntl.h>
  6. #include <sys/inet.h>
  7. #include "inet.h"
  8. #define    TELOPTS
  9. #include "telnet.h"
  10. #ifdef hpux
  11. #include <arpa/inet.h>
  12. #include <arpa/telnet.h>
  13. #endif
  14. #include <netdb.h>
  15. #include <stdio.h>
  16. #include <errno.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <signal.h>
  20. #include <string.h>
  21. #include <memory.h>
  22. #if defined(sun) || defined(M_UNIX) || defined(NeXT)
  23. #include <fcntl.h>
  24. #endif
  25. #ifdef _AIX 
  26. #include <sys/select.h>
  27. #endif
  28. #include "config.h"
  29. #include "lint.h"
  30. #include "interpret.h"
  31. #include "comm.h"
  32. #include "object.h"
  33. #include "sent.h"
  34. #include "patchlevel.h"
  35. #include "wiz_list.h"
  36.  
  37. #ifdef MUDWHO
  38. #include "mudwho.h"
  39. #endif
  40.  
  41. #define USE_SELECT_ACCEPT
  42.  
  43. /* #define INET_NTOA_OK This is defined (if wanted) in config.h */
  44.  
  45. #ifdef MSDOS
  46. #include "msdos/pcomm.h"
  47. #endif
  48.  
  49. int socket PROT((int, int, int));
  50. #ifndef sgi
  51. #ifndef NeXT
  52. int setsockopt PROT((int, int, int, char *, int));
  53. #endif
  54. int bind PROT((int, struct sockaddr *, int));
  55. int listen PROT((int, int));
  56. int accept PROT((int, struct sockaddr *, int *));
  57. #endif
  58. int select PROT((int, fd_set *, fd_set *, fd_set *, struct timeval *));
  59. int getpeername PROT((int, struct sockaddr *, int *));
  60.  
  61. void telnet_neg PROT((char *, char *));
  62. void set_prompt PROT((char *));
  63. char *query_ip_number PROT((struct object *));
  64. static void add_ip_entry PROT((long, char *));
  65.  
  66. extern char *xalloc(), *string_copy(), *unshared_str_copy();
  67. extern int d_flag;
  68. extern int current_time;
  69. char * first_cmd_in_buf PROT((struct interactive *));
  70. void next_cmd_in_buf PROT((struct interactive *));
  71. char * skip_eols PROT((struct interactive *, char *));
  72. void remove_flush_entry PROT((struct interactive *ip));
  73.  
  74. void remove_interactive(), add_ref();
  75.  
  76. extern void debug_message(), fatal(), free_sentence();
  77.  
  78. struct interactive *all_players[MAX_PLAYERS];
  79.  
  80. extern int errno;
  81.  
  82. void new_player();
  83.  
  84. #ifdef ACCESS_RESTRICTED
  85. extern void *allow_host_access();
  86. extern void release_host_access();
  87. #else
  88. int *allow_host_access();
  89. #endif
  90.  
  91. void flush_all_player_mess();
  92.  
  93. fd_set readfds;
  94. int nfds = 0;
  95. int num_player;
  96.  
  97. FILE *f_ip_demon = NULL, *f_ip_demon_wr;
  98.  
  99. static struct object *first_player_for_flush=(struct object *)NULL;
  100.  
  101. /*
  102.  * Interprocess communication interface to the backend.
  103.  */
  104.  
  105. static int s;
  106. extern int port_number;
  107.  
  108. #ifdef COMM_STAT
  109. int add_message_calls=0;
  110. int inet_packets=0;
  111. int inet_volume=0;
  112. #endif
  113.  
  114. void prepare_ipc() {
  115. #ifndef MSDOS
  116.     struct sockaddr_in sin;
  117.     struct hostent *hp;
  118.     int tmp;
  119.     char host_name[100];
  120. #ifdef MUDWHO
  121.     char buff[100];
  122. #endif
  123.  
  124.     if (gethostname(host_name, sizeof host_name) == -1) {
  125.         perror("gethostname");
  126.     fatal("Error in gethostname()\n");
  127.     }
  128.     hp = gethostbyname(host_name);
  129.     if (hp == 0) {
  130.     (void)fprintf(stderr, "gethostbyname: unknown host.\n");
  131.     exit(1);
  132.     }
  133.     memset((char *)&sin, '\0', sizeof sin);
  134.     memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
  135.     sin.sin_port = htons((u_short)port_number);
  136.     sin.sin_family = hp->h_addrtype;
  137.     sin.sin_addr.s_addr = INADDR_ANY;
  138.     s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  139.     if (s == -1) {
  140.     perror("socket");
  141.     abort();
  142.     }
  143.     tmp = 1;
  144.     if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR,
  145.             (char *) &tmp, sizeof (tmp)) < 0) {
  146.     perror ("setsockopt");
  147.     exit (1);
  148.     }
  149.     if (bind(s, (struct sockaddr *)&sin, sizeof sin) == -1) {
  150.     if (errno == EADDRINUSE) {
  151.         fprintf(stderr, "Socket already bound!\n");
  152.         debug_message("Socket already bound!\n");
  153.         exit(errno);
  154.     } else {
  155.         perror("bind");
  156.         abort();
  157.     }
  158.     }
  159.     if (listen(s, 5) == -1) {
  160.     perror("listen");
  161.     abort();
  162.     }
  163.     tmp = 1;
  164. #ifndef USE_SELECT_ACCEPT
  165. #if 1
  166.     if (ioctl(s, FIONBIO, &tmp) == -1) {
  167.     perror("ioctl socket FIONBIO");
  168.     abort();
  169.     }
  170. #else
  171. #if defined(hpux) 
  172.     if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
  173.     perror("ioctl socket O_NONBLOCK");
  174.     abort();
  175.     }
  176. #else /* not sun or hpux */
  177.     if (fcntl(s, F_SETFL, FNDELAY) == -1) {
  178.     perror("ioctl socket FIONBIO");
  179.     abort();
  180.     }
  181. #endif  /* hpux */
  182. #endif /* sun */
  183. #endif /*USE_SELECT_ACCEPT*/
  184.     signal(SIGPIPE, SIG_IGN);
  185. #ifdef MUDWHO
  186.     sprintf(buff, "%s%02d-DR", GAME_VERSION, PATCH_LEVEL);
  187.     rwhocli_setup(MUDWHO_SERVER,MUDWHO_PASSWORD,MUDWHO_NAME,buff);
  188. #endif
  189. #else
  190.     c_listen();
  191. #endif
  192. }
  193.  
  194. /*
  195.  * This one is called when shutting down the MUD.
  196.  */
  197. void ipc_remove() {
  198.     (void)printf("Shutting down ipc...\n");
  199. #ifndef MSDOS
  200.     close(s);
  201. #ifdef MUDWHO
  202.     rwhocli_shutdown();
  203. #endif
  204. #else
  205.     c_shutdown();
  206. #endif
  207. }
  208.  
  209. /*
  210.  * Send a message to a player. If that player is shadowed, special
  211.  * care hs tobe taken.
  212.  */
  213. /*VARARGS1*/
  214. void add_message(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  215.     char *fmt;
  216.     int a1, a2, a3, a4, a5, a6, a7, a8, a9;
  217. {
  218.     char buff[10000];        /* Kludgy! Hope this is enough ! */
  219.     char buff2[MAX_SOCKET_PACKET_SIZE+1];
  220.     struct interactive *ip;
  221.     int n, chunk, length;
  222.     int from, to;
  223.     int min_length;
  224.     int old_message_length;
  225.  
  226.     if (command_giver == 0 || (command_giver->flags & O_DESTRUCTED) ||
  227.     command_giver->interactive == 0 ||
  228.       command_giver->interactive->do_close) {
  229.       putchar(']');
  230.     if ( fmt != MESSAGE_FLUSH )
  231.         printf(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  232.         fflush(stdout);
  233.     return;
  234.     }
  235.     ip = command_giver->interactive;
  236.     old_message_length = ip->message_length;
  237.     if ( fmt == MESSAGE_FLUSH ) {
  238.     min_length = 1;
  239.       strncpy ( buff, ip->message_buf, length=old_message_length );
  240.         buff[length] = '\0';
  241.     } else {
  242. #ifdef COMM_STAT
  243.     add_message_calls++; /* We want to know how many packets the old
  244.                 version would have sent             */
  245. #endif
  246.     min_length = DESIRED_SOCKET_PACKET_SIZE;
  247.     (void)sprintf(buff+old_message_length,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
  248.     length = old_message_length + strlen(buff+old_message_length);
  249.     /*
  250.      * Always check that your arrays are big enough ! :-)
  251.      */
  252.     if (length > sizeof buff)
  253.         fatal("To long message!\n");
  254.     if (shadow_catch_message(command_giver, buff+old_message_length))
  255.         return;
  256.     if (ip->snoop_by) {
  257.         struct object *save = command_giver;
  258.         command_giver = ip->snoop_by->ob;
  259.         add_message("%%%s", buff+old_message_length);
  260.         command_giver = save;
  261.     }
  262.     if ( length >= min_length ) {
  263.         strncpy ( buff, ip->message_buf, old_message_length );
  264.     } else {
  265.         strcpy( ip->message_buf+old_message_length,
  266.         buff+old_message_length );
  267.     }
  268.     }
  269.     if (d_flag > 1)
  270.     debug_message("[%s(%d)]: %s", command_giver->name, length, buff);
  271.     /*
  272.      * Insert CR after all NL.
  273.      */
  274.     to = 0;
  275. #ifdef PORTALS
  276.     if (ip->out_portal) {
  277.     buff2[0] = ']';
  278.     to = 1;
  279.     }
  280. #endif
  281.     for (from = 0; length-from >= min_length; to = 0 ) {
  282.     for ( ; to < (sizeof buff2)-1 && buff[from] != '\0';) {
  283.         if (buff[from] == '\n')
  284.         buff2[to++] = '\r';
  285. #if 0
  286.         if (isprint(buff[from]) || isspace(buff[from]))
  287.         buff2[to++] = buff[from++];
  288.         else
  289.         from++;
  290. #else
  291.         buff2[to++] = buff[from++];
  292. #endif
  293.     }
  294.     if ( to == sizeof(buff2) ) {
  295.         to -= 2;
  296.         from--;
  297.     }
  298.     chunk = to;
  299.     /*
  300.      * We split up the message into something smaller than the max size.
  301.      */
  302.     if ((n = write(ip->socket, buff2, chunk)) == -1) {
  303.             if (errno == EINTR) {
  304.             fprintf(stderr, "comm1: write EINTR.\n");
  305.                 if (old_message_length) remove_flush_entry(ip);
  306.                 ip->do_close = 1;
  307.                 return;
  308.         }
  309.         if (errno == EMSGSIZE) {
  310.         fprintf(stderr, "comm1: write EMSGSIZE.\n");
  311.         return;
  312.         }
  313.         if (errno == EINVAL) {
  314.         fprintf(stderr, "comm1: write EINVAL.\n");
  315.         if (old_message_length) remove_flush_entry(ip);
  316.         ip->do_close = 1;
  317.         return;
  318.         }
  319.         if (errno == ENETUNREACH) {
  320.         fprintf(stderr, "comm1: write ENETUNREACH.\n");
  321.         if (old_message_length) remove_flush_entry(ip);
  322.         ip->do_close = 1;
  323.         return;
  324.         }
  325.         if (errno == EHOSTUNREACH) {
  326.         fprintf(stderr, "comm1: write EHOSTUNREACH.\n");
  327.         if (old_message_length) remove_flush_entry(ip);
  328.         ip->do_close = 1;
  329.         return;
  330.         }
  331.         if (errno == EPIPE) {
  332.         fprintf(stderr, "comm1: write EPIPE detected\n");
  333.         if (old_message_length) remove_flush_entry(ip);
  334.         ip->do_close = 1;
  335.         return;
  336.         }
  337.         if (errno == EWOULDBLOCK) {
  338.         fprintf(stderr,
  339.               "comm1: write EWOULDBLOCK. Message discarded.\n");
  340.         if (old_message_length) remove_flush_entry(ip);
  341.         /* ip->do_close = 1; */
  342.         return;
  343.         }
  344.         fprintf(stderr, "write: unknown errno %d\n", errno);
  345.         perror("write");
  346.         if (old_message_length) remove_flush_entry(ip);
  347.         ip->do_close = 1;
  348.         return;
  349.     }
  350.  
  351. #ifdef COMM_STAT
  352.     inet_packets++;
  353.     inet_volume += n;
  354. #endif
  355.     if (n != chunk)
  356.         {
  357.         fprintf(stderr, "write socket: wrote %d, should be %d.\n",
  358.             n, chunk);
  359.             fprintf(stderr, "Closing down.");
  360.             ip->do_close = 1;
  361.         ip->silent_close = 1;
  362.         } 
  363.     continue;
  364.     }
  365.  
  366.     length -= from;
  367.     ip->message_length=length;
  368.     if (from)
  369.         strncpy( ip->message_buf, buff+from, length );
  370.     if ( length && !old_message_length ) { /* buffer became 'dirty' */
  371.     if ( ip->next_player_for_flush = first_player_for_flush ) {
  372.         first_player_for_flush->interactive->previous_player_for_flush =
  373.         command_giver;
  374.     }
  375.     ip->previous_player_for_flush = 0;
  376.     first_player_for_flush = command_giver;
  377.     }
  378.     if ( !length && old_message_length ) { /* buffer has become empty */
  379.     remove_flush_entry(ip);
  380.     }
  381. }
  382.  
  383. void remove_flush_entry(ip)
  384.     struct interactive *ip;
  385. {
  386.  
  387.     ip->message_length=0;
  388.     if ( ip->previous_player_for_flush ) {
  389.     ip->previous_player_for_flush->interactive->next_player_for_flush
  390.     = ip->next_player_for_flush;
  391.     } else {
  392.     first_player_for_flush = ip->next_player_for_flush;
  393.     }
  394.     if ( ip->next_player_for_flush ) {
  395.     ip->next_player_for_flush->interactive->previous_player_for_flush
  396.     = ip->previous_player_for_flush;
  397.     }
  398. }
  399.  
  400. void flush_all_player_mess() {
  401.     struct object *p,*np;
  402.     struct object *save = command_giver;
  403.  
  404.     for ( p = first_player_for_flush; p; p=np) {
  405.         np = p->interactive->next_player_for_flush;
  406.     /* beware of side-effects when calling add_message the first time! */
  407.     command_giver = p;
  408.     add_message(MESSAGE_FLUSH);
  409.     }
  410.     command_giver=save;
  411. }
  412.  
  413. /*
  414.  * Copy a string, replacing newlines with '\0'. Also add an extra
  415.  * space and back space for every newline. This trick will allow
  416.  * otherwise empty lines, as multiple newlines would be replaced by
  417.  * multiple zeroes only.
  418.  */
  419.  
  420. static int copy_chars(from, to, n, end)
  421.     char *from, *to;
  422.     int n;
  423.     char *end;
  424. {
  425.     int i;
  426.     char *start = to;
  427.     for (i=0; i<n && to < end; i++) {
  428.     if (from[i] == '\r' || from[i] == '\033')  /* Kill ESCs - Render 2/11*/
  429.         continue;
  430.     if (from[i] == '\n') {
  431.             if (to+3 >= end)
  432.                while (to < end) *to++ = '\0'; /* fill the remaining with 0's */
  433.             else {
  434.            *to++ = ' ';
  435.            *to++ = '\b';
  436.            *to++ = '\0';
  437.             }
  438.         continue;
  439.     }
  440.     *to++ = from[i];
  441.     }
  442.     return to - start;
  443. }
  444.  
  445. /*
  446.  * Get a message from any player.  For all players without a completed
  447.  * cmd in their input buffer, read their socket.  Then, return the first
  448.  * cmd of the next player in sequence that has a complete cmd in their buffer.
  449.  * CmdsGiven is used to allow people in ED to send more cmds (if they have
  450.  * them queued up) than normal players.  If we get a heartbeat, still read
  451.  * all sockets; if the next cmd giver is -1, we have already cycled and
  452.  * can go back to do the heart beat.
  453.  */
  454.  
  455. #define    StartCmdGiver    (MAX_PLAYERS-1) /* the one after heartbeat */
  456. #define IncCmdGiver    NextCmdGiver = (NextCmdGiver < 0? StartCmdGiver: \
  457.                     NextCmdGiver - 1)
  458.  
  459. int NextCmdGiver = StartCmdGiver;
  460. int CmdsGiven = 0;     /* -1 is used to poll heart beat. */
  461. int twait = 0;         /* wait time for select() */
  462. extern int time_to_call_heart_beat, comm_time_to_call_heart_beat;
  463. #ifndef FD_SET
  464. #define FD_ZERO(x) (((x)->fds_bits[0]=0),((x)->fds_bits[1]=0));
  465. #define FD_SET(x,y) (((y)->fds_bits[0])|=(1<<(x)))
  466. #define FD_ISSET(x,y) (((y)->fds_bits[0])&(1<<(x)))
  467. #endif
  468. int get_message(buff, size)
  469.     char *buff[];
  470.     int size;
  471. {
  472.     int i, res;
  473.     struct interactive * ip = 0;
  474.     char *p;
  475.  
  476.     /*
  477.      * Stay in this loop until we have a message from a player.
  478.      */
  479.     while(1) {
  480.     int new_socket;
  481.     struct sockaddr_in addr;
  482.     struct timeval timeout;
  483.     int length;
  484.  
  485.     /* First, try to get a new player... */
  486. #if defined(USE_SELECT_ACCEPT) || defined(HPUX_BEFORE_SEVEN)
  487.     fd_set x;
  488.  
  489.     FD_ZERO(&x);
  490.     FD_SET(s,&x);
  491.     timeout.tv_sec=0;
  492.     timeout.tv_usec=0;
  493.     if((select(s+1,&x,0,0,&timeout)>=0) && FD_ISSET(s,&x)) {
  494.       length = sizeof addr;
  495.       new_socket = accept(s, (struct sockaddr *)&addr, &length);
  496.       if (new_socket != -1)
  497.         new_player(new_socket, /* &addr, */ length);
  498.       else if (new_socket == -1 && errno != EWOULDBLOCK &&
  499.            errno != EAGAIN && errno != EINTR) {
  500.         perror("accept");
  501.         abort();
  502.       }
  503.     }
  504. #else
  505.     length = sizeof addr;
  506.     new_socket = accept(s, (struct sockaddr *)&addr, &length);
  507.     if (new_socket != -1)
  508.         new_player(new_socket, /* &addr, */ length);
  509.     else if (new_socket == -1 && errno != EWOULDBLOCK &&
  510.         errno != EAGAIN && errno != EINTR) {
  511.         perror("accept");
  512.         abort();
  513.     }
  514. #endif
  515.  
  516.     nfds = 0;
  517.     FD_ZERO(&readfds);
  518.     for (i=0; i<MAX_PLAYERS; i++) {
  519.         ip = all_players[i];
  520.         if (!ip)
  521.         continue;
  522.         if (ip->do_close) {
  523.         ip->do_close = 0;
  524.         remove_interactive(ip->ob);
  525.         continue;
  526.         }
  527.         if (!first_cmd_in_buf(ip)) {
  528.         FD_SET(ip->socket, &readfds);
  529.         if (ip->socket >= nfds)
  530.             nfds = ip->socket+1;
  531. #ifdef PORTALS
  532.         if (ip->out_portal) {
  533.             FD_SET(ip->portal_socket, &readfds);
  534.             if (ip->portal_socket >= nfds)
  535.             nfds = ip->portal_socket + 1;
  536.         }
  537. #endif /* PORTALS */
  538.         }
  539.     }
  540.     if (f_ip_demon != NULL) {
  541.         FD_SET(fileno(f_ip_demon), &readfds);
  542.     }
  543.     timeout.tv_sec = twait; /* avoid busy waiting when no buffered cmds */
  544.     timeout.tv_usec = 0;
  545.     res = select(nfds, &readfds, 0, 0, &timeout);
  546. #ifdef MSDOS
  547.     if (timer_expired()) {
  548.         twait = 0;
  549.         goto return_next_command;
  550.     }
  551. #endif
  552.     if (res == -1) {
  553.         twait = 0;
  554.         if (errno == EINTR) /* if we got an alarm, finish the round */
  555.         goto return_next_command;
  556.         perror("select");
  557.         return 0;
  558.     }
  559.     if (res) { /* waiting packets */
  560.         if (f_ip_demon != NULL && FD_ISSET(fileno(f_ip_demon), &readfds)) {
  561.         char buf[200], *p, *q;
  562.         long laddr;
  563.                 buf[0] = '\0';
  564.         if (fgets(buf, sizeof buf, f_ip_demon)) {
  565. /*printf("hname says: %s\n", buf);*/
  566.             laddr=inet_addr(buf);
  567.             if (laddr != -1) {
  568.             p = strchr(buf, ' ');
  569.             if (p) {
  570.                 p++;
  571.                 q = strchr(buf, '\n');
  572.                 if (q) {
  573.                 *q = 0;
  574.                 add_ip_entry(laddr, p);
  575.                 }
  576.             }
  577.             }
  578.         }
  579.         }
  580.         for (i=0; i<MAX_PLAYERS; i++) { /* read all pending sockets */
  581.         ip = all_players[i];
  582.         if (ip == 0)
  583.             continue;
  584.         if (FD_ISSET(ip->socket, &readfds)) { /* read this player */
  585.             int l;
  586.  
  587.             /* dont overfill their buffer */
  588.             l = MAX_TEXT - ip->text_end - 1;
  589.             if (l < size)
  590.             size = l;
  591.  
  592.             if ((l = read(ip->socket, buff, size)) == -1) {
  593.             if (errno == ENETUNREACH) {
  594.                 debug_message("Net unreachable detected.\n");
  595.                 remove_interactive(ip->ob);
  596.                 continue;
  597.             }
  598.             if (errno == EHOSTUNREACH) {
  599.                 debug_message("Host unreachable detected.\n");
  600.                 remove_interactive(ip->ob);
  601.                 continue;
  602.             }
  603.             if (errno == ETIMEDOUT) {
  604.                 debug_message("Connection timed out detected.\n");
  605.                 remove_interactive(ip->ob);
  606.                 continue;
  607.             }
  608.             if (errno == ECONNRESET) {
  609.                 debug_message("Connection reset by peer detected.\n");
  610.                 remove_interactive(ip->ob);
  611.                 continue;
  612.             }
  613.             if (errno == EWOULDBLOCK) {
  614.                 debug_message("read would block socket %d!\n",
  615.                       ip->socket);
  616.                 remove_interactive(ip->ob);
  617.                 continue;
  618.             }
  619.             if (errno == EMSGSIZE) {
  620.                 debug_message("read EMSGSIZE !\n");
  621.                 continue;
  622.             }
  623.             perror("read");
  624.             debug_message("Unknown errno %d\n", errno);
  625.             remove_interactive(ip->ob);
  626.             continue;
  627.             }
  628. #ifdef PORTALS
  629.             /*
  630.              * IF the data goes through a portal, send it,
  631.              * but don't return any data.
  632.              */
  633.             if (ip->out_portal) {
  634.             if (ip->text_end) { /* pending text first */
  635.                 write(ip->portal_socket, ip->text, ip->text_end);
  636.                 ip->text_end = 0;
  637.             }
  638.             if (l)
  639.                 write(ip->portal_socket, buff, l);
  640.             continue;
  641.             }
  642. #endif /* PORTALS */
  643.             if (l == 0) {
  644.             if (ip->closing)
  645.                 fatal("Tried to read from closing socket.\n");
  646.             remove_interactive(ip->ob);
  647.             return 0;
  648.             }
  649.             buff[l] = '\0';
  650.             /* replace newlines by nulls and catenate to buffer */
  651.             ip->text_end +=
  652.             copy_chars(buff, ip->text + ip->text_end, l,
  653.                                    ip->text + MAX_TEXT);
  654. #if 0
  655.             for (x=0; x<l; x++) {
  656.             if (buff[x] == '\n' || buff[x] == '\r')
  657.                 buff[x] = '\0';
  658.             }
  659.             memcpy(ip->text+ip->text_end, buff, l+1);
  660.             ip->text_end += l;
  661. #endif
  662.             /* now, text->end is just after the last char read.  If last */
  663.             /* char was a nl, char *before* text_end will be null. */
  664.             ip->text[ip->text_end] = '\0';
  665.         }
  666.         }
  667.     }
  668.     /*
  669.      * we have read the sockets; now find and return a command
  670.      */
  671.     return_next_command:
  672.     twait = 0;
  673.     ip = 0;
  674.     for (i = 0; i < MAX_PLAYERS + 1; i++) {
  675.         if (NextCmdGiver == -1) { /* we have cycled around all players */
  676.         CmdsGiven = 0;      /* check heart beat */
  677.         IncCmdGiver;
  678.         if (comm_time_to_call_heart_beat) {
  679.             time_to_call_heart_beat = 1; /* twait stays 0! */
  680.             return 0;
  681.         }
  682.         }
  683.         ip = all_players[NextCmdGiver];
  684.         if (ip && (p = first_cmd_in_buf(ip))) /* wont respond to partials */
  685.         break;
  686.         CmdsGiven = 0; /* new player, no cmds issued */
  687.         IncCmdGiver;
  688.     }
  689.     
  690.     if ((!ip)||!p) { /* no cmds found; loop and select (on timeout) again */
  691.         if (comm_time_to_call_heart_beat) { /* may as well do it now */
  692.         time_to_call_heart_beat = 1; /* no cmds, do heart beat */
  693.         NextCmdGiver = StartCmdGiver;/* do a complete poll next time */
  694.         CmdsGiven = 0;
  695.         return(0);
  696.         }
  697.         /* no heart beat to do and no cmds pending - avoid busy wait on select */
  698.         twait = 1;
  699.         continue; /* else await another cmd */
  700.     }
  701.     
  702.     /*
  703.      * we have a player cmd - return it.  If he is in ed, count his
  704.      * cmds, else only allow 1 cmd.  If he has only one partially
  705.      * completed cmd left after * this, move it to the start of his
  706.      * buffer; new stuff will be appended.
  707.      */
  708.     
  709.     command_giver = ip->ob;
  710.     telnet_neg(buff, p);
  711.     next_cmd_in_buf(ip); /* move on buffer pointers */
  712.     
  713.     /* if he is not in ed, dont let him issue another till the poll comes again */
  714.     
  715.     if (ip->ed_buffer && CmdsGiven < ALLOWED_ED_CMDS)
  716.         CmdsGiven++;
  717.     else {
  718.         IncCmdGiver;
  719.         CmdsGiven = 0;
  720.     }
  721.     
  722.     /* manage snooping - should the snooper see type ahead?  Well, he doesn't here
  723.      */
  724.     if (ip->snoop_by && !ip->noecho) {
  725.         command_giver = ip->snoop_by->ob;
  726.         add_message("%% %s\n", buff);
  727.     }
  728.     command_giver = ip->ob;
  729.     if (ip->noecho) {
  730.         /* Must not enable echo before the user input is received. */
  731.         add_message("%c%c%c", IAC, WONT, TELOPT_ECHO);
  732.     }
  733.     ip->noecho = 0;
  734.     ip->last_time = current_time;
  735.     return 1;
  736.     }
  737. }
  738.  
  739. /*
  740.  * find the first character of the next complete cmd in a buffer, 0 if no
  741.  * completed cmd.  There is a completed cmd if there is a null between
  742.  * text_start and text_end.  Zero length commands are discarded (as occur
  743.  * between <cr> and <lf>).  Update text_start if we have to skip leading
  744.  * nulls.
  745.  */
  746.  
  747. char * first_cmd_in_buf(ip) 
  748. struct interactive *ip;
  749. {
  750.     char * p, *q;
  751.  
  752.     p = ip->text_start + ip->text;
  753.  
  754.     while ((p < (ip->text_end + ip->text)) && !*p) /* skip null input */
  755.     p++;
  756.  
  757.     ip->text_start = p - ip->text;
  758.  
  759.     if (ip->text_start >= ip->text_end) {
  760.     ip->text_start = ip->text_end = 0;
  761.     ip->text[0] = '\0';
  762.     return(0);
  763.     }
  764.  
  765.     while ((p < (ip->text_end + ip->text)) && *p) /* find end of cmd */
  766.     p++;
  767.  
  768.     if (p < ip->text + ip->text_end) /* null terminated, was command */
  769.     return(ip->text + ip->text_start);
  770.  
  771. /* have a partial command at end of buffer; move it to start, return null */
  772. /* if it can't move down, truncate it and return it as cmd. */
  773.     
  774.     p = ip->text + ip->text_start;
  775.     q = ip->text;
  776.     while (p < (ip->text + ip->text_end))
  777.     *(q++) = *(p++);
  778.  
  779.     ip->text_end -= ip->text_start;
  780.     ip->text_start = 0;
  781.     if (ip->text_end > MAX_TEXT - 2) {
  782.     ip->text[ip->text_end-2] = '\0'; /* nulls to truncate */
  783.     ip->text[ip->text_end-1] = '\0'; /* nulls to truncate */
  784.     ip->text_end--;
  785.     return(ip->text);
  786.     }
  787. /* buffer not full and no newline - no cmd. */
  788.     return(0);
  789. }
  790.  
  791. /*
  792.  * move pointers to next cmd, or clear buf.
  793.  */
  794.  
  795. void next_cmd_in_buf(ip)
  796. struct interactive *ip;
  797. {
  798.     char * p = ip->text + ip->text_start;
  799.     while (*p && p < ip->text + ip->text_end)
  800.     p++;
  801.     /* skip past any nulls at the end */
  802.     while (!*p && p < ip->text + ip->text_end)
  803.     p++;
  804.     if (p < ip->text + ip->text_end)
  805.     ip->text_start = p - ip->text;
  806.     else {
  807.     ip->text_start = ip->text_end = 0;
  808.     ip->text[0] = '\0';
  809.     }
  810. }
  811.     
  812. /*
  813.  * Cause a player to go net-dead
  814.  */
  815. void remove_interactive_player(ob)
  816.    struct object *ob;
  817. {
  818.    ob->interactive->do_close = 1;
  819.  
  820. /*
  821.  * Remove an interactive player immediately.
  822.  */
  823. void remove_interactive(ob)
  824.     struct object *ob;
  825. {
  826.     struct object *save = command_giver;
  827.     int i;
  828.  
  829.     for (i=0; i<MAX_PLAYERS; i++) {
  830.     if (all_players[i] != ob->interactive)
  831.         continue;
  832.     if (ob->interactive->closing)
  833.         fatal("Double call to remove_interactive()\n");
  834.     ob->interactive->closing = 1;
  835.     if (ob->interactive->snoop_by) {
  836.         ob->interactive->snoop_by->snoop_on = 0;
  837.         ob->interactive->snoop_by = 0;
  838.     }
  839.     if (ob->interactive->snoop_on) {
  840.         ob->interactive->snoop_on->snoop_by = 0;
  841.         ob->interactive->snoop_on = 0;
  842.     }
  843.     command_giver = ob;
  844.     if (!ob->interactive->silent_close)
  845.        add_message("Closing down.\n");
  846.         if (ob->interactive->ed_buffer)
  847.         {
  848.            extern void save_ed_buffer();
  849.            save_ed_buffer();
  850.     }
  851.      add_message(MESSAGE_FLUSH);
  852. #if 0
  853.         if (ob->interactive->next_player_for_flush)
  854.             ob->interactive->next_player_for_flush->interactive->
  855.           previous_player_for_flush = 
  856.                 ob->interactive->previous_player_for_flush;
  857.         if (ob->interactive->previous_player_for_flush)
  858.             ob->interactive->previous_player_for_flush->interactive->
  859.           next_player_for_flush = 
  860.                 ob->interactive->next_player_for_flush;
  861.         if (ob == first_player_for_flush)
  862.             first_player_for_flush = ob->interactive->next_player_for_flush;
  863. #endif
  864.     (void)shutdown(ob->interactive->socket, 2);
  865.     close(ob->interactive->socket);
  866. #ifdef ACCESS_RESTRICTED
  867.     release_host_access(ob->interactive->access_class);
  868. #endif
  869.     num_player--;
  870.     if (ob->interactive->input_to) {
  871.         free_object(ob->interactive->input_to->ob, "remove_interactive");
  872.         free_sentence(ob->interactive->input_to);
  873.         ob->interactive->input_to = 0;
  874.     }
  875.     free((char *)ob->interactive);
  876.     ob->interactive = 0;
  877.         {
  878.            int j;
  879.            for (j=i; j<MAX_PLAYERS-1; ++j)
  880.               all_players[j] = all_players[j+1];
  881.            all_players[j] = 0;
  882.         } 
  883.     free_object(ob, "remove_interactive");
  884.     command_giver = save;
  885.     return;
  886.     }
  887.     (void)fprintf(stderr, "Could not find and remove player %s\n", ob->name);
  888.     abort();
  889. }
  890.  
  891. #ifndef MSDOS
  892. #ifndef ACCESS_RESTRICTED 
  893.  
  894. int
  895. allow_host_access(new_socket)
  896.     int new_socket;
  897. {
  898.     struct sockaddr_in apa;
  899.     int len = sizeof apa;
  900.     char * ipname, *calloc(), *xalloc();
  901. #ifndef hpux
  902.     char *index PROT((char *, int));
  903. #endif
  904.     static int read_access_list = 0;
  905.     static struct access_list {
  906.     int addr_len;
  907.     char * addr, *name, *comment;
  908.     struct access_list * next;
  909.     } * access_list;
  910.     register struct access_list * ap;
  911.  
  912.     if(!read_access_list) {
  913.     FILE * f = fopen("ACCESS.DENY", "r");
  914.     char buf[1024], ipn[50], hname[100], comment[1024], *p1, *p2;
  915.     struct access_list * na;
  916.     struct hostent * hent;
  917.  
  918.     read_access_list = 1;
  919.     if(f) {
  920.         while(fgets(buf, sizeof buf - 1, f)) {
  921.         if(*buf != '#') {
  922.             ipn[0] = hname[0] = comment[0] = 0;
  923.             if(p1 = index(buf, ':')) *p1 = 0;
  924.             if(buf[0] && buf[0] != '\n')
  925.             strncpy(ipn, buf, sizeof ipn - 1);
  926.             if((p2 = p1) && *++p2) {
  927.             if(p1 = index(p2, ':')) *p1 = 0;
  928.             if(p2[0] && p2[0] != '\n')
  929.                 strcpy(hname, p2);
  930.             if(p1 && p1[1] && p1[1] != '\n')
  931.                 strcpy(comment, p1+1);
  932.             }
  933.             
  934.             if(!(na = (struct access_list *)xalloc(sizeof na[0]))) {
  935.             fatal("Out of mem.\n");
  936.             }
  937.             na->addr = na->name = na->comment = 0;
  938.             na->next = 0;
  939.             if(*ipn && (!(na->addr = xalloc(strlen(ipn) + 1)) ||
  940.                 !strcpy(na->addr, ipn)))
  941.             fatal("Out of mem.\n");
  942.             if(*hname && (!(na->name = xalloc(strlen(hname) + 1)) ||
  943.                   !strcpy(na->name, hname)))
  944.             fatal("Out of mem.\n");
  945.             if(*comment && (!(na->comment=xalloc(strlen(comment)+1))||
  946.                     !strcpy(na->comment, comment)))
  947.             fatal("Out of mem.\n");
  948.  
  949.             if((!(int)*ipn)
  950.             &&
  951.             ((!*hname)
  952.               || (!(hent = gethostbyname(hname))) ||
  953.                  (!(na->addr =
  954.                    xalloc(hent->h_length+1)))||
  955.                  !strcpy(na->addr,
  956.                     inet_ntoa(*(struct in_addr *)hent->h_addr)))) {
  957.             if(na->name) free(na->name);
  958.             if(na->comment) free(na->comment);
  959.             free((char *)na);
  960.             continue;
  961.             }
  962.             if(!(na->addr_len = strlen(na->addr)))
  963.             continue;
  964.  
  965.             /* printf("disabling: %s:%s:%s\n", na->addr,
  966.                na->name?na->name:"no name",
  967.                na->comment?na->comment:"no comment");  */
  968.  
  969.             na->next = access_list;
  970.             access_list = na;
  971.         }
  972.         }
  973.         fclose(f);
  974.     }
  975.     }
  976.     
  977.     if (!access_list)
  978.     return 0;
  979.     
  980.     if(getpeername(new_socket, (struct sockaddr *)&apa, &len) == -1) {
  981.     close(new_socket);
  982.     perror("getpeername");
  983.     return -1;
  984.     }
  985.  
  986.     ipname = inet_ntoa(apa.sin_addr);
  987.     
  988.     for(ap = access_list; ap; ap = ap->next)
  989.     if(!strncmp(ipname, ap->addr, ap->addr_len)){
  990.         if(ap->comment) (void) write(new_socket, ap->comment,
  991.                      strlen(ap->comment));
  992.         printf("Stopping: %s:%s\n", ap->addr, ap->name?ap->name:"no name");
  993.         close(new_socket);
  994.         return -1;
  995.     }
  996.     return 0;
  997. }
  998.  
  999. #endif
  1000. #endif
  1001.  
  1002. /*
  1003.  * get the I'th player object from the interactive list, i starts at 0
  1004.  * and can go to num_player - 1.  For users(), etc.
  1005.  */
  1006. struct object * get_interactive_object(i)
  1007. int i;
  1008. {
  1009.     if (i >= num_player) /* love them ASSERTS() :-) */
  1010.     fatal("Get interactive (%d) with only %d players!", i, num_player);
  1011.     
  1012.     if (!all_players[i])
  1013.        fatal("Get interactive: player %d not found! (num_players = %d)",
  1014.         i, num_player);
  1015.     return all_players[i]->ob;
  1016.  
  1017. #if 0 
  1018.     for (n = 0; n < MAX_PLAYERS; n++)
  1019.     if (all_players[n])
  1020.         if (!(i--))
  1021.         return(all_players[n]->ob);
  1022.  
  1023.     return 0;    /* Just to satisfy some compiler warnings */
  1024. #endif
  1025. }
  1026.  
  1027. static int priv_host(addr)
  1028. int addr;
  1029. {
  1030.     int j;
  1031.     j = addr & 0xffffff00;
  1032.     return j == 0x80c21c00 || j == 0x80c23300 || j == 0x80088500 ||
  1033.            addr == 0x80c2039b;
  1034. }
  1035.  
  1036. static int get_new_mortal()
  1037. {
  1038.    int i, count, first;
  1039.  
  1040.    count = 0;
  1041.    first = -1;
  1042.    for (i=0; i<MAX_PLAYERS; ++i)
  1043.    {
  1044.       int j;
  1045.    
  1046.       if (!all_players[i])
  1047.       {
  1048.          if (first == -1) 
  1049.             first = i;
  1050.       }
  1051.       else
  1052.       {
  1053.          j = ntohl(all_players[i]->addr.sin_addr.s_addr);
  1054.          if (!priv_host(j)) count++;
  1055.       }
  1056.    }
  1057.  
  1058.    if (count < MAX_MORTALS) return first;
  1059.    else return -1;
  1060. }
  1061.  
  1062. static int get_new_priv()
  1063. {
  1064.    int i;
  1065.  
  1066.    for (i=0; i<MAX_PLAYERS; ++i)
  1067.       if (!all_players[i]) 
  1068.          return i;
  1069.  
  1070.    return -1;
  1071. }
  1072.  
  1073. static int get_new_player(priv)
  1074. int priv;
  1075. {
  1076. #ifdef MAX_MORTALS
  1077.    if (priv) return get_new_priv();
  1078.    else return get_new_mortal();
  1079. #else
  1080.    return get_new_priv();
  1081. #endif
  1082. }
  1083.  
  1084. void new_player(new_socket, /* addr, */ len)
  1085.     int new_socket;
  1086. /*
  1087.     struct sockaddr_in *addr;
  1088. */
  1089.     int len;
  1090. {
  1091.     int i;
  1092.     struct sockaddr_in fooaddr;
  1093.     int wizhost = 0;
  1094.     char *p;
  1095. #ifndef MSDOS
  1096. #ifdef ACCESS_RESTRICTED
  1097.     void *class;
  1098. #endif
  1099.  
  1100.     i = sizeof(fooaddr);
  1101.     getpeername(new_socket, (struct sockaddr *)&fooaddr, &i);
  1102.     i = ntohl(fooaddr.sin_addr.s_addr);
  1103. #ifdef MAX_MORTALS
  1104.     if (priv_host(i))
  1105.     {  
  1106.        wizhost++;
  1107.        p = "\r\n";
  1108.        write(new_socket, p, strlen(p));
  1109.     }
  1110. #endif
  1111.     
  1112. #ifdef ACCESS_RESTRICTED
  1113.     if (!(class = allow_host_access(new_socket, new_socket)))
  1114.     return;
  1115. #else
  1116.     if(allow_host_access(new_socket))
  1117.     return;
  1118. #endif
  1119. #endif
  1120.  
  1121.     if (d_flag)
  1122.     debug_message("New player at socket %d.\n", new_socket);
  1123.  
  1124.     i = get_new_player(wizhost);
  1125.  
  1126.     if (i != -1) {
  1127.     struct object *ob;
  1128.     struct svalue *ret;
  1129.     extern struct object *master_ob;
  1130.     
  1131.         assert_master_ob_loaded();
  1132.     command_giver = master_ob;
  1133.     master_ob->interactive =
  1134.         (struct interactive *)xalloc(sizeof (struct interactive));
  1135.     master_ob->flags |= O_ONCE_INTERACTIVE;
  1136.     master_ob->interactive->ob = master_ob;
  1137.     master_ob->interactive->text[0] = '\0';
  1138.     master_ob->interactive->input_to = 0;
  1139.     master_ob->interactive->closing = 0;
  1140.     master_ob->interactive->snoop_on = 0;
  1141.     master_ob->interactive->snoop_by = 0;
  1142. #ifdef PORTALS
  1143.     master_ob->interactive->out_portal = 0;
  1144.     master_ob->interactive->portal_socket = 0;
  1145.     master_ob->interactive->from_portal = 0;
  1146. #endif /* PORTALS */
  1147.     master_ob->interactive->text_end = 0;
  1148.     master_ob->interactive->text_start = 0;
  1149.     master_ob->interactive->do_close = 0;
  1150.     master_ob->interactive->silent_close = 0;
  1151.     master_ob->interactive->noecho = 0;
  1152.         master_ob->interactive->trace_level = 0;
  1153.         master_ob->interactive->trace_prefix = 0;
  1154.         master_ob->interactive->ed_buffer = 0;
  1155.         master_ob->interactive->last_time = current_time;
  1156.      master_ob->interactive->message_length = 0;
  1157. #ifdef MUDWHO
  1158.     master_ob->interactive->login_time = current_time;
  1159. #endif
  1160.     all_players[i] = master_ob->interactive;
  1161.     all_players[i]->socket = new_socket;
  1162.     set_prompt(PROMPT);
  1163.     getpeername(new_socket, (struct sockaddr *)&all_players[i]->addr,
  1164.             &len);
  1165.         
  1166. #ifdef ACCESS_RESTRICTED
  1167.     all_players[i]->access_class = class;
  1168. #endif
  1169.     num_player++;
  1170.     add_ref(master_ob, "new_player");
  1171.     ret = apply_master_ob("connect", 0);
  1172.     if (ret == 0 || ret->type != T_OBJECT) {
  1173.         remove_interactive(master_ob);
  1174.         return;
  1175.     }
  1176.     /*
  1177.      * There was an object returned from connect(). Use this as the
  1178.      * player object.
  1179.      */
  1180.     ob = ret->u.ob;
  1181.     ob->interactive = master_ob->interactive;
  1182.     ob->interactive->ob = ob;
  1183.     ob->flags |= O_ONCE_INTERACTIVE;
  1184.     master_ob->flags &= ~O_ONCE_INTERACTIVE;
  1185.     add_message(MESSAGE_FLUSH);
  1186.     master_ob->interactive = 0;
  1187.     free_object(master_ob, "reconnect");
  1188.     add_ref(ob, "new_player");
  1189.     command_giver = ob;
  1190.         if (f_ip_demon_wr != NULL) {
  1191.        fprintf(f_ip_demon_wr, "%s\n", query_ip_number(ob));
  1192.            fflush(f_ip_demon_wr);
  1193.     }
  1194.     logon(ob);
  1195.     flush_all_player_mess();
  1196.     return;
  1197.     }
  1198.     p = FULL_MESSAGE;
  1199.     write(new_socket, p, strlen(p));
  1200.     close(new_socket);
  1201. }
  1202.  
  1203. int call_function_interactive(i, str)
  1204.     struct interactive *i;
  1205.     char *str;
  1206. {
  1207.     char *function;
  1208.     struct object *ob;
  1209.  
  1210.     if (!i->input_to)
  1211.     return 0;
  1212.     /*
  1213.      * Special feature: input_to() has been called to setup
  1214.      * a call to a function.
  1215.      */
  1216.     if (i->input_to->ob->flags & O_DESTRUCTED) {
  1217.     /* Sorry, the object has selfdestructed ! */
  1218.     free_object(i->input_to->ob, "call_function_interactive");
  1219.     free_sentence(i->input_to);
  1220.     i->input_to = 0;
  1221.     return 0;
  1222.     }
  1223.     free_object(i->input_to->ob, "call_function_interactive");
  1224.     function = string_copy(command_giver->interactive->input_to->function);
  1225.     ob = i->input_to->ob;
  1226.     free_sentence(i->input_to);
  1227.     /*
  1228.      * We must clear this reference before the call to apply(), because
  1229.      * someone might want to set up a new input_to().
  1230.      */
  1231.     i->input_to = 0;
  1232.     /*
  1233.      * Now we set current_object to this object, so that input_to will
  1234.      * work for static functions.
  1235.      */
  1236.     push_constant_string(str);
  1237.     current_object = ob;
  1238.     (void)apply(function, ob, 1);
  1239.     free(function);
  1240.     flush_all_player_mess();
  1241.     return 1;
  1242. }
  1243.  
  1244. int set_call(ob, sent, noecho)
  1245.     struct object *ob;
  1246.     struct sentence *sent;
  1247.     int noecho;
  1248. {
  1249.     struct object *save = command_giver;
  1250.     if (ob == 0 || sent == 0)
  1251.     return 0;
  1252.     if (ob->interactive == 0 || ob->interactive->input_to)
  1253.     return 0;
  1254.     ob->interactive->input_to = sent;
  1255.     ob->interactive->noecho = noecho;
  1256.     command_giver = ob;
  1257.     if (noecho)
  1258.     add_message("%c%c%c", IAC, WILL, TELOPT_ECHO);
  1259.     command_giver = save;
  1260.     return 1;
  1261. }
  1262.  
  1263. void show_info_about(str, room, i)
  1264.     char *str, *room;
  1265.     struct interactive *i;
  1266. {
  1267.     struct hostent *hp = 0;
  1268.  
  1269. #if 0
  1270.     hp = gethostbyaddr(&i->addr.sin_addr.s_addr, 4, AF_INET);
  1271. #endif
  1272.     add_message("%-15s %-15s %s\n",
  1273.         hp ? hp->h_name : inet_ntoa(i->addr.sin_addr), str, room);
  1274. }
  1275.  
  1276. void remove_all_players()
  1277. {
  1278.     int i;
  1279.  
  1280.     for (i=0; i<MAX_PLAYERS; i++) {
  1281.     if (all_players[i] == 0)
  1282.         continue;
  1283.     command_giver = all_players[i]->ob;
  1284.     (void)apply("quit", all_players[i]->ob, 0);
  1285.     }
  1286. }
  1287.  
  1288. void set_prompt(str)
  1289.     char *str;
  1290. {
  1291.     command_giver->interactive->prompt = str;
  1292. }
  1293.  
  1294. /*
  1295.  * Print the prompt, but only if input_to not is disabled.
  1296.  */
  1297. void print_prompt()
  1298. {
  1299.     if (command_giver == 0)
  1300.     fatal("command_giver == 0.\n");
  1301.     if (command_giver->interactive->input_to == 0) {
  1302.     add_message(command_giver->interactive->prompt);
  1303.     if (1) { /* add test for heart_beat later */
  1304.             flush_all_player_mess();
  1305.     }
  1306.     }
  1307. }
  1308.  
  1309. /*
  1310.  * Let object 'me' snoop object 'you'. If 'you' is 0, then turn off
  1311.  * snooping.
  1312.  */
  1313. void set_snoop(me, you)
  1314.     struct object *me, *you;
  1315. {
  1316.     struct interactive *on = 0, *by = 0, *tmp;
  1317.     int i;
  1318.  
  1319.     if (me->flags & O_DESTRUCTED)
  1320.     return;
  1321.     if (you && (you->flags & O_DESTRUCTED))
  1322.     return;
  1323.     for(i=0; i<MAX_PLAYERS && (on == 0 || by == 0); i++) {
  1324.     if (all_players[i] == 0)
  1325.         continue;
  1326.     if (all_players[i]->ob == me)
  1327.         by = all_players[i];
  1328.     else if (all_players[i]->ob == you)
  1329.         on = all_players[i];
  1330.     }
  1331.     if (you == 0) {
  1332.     if (by == 0)
  1333.         error("Could not find myself to stop snoop.\n");
  1334.     add_message("Ok.\n");
  1335.     if (by->snoop_on == 0)
  1336.         return;
  1337.     by->snoop_on->snoop_by = 0;
  1338.     by->snoop_on = 0;
  1339.     return;
  1340.     }
  1341.     if (on == 0 || by == 0) {
  1342.     add_message("Failed.\n");
  1343.     return;
  1344.     }
  1345.     if (by->snoop_on) {
  1346.     by->snoop_on->snoop_by = 0;
  1347.     by->snoop_on = 0;
  1348.     }
  1349.     if (on->snoop_by) {
  1350.     add_message("Busy.\n");
  1351.     return;
  1352.     }
  1353.     /*
  1354.      * Protect against snooping loops.
  1355.      */
  1356.     for (tmp = on; tmp; tmp = tmp->snoop_on) {
  1357.     if (tmp == by) {
  1358.         add_message("Busy.\n");
  1359.         return;
  1360.     }
  1361.     }
  1362.     on->snoop_by = by;
  1363.     by->snoop_on = on;
  1364.     add_message("Ok.\n");
  1365.     return;
  1366. }
  1367.  
  1368. /*
  1369.  * Let object 'me' snoop object 'you'. If 'you' is 0, then turn off
  1370.  * snooping.
  1371.  *
  1372.  * This routine is almost identical to the old set_snoop. The main
  1373.  * difference is that the routine writes nothing to player directly,
  1374.  * all such communication is taken care of by the mudlib. It communicates
  1375.  * with master.c in order to find out if the operation is permissble or
  1376.  * not. The old routine let everyone snoop anyone. This routine also returns
  1377.  * 0 or 1 depending on success.
  1378.  */
  1379. int new_set_snoop(me, you)
  1380.     struct object *me, *you;
  1381. {
  1382.     struct interactive *on = 0, *by = 0, *tmp;
  1383.     int i;
  1384.     struct svalue *ret;
  1385.  
  1386.     /* Stop if people managed to quit before we got this far */
  1387.     if (me->flags & O_DESTRUCTED)
  1388.     return 0;
  1389.     if (you && (you->flags & O_DESTRUCTED))
  1390.     return 0;
  1391.  
  1392.     /* Find the snooper & snopee */
  1393.     for(i = 0 ; i < MAX_PLAYERS && (on == 0 || by == 0); i++) 
  1394.     {
  1395.     if (all_players[i] == 0)
  1396.         continue;
  1397.     if (all_players[i]->ob == me)
  1398.         by = all_players[i];
  1399.     else if (all_players[i]->ob == you)
  1400.         on = all_players[i];
  1401.     }
  1402.  
  1403.     /* Illegal snoop attempt by null object */
  1404.     if (!current_object->eff_user)
  1405.     return 0;
  1406.  
  1407.     /* Check for permissions with valid_snoop in master */
  1408.     push_object(me, "snoop");
  1409.     if (you == 0)
  1410.     push_number(0);
  1411.     else
  1412.     push_object(you, "snoop");
  1413.     ret = apply_master_ob("valid_snoop", 2);
  1414.  
  1415.     if (!ret || ret->type != T_NUMBER || ret->u.number == 0)
  1416.     return 0;
  1417.  
  1418.     /* Stop snoop */
  1419.     if (you == 0) 
  1420.     {
  1421.     if (by == 0)
  1422.         error("Could not find snooper to stop snoop on.\n");
  1423.     if (by->snoop_on == 0)
  1424.         return 1;
  1425.     by->snoop_on->snoop_by = 0;
  1426.     by->snoop_on = 0;
  1427.     return 1;
  1428.     }
  1429.  
  1430.     /* Strange event, but possible, so test for it */
  1431.     if (on == 0 || by == 0)
  1432.     return 0;
  1433.  
  1434.     /* Protect against snooping loops */
  1435.     for (tmp = on; tmp; tmp = tmp->snoop_on) 
  1436.     {
  1437.     if (tmp == by) 
  1438.         return 0;
  1439.     }
  1440.  
  1441.     /* Terminate previous snoop, if any */
  1442.     if (by->snoop_on) 
  1443.     {
  1444.     by->snoop_on->snoop_by = 0;
  1445.     by->snoop_on = 0;
  1446.     }
  1447.     if (on->snoop_by)
  1448.     {
  1449.     on->snoop_by->snoop_on = 0;
  1450.     on->snoop_by = 0;
  1451.     }
  1452.  
  1453.     on->snoop_by = by;
  1454.     by->snoop_on = on;
  1455.     return 1;
  1456.     
  1457. }
  1458.  
  1459. #define    TS_DATA        0
  1460. #define    TS_IAC        1
  1461. #define    TS_WILL        2
  1462. #define    TS_WONT        3
  1463. #define    TS_DO        4
  1464. #define    TS_DONT        5
  1465.  
  1466. void telnet_neg(to, from)
  1467.     char *to, *from;
  1468. {
  1469.     int state = TS_DATA;
  1470.     int ch;
  1471.     char *first = to;
  1472.  
  1473.     while(1) {
  1474.     ch = (*from++ & 0xff);
  1475.     switch(state) {
  1476.     case TS_DATA:
  1477.         switch(ch) {
  1478.         case IAC:
  1479.         state = TS_IAC;
  1480.         continue;
  1481.         case '\b':    /* Backspace */
  1482.         case 0x7f:    /* Delete */
  1483.         if (to <= first)
  1484.             continue;
  1485.         to -= 1;
  1486.         continue;
  1487.         default:
  1488.         if (ch & 0x80) {
  1489.             if (d_flag) debug_message("Tel_neg: 0x%x\n", ch);
  1490.             continue;
  1491.         }
  1492.         *to++ = ch;
  1493.         if (ch == 0)
  1494.             return;
  1495.         continue;
  1496.         }
  1497.     case TS_IAC:
  1498.         switch(ch) {
  1499.         case WILL:
  1500.         state = TS_WILL;
  1501.         continue;
  1502.         case WONT:
  1503.         state = TS_WONT;
  1504.         continue;
  1505.         case DO:
  1506.         state = TS_DO;
  1507.         continue;
  1508.         case DONT:
  1509.         state = TS_DONT;
  1510.         continue;
  1511.         case DM:
  1512.         break;
  1513.         case NOP:
  1514.         case GA:
  1515.         default:
  1516.         break;
  1517.         }
  1518.         state = TS_DATA;
  1519.         continue;
  1520.     case TS_WILL:
  1521.         if (d_flag) debug_message("Will %s\n", telopts[ch]);
  1522.         state = TS_DATA;
  1523.         continue;
  1524.     case TS_WONT:
  1525.         if (d_flag) debug_message("Wont %s\n", telopts[ch]);
  1526.         state = TS_DATA;
  1527.         continue;
  1528.     case TS_DO:
  1529.         if (d_flag) debug_message("Do %s\n", telopts[ch]);
  1530.         state = TS_DATA;
  1531.         continue;
  1532.     case TS_DONT:
  1533.         if (d_flag) debug_message("Dont %s\n", telopts[ch]);
  1534.         state = TS_DATA;
  1535.         continue;
  1536.     default:
  1537.         if (d_flag) debug_message("Bad state: 0x%x\n", state);
  1538.         state = TS_DATA;
  1539.         continue;
  1540.     }
  1541.     }
  1542. }
  1543.  
  1544. #define IPSIZE 200
  1545. static struct ipentry {
  1546.     long addr;
  1547.     char *name;
  1548. } iptable[IPSIZE];
  1549. static int ipcur;
  1550.  
  1551. char *query_ip_name(ob)
  1552.     struct object *ob;
  1553. {
  1554.     int i;
  1555.  
  1556.     if (ob == 0)
  1557.     ob = command_giver;
  1558.     if (!ob || ob->interactive == 0)
  1559.     return 0;
  1560.     for(i = 0; i < IPSIZE; i++) {
  1561.     if (iptable[i].addr == ob->interactive->addr.sin_addr.s_addr &&
  1562.         iptable[i].name)
  1563.         return iptable[i].name;
  1564.     }
  1565.     return inet_ntoa(ob->interactive->addr.sin_addr);
  1566. }
  1567.  
  1568. static void add_ip_entry(addr, name)
  1569. long addr;
  1570. char *name;
  1571. {
  1572.     int i;
  1573.  
  1574.     for(i = 0; i < IPSIZE; i++) {
  1575.     if (iptable[i].addr == addr)
  1576.         return;
  1577.     }
  1578.     iptable[ipcur].addr = addr;
  1579.     if (iptable[ipcur].name)
  1580.     free_string(iptable[ipcur].name);
  1581.     iptable[ipcur].name = make_shared_string(name);
  1582.     ipcur = (ipcur+1) % IPSIZE;
  1583. }
  1584.  
  1585. char *query_ip_number(ob)
  1586.     struct object *ob;
  1587. {
  1588.     if (ob == 0)
  1589.     ob = command_giver;
  1590.     if (!ob || ob->interactive == 0)
  1591.     return 0;
  1592.     return inet_ntoa(ob->interactive->addr.sin_addr);
  1593. }
  1594.  
  1595. #ifndef INET_NTOA_OK
  1596. /*
  1597. Note: if the address string is "a.b.c.d" the address number is
  1598.       a * 256^3 + b * 256^2 + c * 256 + d
  1599.  
  1600. */
  1601.  
  1602. #if !defined(hpux) && !defined(NeXT)
  1603. char *inet_ntoa(ad)
  1604.     struct in_addr ad;
  1605. {
  1606.     u_long s_ad;
  1607.     int a, b, c, d;
  1608.     static char addr[20]; /* 16 + 1 should be enough */
  1609.  
  1610.     s_ad = ad.s_addr;
  1611.     d = s_ad % 256;
  1612.     s_ad /= 256;
  1613.     c = s_ad % 256;
  1614.     s_ad /= 256;
  1615.     b = s_ad % 256;
  1616.     a = s_ad / 256;
  1617.     sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
  1618.     return addr;
  1619. }
  1620. #endif /* !NeXT && !hpux */
  1621. #endif /* INET_NTOA_OK */
  1622.  
  1623. char *query_host_name() {
  1624.     static char name[20];
  1625.     
  1626.     gethostname(name, sizeof name);
  1627.     name[sizeof name - 1] = '\0';    /* Just to make sure */
  1628.     return name;
  1629. }
  1630.  
  1631. struct object *query_snoop(ob)
  1632.     struct object *ob;
  1633. {
  1634.     if (ob->interactive->snoop_by == 0)
  1635.     return 0;
  1636.     return ob->interactive->snoop_by->ob;
  1637. }
  1638.  
  1639. int query_idle(ob)
  1640.     struct object *ob;
  1641. {
  1642.     if (!ob->interactive)
  1643.     error("query_idle() of non-interactive object.\n");
  1644.     return current_time - ob->interactive->last_time;
  1645. }
  1646.  
  1647. void notify_no_command() {
  1648.     char *p,*m;
  1649.  
  1650.     if (!command_giver) return;
  1651.     p = command_giver->default_err_message;
  1652.     if (!p) p = make_shared_string("What?\n");
  1653.     m = process_string(p);
  1654.     if (!shadow_catch_message(command_giver, m))
  1655.     {
  1656.        if((command_giver->flags&O_ENABLE_COMMANDS)&&!command_giver->interactive)
  1657.           tell_npc(command_giver, m);
  1658.        else
  1659.           add_message(m);
  1660.        command_giver->default_err_message = 0;
  1661.     }
  1662.     if (m != p) 
  1663.     free(m);
  1664.     free_string(p);
  1665. }
  1666.  
  1667. void clear_notify() {
  1668.     if (command_giver->default_err_message) {
  1669.     free_string(command_giver->default_err_message);
  1670.     command_giver->default_err_message = 0;
  1671.     }
  1672. }
  1673.  
  1674. void set_notify_fail_message(str)
  1675.     char *str;
  1676. {
  1677.     clear_notify();
  1678.     if (!command_giver)
  1679.     return;
  1680.     if (command_giver->default_err_message)
  1681.     free_string(command_giver->default_err_message);
  1682.     command_giver->default_err_message = make_shared_string(str);
  1683. }
  1684.  
  1685. int replace_interactive(ob, obfrom, /*IGN*/name)
  1686.     struct object *ob;
  1687.     struct object *obfrom;
  1688.     char *name;
  1689. {
  1690.     /* marion
  1691.      * i see no reason why to restrict this, besides - the length
  1692.      * (was) missing to strncmp()
  1693.      * JnA: There is EVERY reason to restrict this!!
  1694.      *      Otherwise I can write my own player object without any security
  1695.      *      at all!
  1696.      */
  1697.     struct svalue *v;
  1698.  
  1699.     push_string(name, STRING_CONSTANT);
  1700.     v = apply_master_ob("valid_exec", 1);
  1701.     if (!v || v->type != T_NUMBER || v->u.number == 0)
  1702.         return 0;
  1703.     
  1704.     if (ob->interactive)
  1705.         remove_interactive(ob);
  1706.     if (!obfrom->interactive)
  1707.     error("Bad argument2 to exec()\n");
  1708.     if (obfrom->interactive->message_length) {
  1709.         struct object *save;
  1710.         save=command_giver;
  1711.         command_giver=obfrom;
  1712.         add_message(MESSAGE_FLUSH);
  1713.     command_giver=save;
  1714.     }
  1715.     ob->interactive = obfrom->interactive;
  1716.     obfrom->interactive = 0;
  1717.     ob->interactive->ob = ob;
  1718.     ob->flags |= O_ONCE_INTERACTIVE;
  1719.     obfrom->flags &= ~O_ONCE_INTERACTIVE;
  1720.     add_ref(ob, "exec");
  1721.     free_object(obfrom, "exec");
  1722.     if (obfrom == command_giver) command_giver = ob;
  1723.     return 1;
  1724. }
  1725.  
  1726. #ifdef DEBUG
  1727. /*
  1728.  * This is used for debugging reference counts.
  1729.  */
  1730.  
  1731. void update_ref_counts_for_players() {
  1732.     int i;
  1733.  
  1734.     for (i=0; i<MAX_PLAYERS; i++) {
  1735.     if (all_players[i] == 0)
  1736.         continue;
  1737.     all_players[i]->ob->extra_ref++;
  1738.     if (all_players[i]->input_to)
  1739.         all_players[i]->input_to->ob->extra_ref++;
  1740.     }
  1741. }
  1742. #endif /* DEBUG */
  1743.  
  1744. #ifdef MUDWHO
  1745.  
  1746. char mudwhoid[200];
  1747.  
  1748. sendmudwhoinfo()
  1749. {
  1750.     struct object *ob;
  1751.     int i;
  1752.     static int last_called_time;
  1753.  
  1754.     if (current_time - last_called_time < MUDWHO_REFRESH_TIME)
  1755.     return;
  1756.  
  1757.     last_called_time = get_current_time();
  1758.  
  1759.     rwhocli_pingalive();
  1760.  
  1761.     for (i = 0; i < num_player; i++) {
  1762.     ob = get_interactive_object(i);
  1763.     if (ob->living_name)
  1764.     {
  1765.         sscanf(ob->name,"%*[^#]#%s",mudwhoid);
  1766.         strcat(mudwhoid,"@");
  1767.         strcat(mudwhoid,MUDWHO_NAME);
  1768.         rwhocli_userlogin(mudwhoid,ob->living_name,
  1769.         ob->interactive->login_time);
  1770.     }
  1771.     }
  1772. }
  1773. sendmudwhologout(ob)
  1774. struct object *ob;
  1775. {
  1776.     if (ob->interactive)
  1777.     {
  1778.         sscanf(ob->name,"%*[^#]#%s",mudwhoid);
  1779.         strcat(mudwhoid,"@");
  1780.         strcat(mudwhoid,MUDWHO_NAME);
  1781.         rwhocli_userlogout(mudwhoid);
  1782.     }
  1783. }
  1784. #endif
  1785.