COMM.C
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:51k
源码类别:

Internet/网络编程

开发平台:

WINDOWS

  1. /***************************************************************************
  2.  *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
  3.  *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
  4.  *                                                                         *
  5.  *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
  6.  *  Chastain, Michael Quan, and Mitchell Tse.                              *
  7.  *                                                                         *
  8.  *  In order to use any part of this Merc Diku Mud, you must comply with   *
  9.  *  both the original Diku license in 'license.doc' as well the Merc       *
  10.  *  license in 'license.txt'.  In particular, you may not remove either of *
  11.  *  these copyright notices.                                               *
  12.  *                                                                         *
  13.  *  Thanks to abaddon for proof-reading our comm.c and pointing out bugs.  *
  14.  *  Any remaining bugs are, of course, our work, not his.  :)              *
  15.  *                                                                         *
  16.  *  Much time and thought has gone into this software and you are          *
  17.  *  benefitting.  We hope that you share your changes too.  What goes      *
  18.  *  around, comes around.                                                  *
  19.  ***************************************************************************/
  20. /*
  21.  * This file contains all of the OS-dependent stuff:
  22.  *   startup, signals, BSD sockets for tcp/ip, i/o, timing.
  23.  *
  24.  * The data flow for input is:
  25.  *    Game_loop ---> Read_from_descriptor ---> Read
  26.  *    Game_loop ---> Read_from_buffer
  27.  *
  28.  * The data flow for output is:
  29.  *    Game_loop ---> Process_Output ---> Write_to_descriptor -> Write
  30.  *
  31.  * The OS-dependent functions are Read_from_descriptor and Write_to_descriptor.
  32.  * -- Furey  26 Jan 1993
  33.  */
  34. #if defined(macintosh)
  35. #include <types.h>
  36. #else
  37. #include <sys/types.h>
  38. #ifndef WIN32s
  39. #include <sys/time.h>
  40. #endif // @@@
  41. #endif
  42. #include <ctype.h>
  43. #include <errno.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <time.h>
  48. #include "merc.h"
  49. /*
  50.  * Malloc debugging stuff.
  51.  */
  52. #if defined(sun)
  53. #undef MALLOC_DEBUG
  54. #endif
  55. #if defined(MALLOC_DEBUG)
  56. #include <malloc.h>
  57. extern int malloc_debug args( ( int  ) );
  58. extern int malloc_verify args( ( void ) );
  59. #endif
  60. /*
  61.  * Signal handling.
  62.  * Apollo has a problem with __attribute(atomic) in signal.h,
  63.  *   I dance around it.
  64.  */
  65. #if defined(apollo)
  66. #define __attribute(x)
  67. #endif
  68. #if defined(unix)
  69. #include <signal.h>
  70. #endif
  71. #if defined(apollo)
  72. #undef __attribute
  73. #endif
  74. /*
  75.  * Socket and TCP/IP stuff.
  76.  */
  77. #if defined(macintosh) || defined(MSDOS)
  78. const char echo_off_str [] = { '' };
  79. const char echo_on_str [] = { '' };
  80. const char  go_ahead_str [] = { '' };
  81. #endif
  82. #if defined(unix)
  83. #include <fcntl.h>
  84. #ifndef WIN32s // @@@
  85. #include <netdb.h>
  86. #include <netinet/in.h>
  87. #include <sys/socket.h>
  88. #include <arpa/telnet.h>
  89. const char echo_off_str [] = { IAC, WILL, TELOPT_ECHO, '' };
  90. const char echo_on_str [] = { IAC, WONT, TELOPT_ECHO, '' };
  91. const char  go_ahead_str [] = { IAC, GA, '' };
  92. #endif
  93. #endif
  94. /*
  95.  * OS-dependent declarations.
  96.  */
  97. #if defined(_AIX)
  98. #include <sys/select.h>
  99. int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
  100. int bind args( ( int s, struct sockaddr *name, int namelen ) );
  101. void bzero args( ( char *b, int length ) );
  102. int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
  103. int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
  104. int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
  105. int listen args( ( int s, int backlog ) );
  106. int setsockopt args( ( int s, int level, int optname, void *optval,
  107.     int optlen ) );
  108. int socket args( ( int domain, int type, int protocol ) );
  109. #endif
  110. #if defined(apollo)
  111. #include <unistd.h>
  112. void bzero args( ( char *b, int length ) );
  113. #endif
  114. #if defined(__hpux)
  115. int accept args( ( int s, void *addr, int *addrlen ) );
  116. int bind args( ( int s, const void *addr, int addrlen ) );
  117. void bzero args( ( char *b, int length ) );
  118. int getpeername args( ( int s, void *addr, int *addrlen ) );
  119. int getsockname args( ( int s, void *name, int *addrlen ) );
  120. int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
  121. int listen args( ( int s, int backlog ) );
  122. int setsockopt args( ( int s, int level, int optname,
  123.   const void *optval, int optlen ) );
  124. int socket args( ( int domain, int type, int protocol ) );
  125. #endif
  126. #if     defined(interactive)
  127. #include <net/errno.h>
  128. #include <sys/fcntl.h>
  129. #endif
  130. #if defined(linux)
  131. int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
  132. int bind args( ( int s, struct sockaddr *name, int namelen ) );
  133. int close args( ( int fd ) );
  134. int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
  135. int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
  136. int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
  137. int listen args( ( int s, int backlog ) );
  138. int read args( ( int fd, char *buf, int nbyte ) );
  139. int select args( ( int width, fd_set *readfds, fd_set *writefds,
  140.     fd_set *exceptfds, struct timeval *timeout ) );
  141. int socket args( ( int domain, int type, int protocol ) );
  142. int write args( ( int fd, char *buf, int nbyte ) );
  143. #endif
  144. #if defined(macintosh)
  145. #include <console.h>
  146. #include <fcntl.h>
  147. #include <unix.h>
  148. struct timeval
  149. {
  150. time_t tv_sec;
  151. time_t tv_usec;
  152. };
  153. #if !defined(isascii)
  154. #define isascii(c) ( (c) < 0200 )
  155. #endif
  156. static long theKeys [4];
  157. int gettimeofday args( ( struct timeval *tp, void *tzp ) );
  158. #endif
  159. #if defined(MIPS_OS)
  160. extern int errno;
  161. #endif
  162. #if defined(MSDOS)
  163. int gettimeofday args( ( struct timeval *tp, void *tzp ) );
  164. int kbhit args( ( void ) );
  165. #endif
  166. #if defined(WIN32s)
  167. int gettimeofday args( ( struct timeval *tp, void *tzp ) );
  168. #endif
  169. #if defined(NeXT)
  170. int close args( ( int fd ) );
  171. int fcntl args( ( int fd, int cmd, int arg ) );
  172. #if !defined(htons)
  173. u_short htons args( ( u_short hostshort ) );
  174. #endif
  175. #if !defined(ntohl)
  176. u_long ntohl args( ( u_long hostlong ) );
  177. #endif
  178. int read args( ( int fd, char *buf, int nbyte ) );
  179. int select args( ( int width, fd_set *readfds, fd_set *writefds,
  180.     fd_set *exceptfds, struct timeval *timeout ) );
  181. int write args( ( int fd, char *buf, int nbyte ) );
  182. #endif
  183. #if defined(sequent)
  184. int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
  185. int bind args( ( int s, struct sockaddr *name, int namelen ) );
  186. int close args( ( int fd ) );
  187. int fcntl args( ( int fd, int cmd, int arg ) );
  188. int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
  189. int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
  190. int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
  191. #if !defined(htons)
  192. u_short htons args( ( u_short hostshort ) );
  193. #endif
  194. int listen args( ( int s, int backlog ) );
  195. #if !defined(ntohl)
  196. u_long ntohl args( ( u_long hostlong ) );
  197. #endif
  198. int read args( ( int fd, char *buf, int nbyte ) );
  199. int select args( ( int width, fd_set *readfds, fd_set *writefds,
  200.     fd_set *exceptfds, struct timeval *timeout ) );
  201. int setsockopt args( ( int s, int level, int optname, caddr_t optval,
  202.     int optlen ) );
  203. int socket args( ( int domain, int type, int protocol ) );
  204. int write args( ( int fd, char *buf, int nbyte ) );
  205. #endif
  206. /*
  207.  * This includes Solaris SYSV as well
  208.  */
  209. #if defined(sun)
  210. int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
  211. int bind args( ( int s, struct sockaddr *name, int namelen ) );
  212. void bzero args( ( char *b, int length ) );
  213. int close args( ( int fd ) );
  214. int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
  215. int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
  216. int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
  217. int listen args( ( int s, int backlog ) );
  218. int read args( ( int fd, char *buf, int nbyte ) );
  219. int select args( ( int width, fd_set *readfds, fd_set *writefds,
  220.     fd_set *exceptfds, struct timeval *timeout ) );
  221. #if defined(SYSV)
  222. int     setsockopt      args( ( int s, int level, int optname,
  223.     const char *optval, int optlen ) );
  224. #else
  225. int setsockopt args( ( int s, int level, int optname, void *optval,
  226.     int optlen ) );
  227. #endif
  228. int socket args( ( int domain, int type, int protocol ) );
  229. int write args( ( int fd, char *buf, int nbyte ) );
  230. #endif
  231. #if defined(ultrix)
  232. int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
  233. int bind args( ( int s, struct sockaddr *name, int namelen ) );
  234. void bzero args( ( char *b, int length ) );
  235. int close args( ( int fd ) );
  236. int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
  237. int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
  238. int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
  239. int listen args( ( int s, int backlog ) );
  240. int read args( ( int fd, char *buf, int nbyte ) );
  241. int select args( ( int width, fd_set *readfds, fd_set *writefds,
  242.     fd_set *exceptfds, struct timeval *timeout ) );
  243. int setsockopt args( ( int s, int level, int optname, void *optval,
  244.     int optlen ) );
  245. int socket args( ( int domain, int type, int protocol ) );
  246. int write args( ( int fd, char *buf, int nbyte ) );
  247. #endif
  248. /*
  249.  * Global variables.
  250.  */
  251. DESCRIPTOR_DATA *   descriptor_free; /* Free list for descriptors */
  252. DESCRIPTOR_DATA *   descriptor_list; /* All open descriptors */
  253. DESCRIPTOR_DATA *   d_next; /* Next descriptor in loop */
  254. FILE *     fpReserve; /* Reserved file handle */
  255. bool     god; /* All new chars are gods! */
  256. bool     merc_down; /* Shutdown */
  257. bool     wizlock; /* Game is wizlocked */
  258. char     str_boot_time[MAX_INPUT_LENGTH];
  259. time_t     current_time; /* Time of this pulse */
  260. /*
  261.  * OS-dependent local functions.
  262.  */
  263. #if defined(macintosh) || defined(MSDOS)
  264. void game_loop_mac_msdos args( ( void ) );
  265. bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) );
  266. bool write_to_descriptor args( ( int desc, char *txt, int length ) );
  267. #endif
  268. #if defined(unix)
  269. void game_loop_unix args( ( int control ) );
  270. int init_socket args( ( int port ) );
  271. void new_descriptor args( ( int control ) );
  272. bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) );
  273. bool write_to_descriptor args( ( int desc, char *txt, int length ) );
  274. #endif
  275. /*
  276.  * Other local functions (OS-independent).
  277.  */
  278. bool check_parse_name args( ( char *name ) );
  279. bool check_reconnect args( ( DESCRIPTOR_DATA *d, char *name,
  280.     bool fConn ) );
  281. bool check_playing args( ( DESCRIPTOR_DATA *d, char *name ) );
  282. int main args( ( int argc, char **argv ) );
  283. void nanny args( ( DESCRIPTOR_DATA *d, char *argument ) );
  284. bool process_output args( ( DESCRIPTOR_DATA *d, bool fPrompt ) );
  285. void read_from_buffer args( ( DESCRIPTOR_DATA *d ) );
  286. void stop_idling args( ( CHAR_DATA *ch ) );
  287. void    bust_a_prompt           args( ( CHAR_DATA *ch ) );
  288. #ifdef WIN32s
  289. #include <winsock.h>
  290. int close(SOCKET s) { return closesocket(s); }
  291. #endif
  292. int main( int argc, char **argv )
  293. {
  294.     struct timeval now_time;
  295.     int port;
  296. #if defined(unix)
  297.     int control;
  298. #endif
  299.     /*
  300.      * Memory debugging if needed.
  301.      */
  302. #if defined(MALLOC_DEBUG)
  303.     malloc_debug( 2 );
  304. #endif
  305.     /*
  306.      * Init time.
  307.      */
  308.     gettimeofday( &now_time, NULL );
  309.     current_time = (time_t) now_time.tv_sec;
  310.     strcpy( str_boot_time, ctime( &current_time ) );
  311.     /*
  312.      * Macintosh console initialization.
  313.      */
  314. #if defined(macintosh)
  315.     console_options.nrows = 31;
  316.     cshow( stdout );
  317.     csetmode( C_RAW, stdin );
  318.     cecho2file( "log file", 1, stderr );
  319. #endif
  320.     /*
  321.      * Reserve one channel for our use.
  322.      */
  323.     if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
  324.     {
  325. perror( NULL_FILE );
  326. exit( 1 );
  327.     }
  328.     /*
  329.      * Get the port number.
  330.      */
  331.     port = 1234;
  332.     if ( argc > 1 )
  333.     {
  334. if ( !is_number( argv[1] ) )
  335. {
  336.     fprintf( stderr, "Usage: %s [port #]n", argv[0] );
  337.     exit( 1 );
  338. }
  339. else if ( ( port = atoi( argv[1] ) ) <= 1024 )
  340. {
  341.     fprintf( stderr, "Port number must be above 1024.n" );
  342.     exit( 1 );
  343. }
  344.     }
  345.     /*
  346.      * Run the game.
  347.      */
  348. #if defined(macintosh) || defined(MSDOS)
  349.     boot_db( );
  350.     log_string( "Merc is ready to rock." );
  351.     game_loop_mac_msdos( );
  352. #endif
  353. #if defined(unix)
  354.     control = init_socket( port );
  355.     boot_db( );
  356.     sprintf( log_buf, "Merc is ready to rock on port %d.", port );
  357.     log_string( log_buf );
  358.     game_loop_unix( control );
  359.     close( control );
  360. #endif
  361.     /*
  362.      * That's all, folks.
  363.      */
  364.     log_string( "Normal termination of game." );
  365.     exit( 0 );
  366.     return 0;
  367. }
  368. #if defined(unix)
  369. int init_socket( int port )
  370. {
  371.     static struct sockaddr_in sa_zero;
  372.     struct sockaddr_in sa;
  373.     int x = 1; 
  374.     int fd;
  375.     if ( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
  376.     {
  377. perror( "Init_socket: socket" );
  378. exit( 1 );
  379.     }
  380.     if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
  381.     (char *) &x, sizeof(x) ) < 0 )
  382.     {
  383. perror( "Init_socket: SO_REUSEADDR" );
  384. close( fd );
  385. exit( 1 );
  386.     }
  387. #if defined(SO_DONTLINGER) && !defined(SYSV)
  388.     {
  389. struct linger ld;
  390. ld.l_onoff  = 1;
  391. ld.l_linger = 1000;
  392. if ( setsockopt( fd, SOL_SOCKET, SO_DONTLINGER,
  393. (char *) &ld, sizeof(ld) ) < 0 )
  394. {
  395.     perror( "Init_socket: SO_DONTLINGER" );
  396.     close( fd );
  397.     exit( 1 );
  398. }
  399.     }
  400. #endif
  401.     sa     = sa_zero;
  402.     sa.sin_family   = AF_INET;
  403.     sa.sin_port     = htons( port );
  404.     if ( bind( fd, (struct sockaddr *) &sa, sizeof(sa) ) < 0 )
  405.     {
  406. perror( "Init_socket: bind" );
  407. close( fd );
  408. exit( 1 );
  409.     }
  410.     if ( listen( fd, 3 ) < 0 )
  411.     {
  412. perror( "Init_socket: listen" );
  413. close( fd );
  414. exit( 1 );
  415.     }
  416.     return fd;
  417. }
  418. #endif
  419. #if defined(macintosh) || defined(MSDOS)
  420. void game_loop_mac_msdos( void )
  421. {
  422.     struct timeval last_time;
  423.     struct timeval now_time;
  424.     static DESCRIPTOR_DATA dcon;
  425.     gettimeofday( &last_time, NULL );
  426.     current_time = (time_t) last_time.tv_sec;
  427.     /*
  428.      * New_descriptor analogue.
  429.      */
  430.     dcon.descriptor = 0;
  431.     dcon.connected = CON_GET_NAME;
  432.     dcon.host = str_dup( "localhost" );
  433.     dcon.outsize = 2000;
  434.     dcon.outbuf = alloc_mem( dcon.outsize );
  435.     dcon.next = descriptor_list;
  436.     descriptor_list = &dcon;
  437.     /*
  438.      * Send the greeting.
  439.      */
  440.     {
  441. extern char * help_greeting;
  442. if ( help_greeting[0] == '.' )
  443.     write_to_buffer( &dcon, help_greeting+1, 0 );
  444. else
  445.     write_to_buffer( &dcon, help_greeting  , 0 );
  446.     }
  447.     /* Main loop */
  448.     while ( !merc_down )
  449.     {
  450. DESCRIPTOR_DATA *d;
  451. /*
  452.  * Process input.
  453.  */
  454. for ( d = descriptor_list; d != NULL; d = d_next )
  455. {
  456.     d_next = d->next;
  457.     d->fcommand = FALSE;
  458. #if defined(MSDOS)
  459.     if ( kbhit( ) )
  460. #endif
  461.     {
  462. if ( d->character != NULL )
  463.     d->character->timer = 0;
  464. if ( !read_from_descriptor( d ) )
  465. {
  466.     if ( d->character != NULL )
  467. save_char_obj( d->character );
  468.     d->outtop = 0;
  469.     close_socket( d );
  470.     continue;
  471. }
  472.     }
  473.     if ( d->character != NULL && d->character->wait > 0 )
  474.     {
  475. --d->character->wait;
  476. continue;
  477.     }
  478.     read_from_buffer( d );
  479.     if ( d->incomm[0] != '' )
  480.     {
  481. d->fcommand = TRUE;
  482. stop_idling( d->character );
  483. if ( d->connected == CON_PLAYING )
  484.     if ( d->showstr_point )
  485.         show_string( d, d->incomm );
  486.     else
  487.         interpret( d->character, d->incomm );
  488. else
  489.     nanny( d, d->incomm );
  490. d->incomm[0] = '';
  491.     }
  492. }
  493. /*
  494.  * Autonomous game motion.
  495.  */
  496. update_handler( );
  497. /*
  498.  * Output.
  499.  */
  500. for ( d = descriptor_list; d != NULL; d = d_next )
  501. {
  502.     d_next = d->next;
  503.     if ( ( d->fcommand || d->outtop > 0 ) )
  504.     {
  505. if ( !process_output( d, TRUE ) )
  506. {
  507.     if ( d->character != NULL )
  508. save_char_obj( d->character );
  509.     d->outtop = 0;
  510.     close_socket( d );
  511. }
  512.     }
  513. }
  514. /*
  515.  * Synchronize to a clock.
  516.  * Busy wait (blargh).
  517.  */
  518. now_time = last_time;
  519. for ( ; ; )
  520. {
  521.     int delta;
  522. #if defined(MSDOS)
  523.     if ( kbhit( ) )
  524. #endif
  525.     {
  526. if ( dcon.character != NULL )
  527.     dcon.character->timer = 0;
  528. if ( !read_from_descriptor( &dcon ) )
  529. {
  530.     if ( dcon.character != NULL )
  531. save_char_obj( d->character );
  532.     dcon.outtop = 0;
  533.     close_socket( &dcon );
  534. }
  535. #if defined(MSDOS)
  536. break;
  537. #endif
  538.     }
  539.     gettimeofday( &now_time, NULL );
  540.     delta = ( now_time.tv_sec  - last_time.tv_sec  ) * 1000 * 1000
  541.   + ( now_time.tv_usec - last_time.tv_usec );
  542.     if ( delta >= 1000000 / PULSE_PER_SECOND )
  543. break;
  544. }
  545. last_time    = now_time;
  546. current_time = (time_t) last_time.tv_sec;
  547.     }
  548.     return;
  549. }
  550. #endif
  551. #if defined(unix)
  552. void game_loop_unix( int control )
  553. {
  554.     static struct timeval null_time;
  555.     struct timeval last_time;
  556. #ifndef WIN32s
  557.     signal( SIGPIPE, SIG_IGN );
  558. #endif
  559.     gettimeofday( &last_time, NULL );
  560.     current_time = (time_t) last_time.tv_sec;
  561.     /* Main loop */
  562.     while ( !merc_down )
  563.     {
  564. fd_set in_set;
  565. fd_set out_set;
  566. fd_set exc_set;
  567. DESCRIPTOR_DATA *d;
  568. int maxdesc;
  569. #if defined(MALLOC_DEBUG)
  570. if ( malloc_verify( ) != 1 )
  571.     abort( );
  572. #endif
  573. /*
  574.  * Poll all active descriptors.
  575.  */
  576. FD_ZERO( &in_set  );
  577. FD_ZERO( &out_set );
  578. FD_ZERO( &exc_set );
  579. FD_SET( control, &in_set );
  580. maxdesc = control;
  581. for ( d = descriptor_list; d; d = d->next )
  582. {
  583.     maxdesc = UMAX( maxdesc, d->descriptor );
  584.     FD_SET( d->descriptor, &in_set  );
  585.     FD_SET( d->descriptor, &out_set );
  586.     FD_SET( d->descriptor, &exc_set );
  587. }
  588. if ( select( maxdesc+1, &in_set, &out_set, &exc_set, &null_time ) < 0 )
  589. {
  590.     perror( "Game_loop: select: poll" );
  591.     exit( 1 );
  592. }
  593. /*
  594.  * New connection?
  595.  */
  596. if ( FD_ISSET( control, &in_set ) )
  597.     new_descriptor( control );
  598. /*
  599.  * Kick out the freaky folks.
  600.  */
  601. for ( d = descriptor_list; d != NULL; d = d_next )
  602. {
  603.     d_next = d->next;   
  604.     if ( FD_ISSET( d->descriptor, &exc_set ) )
  605.     {
  606. FD_CLR( d->descriptor, &in_set  );
  607. FD_CLR( d->descriptor, &out_set );
  608. if ( d->character )
  609.     save_char_obj( d->character );
  610. d->outtop = 0;
  611. close_socket( d );
  612.     }
  613. }
  614. /*
  615.  * Process input.
  616.  */
  617. for ( d = descriptor_list; d != NULL; d = d_next )
  618. {
  619.     d_next = d->next;
  620.     d->fcommand = FALSE;
  621.     if ( FD_ISSET( d->descriptor, &in_set ) )
  622.     {
  623. if ( d->character != NULL )
  624.     d->character->timer = 0;
  625. if ( !read_from_descriptor( d ) )
  626. {
  627.     FD_CLR( d->descriptor, &out_set );
  628.     if ( d->character != NULL )
  629. save_char_obj( d->character );
  630.     d->outtop = 0;
  631.     close_socket( d );
  632.     continue;
  633. }
  634.     }
  635.     if ( d->character != NULL && d->character->wait > 0 )
  636.     {
  637. --d->character->wait;
  638. continue;
  639.     }
  640.     read_from_buffer( d );
  641.     if ( d->incomm[0] != '' )
  642.     {
  643. d->fcommand = TRUE;
  644. stop_idling( d->character );
  645. if ( d->connected == CON_PLAYING )
  646.     if ( d->showstr_point )
  647.         show_string( d, d->incomm );
  648.     else
  649.         interpret( d->character, d->incomm );
  650. else
  651.     nanny( d, d->incomm );
  652. d->incomm[0] = '';
  653.     }
  654. }
  655. /*
  656.  * Autonomous game motion.
  657.  */
  658. update_handler( );
  659. /*
  660.  * Output.
  661.  */
  662. for ( d = descriptor_list; d != NULL; d = d_next )
  663. {
  664.     d_next = d->next;
  665.     if ( ( d->fcommand || d->outtop > 0 )
  666.     &&   FD_ISSET(d->descriptor, &out_set) )
  667.     {
  668. if ( !process_output( d, TRUE ) )
  669. {
  670.     if ( d->character != NULL )
  671. save_char_obj( d->character );
  672.     d->outtop = 0;
  673.     close_socket( d );
  674. }
  675.     }
  676. }
  677. /*
  678.  * Synchronize to a clock.
  679.  * Sleep( last_time + 1/PULSE_PER_SECOND - now ).
  680.  * Careful here of signed versus unsigned arithmetic.
  681.  */
  682. {
  683.     struct timeval now_time;
  684.     long secDelta;
  685.     long usecDelta;
  686.     gettimeofday( &now_time, NULL );
  687.     usecDelta = ((int) last_time.tv_usec) - ((int) now_time.tv_usec)
  688. + 1000000 / PULSE_PER_SECOND;
  689.     secDelta = ((int) last_time.tv_sec ) - ((int) now_time.tv_sec );
  690.     while ( usecDelta < 0 )
  691.     {
  692. usecDelta += 1000000;
  693. secDelta  -= 1;
  694.     }
  695.     while ( usecDelta >= 1000000 )
  696.     {
  697. usecDelta -= 1000000;
  698. secDelta  += 1;
  699.     }
  700.     if ( secDelta > 0 || ( secDelta == 0 && usecDelta > 0 ) )
  701.     {
  702. struct timeval stall_time;
  703. stall_time.tv_usec = usecDelta;
  704. stall_time.tv_sec  = secDelta;
  705. if ( select( 0, NULL, NULL, NULL, &stall_time ) < 0 )
  706. {
  707.     perror( "Game_loop: select: stall" );
  708.     exit( 1 );
  709. }
  710.     }
  711. }
  712. gettimeofday( &last_time, NULL );
  713. current_time = (time_t) last_time.tv_sec;
  714.     }
  715.     return;
  716. }
  717. #endif
  718. #if defined(unix)
  719. void new_descriptor( int control )
  720. {
  721.     static DESCRIPTOR_DATA d_zero;
  722.     char buf[MAX_STRING_LENGTH];
  723.     DESCRIPTOR_DATA *dnew;
  724.     BAN_DATA *pban;
  725.     struct sockaddr_in sock;
  726.     struct hostent *from;
  727.     int desc;
  728.     int size;
  729.     size = sizeof(sock);
  730.     getsockname( control, (struct sockaddr *) &sock, &size );
  731.     if ( ( desc = accept( control, (struct sockaddr *) &sock, &size) ) < 0 )
  732.     {
  733. perror( "New_descriptor: accept" );
  734. return;
  735.     }
  736. #if !defined(FNDELAY)
  737. #define FNDELAY O_NDELAY
  738. #endif
  739. #ifndef WIN32s
  740.     if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 )
  741.     {
  742. perror( "New_descriptor: fcntl: FNDELAY" );
  743. return;
  744.     }
  745. #endif
  746.     /*
  747.      * Cons a new descriptor.
  748.      */
  749.     if ( descriptor_free == NULL )
  750.     {
  751. dnew = alloc_perm( sizeof(*dnew) );
  752.     }
  753.     else
  754.     {
  755. dnew = descriptor_free;
  756. descriptor_free = descriptor_free->next;
  757.     }
  758.     *dnew = d_zero;
  759.     dnew->descriptor = desc;
  760.     dnew->connected = CON_GET_NAME;
  761.     dnew->showstr_head  = NULL;
  762.     dnew->showstr_point = NULL;
  763.     dnew->outsize = 2000;
  764.     dnew->outbuf = alloc_mem( dnew->outsize );
  765.     size = sizeof(sock);
  766.     if ( getpeername( desc, (struct sockaddr *) &sock, &size ) < 0 )
  767.     {
  768. perror( "New_descriptor: getpeername" );
  769. dnew->host = str_dup( "(unknown)" );
  770.     }
  771.     else
  772.     {
  773. /*
  774.  * Would be nice to use inet_ntoa here but it takes a struct arg,
  775.  * which ain't very compatible between gcc and system libraries.
  776.  */
  777. int addr;
  778. addr = ntohl( sock.sin_addr.s_addr );
  779. sprintf( buf, "%d.%d.%d.%d",
  780.     ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
  781.     ( addr >>  8 ) & 0xFF, ( addr       ) & 0xFF
  782.     );
  783. sprintf( log_buf, "Sock.sinaddr:  %s", buf );
  784. log_string( log_buf );
  785. from = gethostbyaddr( (char *) &sock.sin_addr,
  786.     sizeof(sock.sin_addr), AF_INET );
  787. dnew->host = str_dup( from ? from->h_name : buf );
  788.     }
  789.     /*
  790.      * Swiftest: I added the following to ban sites.  I don't
  791.      * endorse banning of sites, but Copper has few descriptors now
  792.      * and some people from certain sites keep abusing access by
  793.      * using automated 'autodialers' and leaving connections hanging.
  794.      *
  795.      * Furey: added suffix check by request of Nickel of HiddenWorlds.
  796.      */
  797.     for ( pban = ban_list; pban != NULL; pban = pban->next )
  798.     {
  799. if ( str_suffix( pban->name, dnew->host ) )
  800. {
  801.     write_to_descriptor( desc,
  802. "Your site has been banned from this Mud.nr", 0 );
  803.     close( desc );
  804.     free_string( dnew->host );
  805.     free_mem( dnew->outbuf, dnew->outsize );
  806.     dnew->next = descriptor_free;
  807.     descriptor_free = dnew;
  808.     return;
  809. }
  810.     }
  811.     /*
  812.      * Init descriptor data.
  813.      */
  814.     dnew->next = descriptor_list;
  815.     descriptor_list = dnew;
  816.     /*
  817.      * Send the greeting.
  818.      */
  819.     {
  820. extern char * help_greeting;
  821. if ( help_greeting[0] == '.' )
  822.     write_to_buffer( dnew, help_greeting+1, 0 );
  823. else
  824.     write_to_buffer( dnew, help_greeting  , 0 );
  825.     }
  826.     return;
  827. }
  828. #endif
  829. void close_socket( DESCRIPTOR_DATA *dclose )
  830. {
  831.     CHAR_DATA *ch;
  832.     if ( dclose->outtop > 0 )
  833. process_output( dclose, FALSE );
  834.     if ( dclose->snoop_by != NULL )
  835.     {
  836. write_to_buffer( dclose->snoop_by,
  837.     "Your victim has left the game.nr", 0 );
  838.     }
  839.     {
  840. DESCRIPTOR_DATA *d;
  841. for ( d = descriptor_list; d != NULL; d = d->next )
  842. {
  843.     if ( d->snoop_by == dclose )
  844. d->snoop_by = NULL;
  845. }
  846.     }
  847.     if ( ( ch = dclose->character ) != NULL )
  848.     {
  849. sprintf( log_buf, "Closing link to %s.", ch->name );
  850. log_string( log_buf );
  851. if ( dclose->connected == CON_PLAYING )
  852. {
  853.     act( "$n has lost $s link.", ch, NULL, NULL, TO_ROOM );
  854.     ch->desc = NULL;
  855. }
  856. else
  857. {
  858.     free_char( dclose->character );
  859. }
  860.     }
  861.     if ( d_next == dclose )
  862. d_next = d_next->next;   
  863.     if ( dclose == descriptor_list )
  864.     {
  865. descriptor_list = descriptor_list->next;
  866.     }
  867.     else
  868.     {
  869. DESCRIPTOR_DATA *d;
  870. for ( d = descriptor_list; d && d->next != dclose; d = d->next )
  871.     ;
  872. if ( d != NULL )
  873.     d->next = dclose->next;
  874. else
  875.     bug( "Close_socket: dclose not found.", 0 );
  876.     }
  877.     close( dclose->descriptor );
  878.     free_string( dclose->host );
  879.     dclose->next = descriptor_free;
  880.     descriptor_free = dclose;
  881. #if defined(MSDOS) || defined(macintosh)
  882.     exit(1);
  883. #endif
  884.     return;
  885. }
  886. bool read_from_descriptor( DESCRIPTOR_DATA *d )
  887. {
  888.     int iStart;
  889.     /* Hold horses if pending command already. */
  890.     if ( d->incomm[0] != '' )
  891. return TRUE;
  892.     /* Check for overflow. */
  893.     iStart = strlen(d->inbuf);
  894.     if ( iStart >= sizeof(d->inbuf) - 10 )
  895.     {
  896. sprintf( log_buf, "%s input overflow!", d->host );
  897. log_string( log_buf );
  898. write_to_descriptor( d->descriptor,
  899.     "nr*** PUT A LID ON IT!!! ***nr", 0 );
  900. return FALSE;
  901.     }
  902.     /* Snarf input. */
  903. #if defined(macintosh)
  904.     for ( ; ; )
  905.     {
  906. int c;
  907. c = getc( stdin );
  908. if ( c == '' || c == EOF )
  909.     break;
  910. putc( c, stdout );
  911. if ( c == 'r' )
  912.     putc( 'n', stdout );
  913. d->inbuf[iStart++] = c;
  914. if ( iStart > sizeof(d->inbuf) - 10 )
  915.     break;
  916.     }
  917. #endif
  918. #if defined(MSDOS) || defined(unix)
  919.     for ( ; ; )
  920.     {
  921. int nRead;
  922. nRead = read( d->descriptor, d->inbuf + iStart,
  923.     sizeof(d->inbuf) - 10 - iStart );
  924. if ( nRead > 0 )
  925. {
  926.     iStart += nRead;
  927.     if ( d->inbuf[iStart-1] == 'n' || d->inbuf[iStart-1] == 'r' )
  928. break;
  929. }
  930. else if ( nRead == 0 )
  931. {
  932.     log_string( "EOF encountered on read." );
  933.     return FALSE;
  934. }
  935. else if ( errno == EWOULDBLOCK )
  936.     break;
  937. else
  938. {
  939.     perror( "Read_from_descriptor" );
  940.     return FALSE;
  941. }
  942.     }
  943. #endif
  944.     d->inbuf[iStart] = '';
  945.     return TRUE;
  946. }
  947. /*
  948.  * Transfer one line from input buffer to input line.
  949.  */
  950. void read_from_buffer( DESCRIPTOR_DATA *d )
  951. {
  952.     int i, j, k;
  953.     /*
  954.      * Hold horses if pending command already.
  955.      */
  956.     if ( d->incomm[0] != '' )
  957. return;
  958.     /*
  959.      * Look for at least one new line.
  960.      */
  961.     for ( i = 0; d->inbuf[i] != 'n' && d->inbuf[i] != 'r'; i++ )
  962.     {
  963. if ( d->inbuf[i] == '' )
  964.     return;
  965.     }
  966.     /*
  967.      * Canonical input processing.
  968.      */
  969.     for ( i = 0, k = 0; d->inbuf[i] != 'n' && d->inbuf[i] != 'r'; i++ )
  970.     {
  971. if ( k >= MAX_INPUT_LENGTH - 2 )
  972. {
  973.     write_to_descriptor( d->descriptor, "Line too long.nr", 0 );
  974.     /* skip the rest of the line */
  975.     for ( ; d->inbuf[i] != ''; i++ )
  976.     {
  977. if ( d->inbuf[i] == 'n' || d->inbuf[i] == 'r' )
  978.     break;
  979.     }
  980.     d->inbuf[i]   = 'n';
  981.     d->inbuf[i+1] = '';
  982.     break;
  983. }
  984. if ( d->inbuf[i] == 'b' && k > 0 )
  985.     --k;
  986. else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) )
  987.     d->incomm[k++] = d->inbuf[i];
  988.     }
  989.     /*
  990.      * Finish off the line.
  991.      */
  992.     if ( k == 0 )
  993. d->incomm[k++] = ' ';
  994.     d->incomm[k] = '';
  995.     /*
  996.      * Deal with bozos with #repeat 1000 ...
  997.      */
  998.     if ( k > 1 || d->incomm[0] == '!' )
  999.     {
  1000.      if ( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) )
  1001. {
  1002.     d->repeat = 0;
  1003. }
  1004. else
  1005. {
  1006.     if ( ++d->repeat >= 20 )
  1007.     {
  1008. sprintf( log_buf, "%s input spamming!", d->host );
  1009. log_string( log_buf );
  1010. write_to_descriptor( d->descriptor,
  1011.     "nr*** PUT A LID ON IT!!! ***nr", 0 );
  1012. strcpy( d->incomm, "quit" );
  1013.     }
  1014. }
  1015.     }
  1016.     /*
  1017.      * Do '!' substitution.
  1018.      */
  1019.     if ( d->incomm[0] == '!' )
  1020. strcpy( d->incomm, d->inlast );
  1021.     else
  1022. strcpy( d->inlast, d->incomm );
  1023.     /*
  1024.      * Shift the input buffer.
  1025.      */
  1026.     while ( d->inbuf[i] == 'n' || d->inbuf[i] == 'r' )
  1027. i++;
  1028.     for ( j = 0; ( d->inbuf[j] = d->inbuf[i+j] ) != ''; j++ )
  1029. ;
  1030.     return;
  1031. }
  1032. /*
  1033.  * Low level output function.
  1034.  */
  1035. bool process_output( DESCRIPTOR_DATA *d, bool fPrompt )
  1036. {
  1037.     extern bool merc_down;
  1038.     /*
  1039.      * Bust a prompt.
  1040.      */
  1041.     if ( fPrompt && !merc_down && d->connected == CON_PLAYING )
  1042.         if ( d->showstr_point )
  1043.     write_to_buffer( d,
  1044.   "[Please type (c)ontinue, (r)efresh, (b)ack, (h)elp, (q)uit, or RETURN]:  ",
  1045.     0 );
  1046. else
  1047. {
  1048.     CHAR_DATA *ch;
  1049.     ch = d->original ? d->original : d->character;
  1050.     if ( IS_SET(ch->act, PLR_BLANK) )
  1051.         write_to_buffer( d, "nr", 2 );
  1052.     if ( IS_SET(ch->act, PLR_PROMPT) )
  1053.         bust_a_prompt( ch );
  1054.     if ( IS_SET(ch->act, PLR_TELNET_GA) )
  1055.         write_to_buffer( d, go_ahead_str, 0 );
  1056. }
  1057.     /*
  1058.      * Short-circuit if nothing to write.
  1059.      */
  1060.     if ( d->outtop == 0 )
  1061. return TRUE;
  1062.     /*
  1063.      * Snoop-o-rama.
  1064.      */
  1065.     if ( d->snoop_by != NULL )
  1066.     {
  1067. write_to_buffer( d->snoop_by, "% ", 2 );
  1068. write_to_buffer( d->snoop_by, d->outbuf, d->outtop );
  1069.     }
  1070.     /*
  1071.      * OS-dependent output.
  1072.      */
  1073.     if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) )
  1074.     {
  1075. d->outtop = 0;
  1076. return FALSE;
  1077.     }
  1078.     else
  1079.     {
  1080. d->outtop = 0;
  1081. return TRUE;
  1082.     }
  1083. }
  1084. /*
  1085.  * Bust a prompt (player settable prompt)
  1086.  * coded by Morgenes for Aldara Mud
  1087.  */
  1088. void bust_a_prompt( CHAR_DATA *ch )
  1089. {
  1090.    char buf[MAX_STRING_LENGTH];
  1091.    char buf2[MAX_STRING_LENGTH];
  1092.    const char *str;
  1093.    const char *i;
  1094.    char *point;
  1095.    if( ch->prompt == NULL || ch->prompt[0] == '' )
  1096.    {
  1097.       send_to_char( "nrnr", ch );
  1098.       return;
  1099.    }
  1100.    point = buf;
  1101.    str = ch->prompt;
  1102.    while( *str != '' )
  1103.    {
  1104.       if( *str != '%' )
  1105.       {
  1106.          *point++ = *str++;
  1107.          continue;
  1108.       }
  1109.       ++str;
  1110.       switch( *str )
  1111.       {
  1112.          default :
  1113.             i = " "; break;
  1114.          case 'h' :
  1115.             sprintf( buf2, "%d", ch->hit );
  1116.             i = buf2; break;
  1117.          case 'H' :
  1118.             sprintf( buf2, "%d", ch->max_hit );
  1119.             i = buf2; break;
  1120.          case 'm' :
  1121.             sprintf( buf2, "%d", ch->mana );
  1122.             i = buf2; break;
  1123.          case 'M' :
  1124.             sprintf( buf2, "%d", ch->max_mana );
  1125.             i = buf2; break;
  1126.          case 'v' :
  1127.             sprintf( buf2, "%d", ch->move );
  1128.             i = buf2; break;
  1129.          case 'V' :
  1130.             sprintf( buf2, "%d", ch->max_move );
  1131.             i = buf2; break;
  1132.          case 'x' :
  1133.             sprintf( buf2, "%d", ch->exp );
  1134.             i = buf2; break;
  1135.          case 'g' :
  1136.             sprintf( buf2, "%d", ch->gold);
  1137.             i = buf2; break;
  1138.          case 'a' :
  1139.             if( ch->level < 5 )
  1140.                sprintf( buf2, "%d", ch->alignment );
  1141.             else
  1142.                sprintf( buf2, "%s", IS_GOOD(ch) ? "good" : IS_EVIL(ch) ? 
  1143.                 "evil" : "neutral" );
  1144.             i = buf2; break;
  1145.          case 'r' :
  1146.             if( ch->in_room != NULL )
  1147.                sprintf( buf2, "%s", ch->in_room->name );
  1148.             else
  1149.                sprintf( buf2, " " );
  1150.             i = buf2; break;
  1151.          case 'R' :
  1152.             if( IS_IMMORTAL( ch ) && ch->in_room != NULL )
  1153.                sprintf( buf2, "%d", ch->in_room->vnum );
  1154.             else
  1155.                sprintf( buf2, " " );
  1156.             i = buf2; break;
  1157.          case 'z' :
  1158.             if( IS_IMMORTAL( ch ) && ch->in_room != NULL )
  1159.                sprintf( buf2, "%s", ch->in_room->area->name );
  1160.             else
  1161.                sprintf( buf2, " " );
  1162.             i = buf2; break;
  1163.          case '%' :
  1164.             sprintf( buf2, "%%" );
  1165.             i = buf2; break;
  1166.       } 
  1167.       ++str;
  1168.       while( (*point = *i) != '' )
  1169.          ++point, ++i;      
  1170.    }
  1171.    write_to_buffer( ch->desc, buf, point - buf );
  1172.    return;
  1173. }
  1174. /*
  1175.  * Append onto an output buffer.
  1176.  */
  1177. void write_to_buffer( DESCRIPTOR_DATA *d, const char *txt, int length )
  1178. {
  1179.     /*
  1180.      * Find length in case caller didn't.
  1181.      */
  1182.     if ( length <= 0 )
  1183. length = strlen(txt);
  1184.     /*
  1185.      * Initial nr if needed.
  1186.      */
  1187.     if ( d->outtop == 0 && !d->fcommand )
  1188.     {
  1189. d->outbuf[0] = 'n';
  1190. d->outbuf[1] = 'r';
  1191. d->outtop = 2;
  1192.     }
  1193.     /*
  1194.      * Expand the buffer as needed.
  1195.      */
  1196.     while ( d->outtop + length >= d->outsize )
  1197.     {
  1198. char *outbuf;
  1199. outbuf      = alloc_mem( 2 * d->outsize );
  1200. strncpy( outbuf, d->outbuf, d->outtop );
  1201. free_mem( d->outbuf, d->outsize );
  1202. d->outbuf   = outbuf;
  1203. d->outsize *= 2;
  1204.     }
  1205.     /*
  1206.      * Copy.
  1207.      */
  1208.     strcpy( d->outbuf + d->outtop, txt );
  1209.     d->outtop += length;
  1210.     return;
  1211. }
  1212. /*
  1213.  * Lowest level output function.
  1214.  * Write a block of text to the file descriptor.
  1215.  * If this gives errors on very long blocks (like 'ofind all'),
  1216.  *   try lowering the max block size.
  1217.  */
  1218. bool write_to_descriptor( int desc, char *txt, int length )
  1219. {
  1220.     int iStart;
  1221.     int nWrite;
  1222.     int nBlock;
  1223. #if defined(macintosh) || defined(MSDOS)
  1224.     if ( desc == 0 )
  1225. desc = 1;
  1226. #endif
  1227.     if ( length <= 0 )
  1228. length = strlen(txt);
  1229.     for ( iStart = 0; iStart < length; iStart += nWrite )
  1230.     {
  1231. nBlock = UMIN( length - iStart, 4096 );
  1232. if ( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 )
  1233.     { perror( "Write_to_descriptor" ); return FALSE; }
  1234.     } 
  1235.     return TRUE;
  1236. }
  1237. /*
  1238.  * Deal with sockets that haven't logged in yet.
  1239.  */
  1240. void nanny( DESCRIPTOR_DATA *d, char *argument )
  1241. {
  1242.     char buf[MAX_STRING_LENGTH];
  1243.     CHAR_DATA *ch;
  1244.     NOTE_DATA *pnote;
  1245.     char *pwdnew;
  1246.     char *p;
  1247.     int iClass;
  1248.     int lines;
  1249.     int notes;
  1250.     bool fOld;
  1251.     while ( isspace(*argument) )
  1252. argument++;
  1253.     ch = d->character;
  1254.     switch ( d->connected )
  1255.     {
  1256.     default:
  1257. bug( "Nanny: bad d->connected %d.", d->connected );
  1258. close_socket( d );
  1259. return;
  1260.     case CON_GET_NAME:
  1261. if ( argument[0] == '' )
  1262. {
  1263.     close_socket( d );
  1264.     return;
  1265. }
  1266. argument[0] = UPPER(argument[0]);
  1267. if ( !check_parse_name( argument ) )
  1268. {
  1269.     write_to_buffer( d, "Illegal name, try another.nrName: ", 0 );
  1270.     return;
  1271. }
  1272. fOld = load_char_obj( d, argument );
  1273. ch   = d->character;
  1274. if ( IS_SET(ch->act, PLR_DENY) )
  1275. {
  1276.     sprintf( log_buf, "Denying access to %s@%s.", argument, d->host );
  1277.     log_string( log_buf );
  1278.     write_to_buffer( d, "You are denied access.nr", 0 );
  1279.     close_socket( d );
  1280.     return;
  1281. }
  1282. if ( check_reconnect( d, argument, FALSE ) )
  1283. {
  1284.     fOld = TRUE;
  1285. }
  1286. else
  1287. {
  1288.     if ( wizlock && !IS_HERO( ch ) && !ch->wizbit )
  1289.     {
  1290. write_to_buffer( d, "The game is wizlocked.nr", 0 );
  1291. close_socket( d );
  1292. return;
  1293.     }
  1294. }
  1295. if ( fOld )
  1296. {
  1297.     /* Old player */
  1298.     write_to_buffer( d, "Password: ", 0 );
  1299.     write_to_buffer( d, echo_off_str, 0 );
  1300.     d->connected = CON_GET_OLD_PASSWORD;
  1301.     return;
  1302. }
  1303. else
  1304. {
  1305.     /* New player */
  1306.     /* New characters with same name fix by Salem's Lot */
  1307.     if ( check_playing( d, ch->name ) )
  1308.         return;
  1309.     sprintf( buf, "Did I get that right, %s (Y/N)? ", argument );
  1310.     write_to_buffer( d, buf, 0 );
  1311.     d->connected = CON_CONFIRM_NEW_NAME;
  1312.     return;
  1313. }
  1314. break;
  1315.     case CON_GET_OLD_PASSWORD:
  1316. #if defined(unix)
  1317. write_to_buffer( d, "nr", 2 );
  1318. #endif
  1319. if ( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
  1320. {
  1321.     write_to_buffer( d, "Wrong password.nr", 0 );
  1322.     close_socket( d );
  1323.     return;
  1324. }
  1325. write_to_buffer( d, echo_on_str, 0 );
  1326. if ( check_reconnect( d, ch->name, TRUE ) )
  1327.     return;
  1328. if ( check_playing( d, ch->name ) )
  1329.     return;
  1330.     
  1331. sprintf( log_buf, "%s@%s has connected.", ch->name, d->host );
  1332. log_string( log_buf );
  1333. lines = ch->pcdata->pagelen;
  1334. ch->pcdata->pagelen = 20;
  1335. if ( IS_HERO(ch) )
  1336.     do_help( ch, "imotd" );
  1337. do_help( ch, "motd" );
  1338. ch->pcdata->pagelen = lines;
  1339. d->connected = CON_READ_MOTD;
  1340. break;
  1341.     case CON_CONFIRM_NEW_NAME:
  1342. switch ( *argument )
  1343. {
  1344. case 'y': case 'Y':
  1345.     sprintf( buf, "New character.nrGive me a password for %s: %s",
  1346. ch->name, echo_off_str );
  1347.     write_to_buffer( d, buf, 0 );
  1348.     d->connected = CON_GET_NEW_PASSWORD;
  1349.     break;
  1350. case 'n': case 'N':
  1351.     write_to_buffer( d, "Ok, what IS it, then? ", 0 );
  1352.     free_char( d->character );
  1353.     d->character = NULL;
  1354.     d->connected = CON_GET_NAME;
  1355.     break;
  1356. default:
  1357.     write_to_buffer( d, "Please type Yes or No? ", 0 );
  1358.     break;
  1359. }
  1360. break;
  1361.     case CON_GET_NEW_PASSWORD:
  1362. #if defined(unix)
  1363. write_to_buffer( d, "nr", 2 );
  1364. #endif
  1365. if ( strlen(argument) < 5 )
  1366. {
  1367.     write_to_buffer( d,
  1368. "Password must be at least five characters long.nrPassword: ",
  1369. 0 );
  1370.     return;
  1371. }
  1372. pwdnew = crypt( argument, ch->name );
  1373. for ( p = pwdnew; *p != ''; p++ )
  1374. {
  1375.     if ( *p == '~' )
  1376.     {
  1377. write_to_buffer( d,
  1378.     "New password not acceptable, try again.nrPassword: ",
  1379.     0 );
  1380. return;
  1381.     }
  1382. }
  1383. free_string( ch->pcdata->pwd );
  1384. ch->pcdata->pwd = str_dup( pwdnew );
  1385. write_to_buffer( d, "Please retype password: ", 0 );
  1386. d->connected = CON_CONFIRM_NEW_PASSWORD;
  1387. break;
  1388.     case CON_CONFIRM_NEW_PASSWORD:
  1389. #if defined(unix)
  1390. write_to_buffer( d, "nr", 2 );
  1391. #endif
  1392. if ( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
  1393. {
  1394.     write_to_buffer( d, "Passwords don't match.nrRetype password: ",
  1395. 0 );
  1396.     d->connected = CON_GET_NEW_PASSWORD;
  1397.     return;
  1398. }
  1399. write_to_buffer( d, echo_on_str, 0 );
  1400. write_to_buffer( d, "What is your sex (M/F/N)? ", 0 );
  1401. d->connected = CON_GET_NEW_SEX;
  1402. break;
  1403.     case CON_GET_NEW_SEX:
  1404. switch ( argument[0] )
  1405. {
  1406. case 'm': case 'M': ch->sex = SEX_MALE;    break;
  1407. case 'f': case 'F': ch->sex = SEX_FEMALE;  break;
  1408. case 'n': case 'N': ch->sex = SEX_NEUTRAL; break;
  1409. default:
  1410.     write_to_buffer( d, "That's not a sex.nrWhat IS your sex? ", 0 );
  1411.     return;
  1412. }
  1413. strcpy( buf, "Select a class [" );
  1414. for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
  1415. {
  1416.     if ( iClass > 0 )
  1417. strcat( buf, " " );
  1418.     strcat( buf, class_table[iClass].who_name );
  1419. }
  1420. strcat( buf, "]: " );
  1421. write_to_buffer( d, buf, 0 );
  1422. d->connected = CON_GET_NEW_CLASS;
  1423. break;
  1424.     case CON_GET_NEW_CLASS:
  1425. for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
  1426. {
  1427.     if ( !str_cmp( argument, class_table[iClass].who_name ) )
  1428.     {
  1429. ch->class = iClass;
  1430. break;
  1431.     }
  1432. }
  1433. if ( iClass == MAX_CLASS )
  1434. {
  1435.     write_to_buffer( d,
  1436. "That's not a class.nrWhat IS your class? ", 0 );
  1437.     return;
  1438. }
  1439. sprintf( log_buf, "%s@%s new player.", ch->name, d->host );
  1440. log_string( log_buf );
  1441. write_to_buffer( d, "nr", 2 );
  1442. ch->pcdata->pagelen = 20;
  1443. ch->prompt = "<%hhp %mm %vmv> ";
  1444. do_help( ch, "motd" );
  1445. d->connected = CON_READ_MOTD;
  1446. break;
  1447.     case CON_READ_MOTD:
  1448. ch->next = char_list;
  1449. char_list = ch;
  1450. d->connected = CON_PLAYING;
  1451. send_to_char(
  1452.     "nrWelcome to Merc Diku Mud.  May your visit here be ... Mercenary.nr",
  1453.     ch );
  1454. if ( ch->level == 0 )
  1455. {
  1456.     OBJ_DATA *obj;
  1457.     switch ( class_table[ch->class].attr_prime )
  1458.     {
  1459.     case APPLY_STR: ch->pcdata->perm_str = 16; break;
  1460.     case APPLY_INT: ch->pcdata->perm_int = 16; break;
  1461.     case APPLY_WIS: ch->pcdata->perm_wis = 16; break;
  1462.     case APPLY_DEX: ch->pcdata->perm_dex = 16; break;
  1463.     case APPLY_CON: ch->pcdata->perm_con = 16; break;
  1464.     }
  1465.     ch->level = 1;
  1466.     ch->exp = 1000;
  1467.     ch->hit = ch->max_hit;
  1468.     ch->mana = ch->max_mana;
  1469.     ch->move = ch->max_move;
  1470.     sprintf( buf, "the %s",
  1471. title_table [ch->class] [ch->level]
  1472. [ch->sex == SEX_FEMALE ? 1 : 0] );
  1473.     set_title( ch, buf );
  1474.     obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_BANNER), 0 );
  1475.     obj_to_char( obj, ch );
  1476.     equip_char( ch, obj, WEAR_LIGHT );
  1477.     obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_VEST), 0 );
  1478.     obj_to_char( obj, ch );
  1479.     equip_char( ch, obj, WEAR_BODY );
  1480.     obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_SHIELD), 0 );
  1481.     obj_to_char( obj, ch );
  1482.     equip_char( ch, obj, WEAR_SHIELD );
  1483.     obj = create_object( get_obj_index(class_table[ch->class].weapon),
  1484. 0 );
  1485.     obj_to_char( obj, ch );
  1486.     equip_char( ch, obj, WEAR_WIELD );
  1487.     char_to_room( ch, get_room_index( ROOM_VNUM_SCHOOL ) );
  1488. }
  1489. else if ( ch->in_room != NULL )
  1490. {
  1491.     char_to_room( ch, ch->in_room );
  1492. }
  1493. else if ( IS_IMMORTAL(ch) )
  1494. {
  1495.     char_to_room( ch, get_room_index( ROOM_VNUM_CHAT ) );
  1496. }
  1497. else
  1498. {
  1499.     char_to_room( ch, get_room_index( ROOM_VNUM_TEMPLE ) );
  1500. }
  1501. act( "$n has entered the game.", ch, NULL, NULL, TO_ROOM );
  1502. do_look( ch, "auto" );
  1503. /* check for new notes */
  1504. notes = 0;
  1505. for ( pnote = note_list; pnote != NULL; pnote = pnote->next )
  1506.     if ( is_note_to( ch, pnote ) && str_cmp( ch->name, pnote->sender )
  1507. && pnote->date_stamp > ch->last_note )
  1508.         notes++;
  1509. if ( notes == 1 )
  1510.     send_to_char( "nrYou have one new note waiting.nr", ch );
  1511. else
  1512.     if ( notes > 1 )
  1513.     {
  1514. sprintf( buf, "nrYou have %d new notes waiting.nr",
  1515. notes );
  1516. send_to_char( buf, ch );
  1517.     }
  1518. break;
  1519.     }
  1520.     return;
  1521. }
  1522. /*
  1523.  * Parse a name for acceptability.
  1524.  */
  1525. bool check_parse_name( char *name )
  1526. {
  1527.     /*
  1528.      * Reserved words.
  1529.      */
  1530.     if ( is_name( name, "all auto immortal self someone" ) )
  1531. return FALSE;
  1532.     /*
  1533.      * Length restrictions.
  1534.      */
  1535.     if ( strlen(name) <  3 )
  1536. return FALSE;
  1537. #if defined(MSDOS)
  1538.     if ( strlen(name) >  8 )
  1539. return FALSE;
  1540. #endif
  1541. #if defined(macintosh) || defined(unix)
  1542.     if ( strlen(name) > 12 )
  1543. return FALSE;
  1544. #endif
  1545.     /*
  1546.      * Alphanumerics only.
  1547.      * Lock out IllIll twits.
  1548.      */
  1549.     {
  1550. char *pc;
  1551. bool fIll;
  1552. fIll = TRUE;
  1553. for ( pc = name; *pc != ''; pc++ )
  1554. {
  1555.     if ( !isalpha(*pc) )
  1556. return FALSE;
  1557.     if ( LOWER(*pc) != 'i' && LOWER(*pc) != 'l' )
  1558. fIll = FALSE;
  1559. }
  1560. if ( fIll )
  1561.     return FALSE;
  1562.     }
  1563.     /*
  1564.      * Prevent players from naming themselves after mobs.
  1565.      */
  1566.     {
  1567. extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
  1568. MOB_INDEX_DATA *pMobIndex;
  1569. int iHash;
  1570. for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
  1571. {
  1572.     for ( pMobIndex  = mob_index_hash[iHash];
  1573.   pMobIndex != NULL;
  1574.   pMobIndex  = pMobIndex->next )
  1575.     {
  1576. if ( is_name( name, pMobIndex->player_name ) )
  1577.     return FALSE;
  1578.     }
  1579. }
  1580.     }
  1581.     return TRUE;
  1582. }
  1583. /*
  1584.  * Look for link-dead player to reconnect.
  1585.  */
  1586. bool check_reconnect( DESCRIPTOR_DATA *d, char *name, bool fConn )
  1587. {
  1588.     CHAR_DATA *ch;
  1589.     OBJ_DATA *obj;
  1590.     for ( ch = char_list; ch != NULL; ch = ch->next )
  1591.     {
  1592. if ( !IS_NPC(ch)
  1593. && ( !fConn || ch->desc == NULL )
  1594. &&   !str_cmp( d->character->name, ch->name ) )
  1595. {
  1596.     if ( fConn == FALSE )
  1597.     {
  1598. free_string( d->character->pcdata->pwd );
  1599. d->character->pcdata->pwd = str_dup( ch->pcdata->pwd );
  1600.     }
  1601.     else
  1602.     {
  1603. free_char( d->character );
  1604. d->character = ch;
  1605. ch->desc  = d;
  1606. ch->timer  = 0;
  1607. send_to_char( "Reconnecting.nr", ch );
  1608. act( "$n has reconnected.", ch, NULL, NULL, TO_ROOM );
  1609. sprintf( log_buf, "%s@%s reconnected.", ch->name, d->host );
  1610. log_string( log_buf );
  1611. d->connected = CON_PLAYING;
  1612. /*
  1613.  * Contributed by Gene Choi
  1614.  */
  1615. if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL
  1616.     && obj->item_type == ITEM_LIGHT
  1617.     && obj->value[2] != 0
  1618.     && ch->in_room != NULL )
  1619.     ++ch->in_room->light;
  1620.     }
  1621.     return TRUE;
  1622. }
  1623.     }
  1624.     return FALSE;
  1625. }
  1626. /*
  1627.  * Check if already playing.
  1628.  */
  1629. bool check_playing( DESCRIPTOR_DATA *d, char *name )
  1630. {
  1631.     DESCRIPTOR_DATA *dold;
  1632.     for ( dold = descriptor_list; dold; dold = dold->next )
  1633.     {
  1634. if ( dold != d
  1635. &&   dold->character != NULL
  1636. &&   dold->connected != CON_GET_NAME
  1637. &&   dold->connected != CON_GET_OLD_PASSWORD
  1638. &&   !str_cmp( name, dold->original
  1639.          ? dold->original->name : dold->character->name ) )
  1640. {
  1641.     write_to_buffer( d, "Already playing.nrName: ", 0 );
  1642.     d->connected = CON_GET_NAME;
  1643.     if ( d->character != NULL )
  1644.     {
  1645. free_char( d->character );
  1646. d->character = NULL;
  1647.     }
  1648.     return TRUE;
  1649. }
  1650.     }
  1651.     return FALSE;
  1652. }
  1653. void stop_idling( CHAR_DATA *ch )
  1654. {
  1655.     if ( ch == NULL
  1656.     ||   ch->desc == NULL
  1657.     ||   ch->desc->connected != CON_PLAYING
  1658.     ||   ch->was_in_room == NULL 
  1659.     ||   ch->in_room != get_room_index( ROOM_VNUM_LIMBO ) )
  1660. return;
  1661.     ch->timer = 0;
  1662.     char_from_room( ch );
  1663.     char_to_room( ch, ch->was_in_room );
  1664.     ch->was_in_room = NULL;
  1665.     act( "$n has returned from the void.", ch, NULL, NULL, TO_ROOM );
  1666.     return;
  1667. }
  1668. /*
  1669.  * Write to one char.
  1670.  */
  1671. void send_to_char( const char *txt, CHAR_DATA *ch )
  1672. {
  1673.     if ( txt == NULL || ch->desc == NULL )
  1674.         return;
  1675.     ch->desc->showstr_head = alloc_mem( strlen( txt ) + 1 );
  1676.     strcpy( ch->desc->showstr_head, txt );
  1677.     ch->desc->showstr_point = ch->desc->showstr_head;
  1678.     show_string( ch->desc, "" );
  1679. }
  1680. /* The heart of the pager.  Thanks to N'Atas-Ha, ThePrincedom
  1681.    for porting this SillyMud code for MERC 2.0 and laying down the groundwork.
  1682.    Thanks to Blackstar, hopper.cs.uiowa.edu 4000 for which
  1683.    the improvements to the pager was modeled from.  - Kahn */
  1684. void show_string(struct descriptor_data *d, char *input)
  1685. {
  1686.   char buffer[ MAX_STRING_LENGTH ];
  1687.   char buf[ MAX_INPUT_LENGTH ];
  1688.   register char *scan, *chk;
  1689.   int lines = 0, toggle=1;
  1690.   one_argument(input, buf);
  1691.   switch( UPPER( buf[0] ) )
  1692.   {
  1693.   case '':
  1694.   case 'C': /* show next page of text */
  1695.     lines = 0;
  1696.     break;
  1697.   case 'R': /* refresh current page of text */
  1698.     lines = - 1 - (d->character->pcdata->pagelen);
  1699.     break;
  1700.   case 'B': /* scroll back a page of text */
  1701.     lines = -(2*d->character->pcdata->pagelen);
  1702.     break;
  1703.   case 'H': /* Show some help */
  1704.     write_to_buffer( d,
  1705.         "C, or Return = continue, R = redraw this page,nr", 0 );
  1706.     write_to_buffer( d,
  1707.         "B = back one page, H = this help, Q or other keys = exit.nrnr",
  1708.     0 );
  1709.     lines = - 1 - (d->character->pcdata->pagelen);
  1710.     break;
  1711.   default: /*otherwise, stop the text viewing */
  1712.     if ( d->showstr_head )
  1713.     {
  1714.       free_string( d->showstr_head );
  1715.       d->showstr_head  = 0;
  1716.     }
  1717.     d->showstr_point = 0;
  1718.     return;
  1719.   }
  1720.   /* do any backing up necessary */
  1721.   if (lines < 0)
  1722.   {
  1723.     for ( scan = d->showstr_point; scan > d->showstr_head; scan-- )
  1724.          if ( ( *scan == 'n' ) || ( *scan == 'r' ) )
  1725.  {
  1726.      toggle = -toggle;
  1727.      if ( toggle < 0 )
  1728.          if ( !( ++lines ) )
  1729.      break;
  1730.  }
  1731.     d->showstr_point = scan;
  1732.   }
  1733.   /* show a chunk */
  1734.   lines  = 0;
  1735.   toggle = 1;
  1736.   for ( scan = buffer; ; scan++, d->showstr_point++ )
  1737.        if ( ( ( *scan = *d->showstr_point ) == 'n' || *scan == 'r' )
  1738.    && ( toggle = -toggle ) < 0 )
  1739.    lines++;
  1740.        else
  1741.    if ( !*scan || ( d->character && !IS_NPC( d->character )
  1742.   && lines >= d->character->pcdata->pagelen) )
  1743.    {
  1744.        *scan = '';
  1745.        write_to_buffer( d, buffer, strlen( buffer ) );
  1746.      /* See if this is the end (or near the end) of the string */
  1747.        for ( chk = d->showstr_point; isspace( *chk ); chk++ );
  1748.        if ( !*chk )
  1749.        {
  1750.    if ( d->showstr_head )
  1751.    {
  1752.       free_string( d->showstr_head );
  1753.       d->showstr_head  = 0;
  1754.    }
  1755.    d->showstr_point = 0;
  1756.        }
  1757.        return;
  1758.    }
  1759.   return;
  1760. }
  1761. /*
  1762.  * The primary output interface for formatted output.
  1763.  */
  1764. void act( const char *format, CHAR_DATA *ch, const void *arg1,
  1765.  const void *arg2, int type )
  1766. {
  1767.     static char * const he_she [] = { "it",  "he",  "she" };
  1768.     static char * const him_her [] = { "it",  "him", "her" };
  1769.     static char * const his_her [] = { "its", "his", "her" };
  1770.     char buf[MAX_STRING_LENGTH];
  1771.     char fname[MAX_INPUT_LENGTH];
  1772.     CHAR_DATA *to;
  1773.     CHAR_DATA *vch = (CHAR_DATA *) arg2;
  1774.     OBJ_DATA *obj1 = (OBJ_DATA  *) arg1;
  1775.     OBJ_DATA *obj2 = (OBJ_DATA  *) arg2;
  1776.     const char *str;
  1777.     const char *i;
  1778.     char *point;
  1779.     /*
  1780.      * Discard null and zero-length messages.
  1781.      */
  1782.     if ( format == NULL || format[0] == '' )
  1783. return;
  1784.     to = ch->in_room->people;
  1785.     if ( type == TO_VICT )
  1786.     {
  1787. if ( vch == NULL )
  1788. {
  1789.     bug( "Act: null vch with TO_VICT.", 0 );
  1790.     return;
  1791. }
  1792. to = vch->in_room->people;
  1793.     }
  1794.     
  1795.     for ( ; to != NULL; to = to->next_in_room )
  1796.     {
  1797. if ( ( to->desc == NULL 
  1798.     && ( IS_NPC( to ) && !(to->pIndexData->progtypes & ACT_PROG ) ) )
  1799.     || !IS_AWAKE(to) )
  1800.     continue;
  1801. if ( type == TO_CHAR && to != ch )
  1802.     continue;
  1803. if ( type == TO_VICT && ( to != vch || to == ch ) )
  1804.     continue;
  1805. if ( type == TO_ROOM && to == ch )
  1806.     continue;
  1807. if ( type == TO_NOTVICT && (to == ch || to == vch) )
  1808.     continue;
  1809. point = buf;
  1810. str = format;
  1811. while ( *str != '' )
  1812. {
  1813.     if ( *str != '$' )
  1814.     {
  1815. *point++ = *str++;
  1816. continue;
  1817.     }
  1818.     ++str;
  1819.     if ( arg2 == NULL && *str >= 'A' && *str <= 'Z' )
  1820.     {
  1821. bug( "Act: missing arg2 for code %d.", *str );
  1822. i = " <@@@> ";
  1823.     }
  1824.     else
  1825.     {
  1826. switch ( *str )
  1827. {
  1828. default:  bug( "Act: bad code %d.", *str );
  1829.   i = " <@@@> "; break;
  1830. /* Thx alex for 't' idea */
  1831. case 't': i = (char *) arg1; break;
  1832. case 'T': i = (char *) arg2;           break;
  1833. case 'n': i = PERS( ch,  to  ); break;
  1834. case 'N': i = PERS( vch, to  ); break;
  1835. case 'e': i = he_she  [URANGE(0, ch  ->sex, 2)]; break;
  1836. case 'E': i = he_she  [URANGE(0, vch ->sex, 2)]; break;
  1837. case 'm': i = him_her [URANGE(0, ch  ->sex, 2)]; break;
  1838. case 'M': i = him_her [URANGE(0, vch ->sex, 2)]; break;
  1839. case 's': i = his_her [URANGE(0, ch  ->sex, 2)]; break;
  1840. case 'S': i = his_her [URANGE(0, vch ->sex, 2)]; break;
  1841. case 'p':
  1842.     i = can_see_obj( to, obj1 )
  1843.     ? obj1->short_descr
  1844.     : "something";
  1845.     break;
  1846. case 'P':
  1847.     i = can_see_obj( to, obj2 )
  1848.     ? obj2->short_descr
  1849.     : "something";
  1850.     break;
  1851. case 'd':
  1852.     if ( arg2 == NULL || ((char *) arg2)[0] == '' )
  1853.     {
  1854. i = "door";
  1855.     }
  1856.     else
  1857.     {
  1858. one_argument( (char *) arg2, fname );
  1859. i = fname;
  1860.     }
  1861.     break;
  1862. }
  1863.     }
  1864.     ++str;
  1865.     while ( ( *point = *i ) != '' )
  1866. ++point, ++i;
  1867. }
  1868. *point++ = 'n';
  1869. *point++ = 'r';
  1870. buf[0]   = UPPER(buf[0]);
  1871. if (to->desc)
  1872.   write_to_buffer( to->desc, buf, point - buf );
  1873. if (MOBtrigger)
  1874.   mprog_act_trigger( buf, to, ch, obj1, vch );
  1875.                                             /* Added by Kahn */
  1876.     }
  1877.     MOBtrigger = TRUE;
  1878.     return;
  1879. }
  1880. /*
  1881.  * Macintosh support functions.
  1882.  */
  1883. #if defined(macintosh)
  1884. int gettimeofday( struct timeval *tp, void *tzp )
  1885. {
  1886.     tp->tv_sec  = time( NULL );
  1887.     tp->tv_usec = 0;
  1888. }
  1889. #endif