COMM.C
资源名称:mercwsrc.zip [点击查看]
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:51k
源码类别:
Internet/网络编程
开发平台:
WINDOWS
- /***************************************************************************
- * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
- * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
- * *
- * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
- * Chastain, Michael Quan, and Mitchell Tse. *
- * *
- * In order to use any part of this Merc Diku Mud, you must comply with *
- * both the original Diku license in 'license.doc' as well the Merc *
- * license in 'license.txt'. In particular, you may not remove either of *
- * these copyright notices. *
- * *
- * Thanks to abaddon for proof-reading our comm.c and pointing out bugs. *
- * Any remaining bugs are, of course, our work, not his. :) *
- * *
- * Much time and thought has gone into this software and you are *
- * benefitting. We hope that you share your changes too. What goes *
- * around, comes around. *
- ***************************************************************************/
- /*
- * This file contains all of the OS-dependent stuff:
- * startup, signals, BSD sockets for tcp/ip, i/o, timing.
- *
- * The data flow for input is:
- * Game_loop ---> Read_from_descriptor ---> Read
- * Game_loop ---> Read_from_buffer
- *
- * The data flow for output is:
- * Game_loop ---> Process_Output ---> Write_to_descriptor -> Write
- *
- * The OS-dependent functions are Read_from_descriptor and Write_to_descriptor.
- * -- Furey 26 Jan 1993
- */
- #if defined(macintosh)
- #include <types.h>
- #else
- #include <sys/types.h>
- #ifndef WIN32s
- #include <sys/time.h>
- #endif // @@@
- #endif
- #include <ctype.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "merc.h"
- /*
- * Malloc debugging stuff.
- */
- #if defined(sun)
- #undef MALLOC_DEBUG
- #endif
- #if defined(MALLOC_DEBUG)
- #include <malloc.h>
- extern int malloc_debug args( ( int ) );
- extern int malloc_verify args( ( void ) );
- #endif
- /*
- * Signal handling.
- * Apollo has a problem with __attribute(atomic) in signal.h,
- * I dance around it.
- */
- #if defined(apollo)
- #define __attribute(x)
- #endif
- #if defined(unix)
- #include <signal.h>
- #endif
- #if defined(apollo)
- #undef __attribute
- #endif
- /*
- * Socket and TCP/IP stuff.
- */
- #if defined(macintosh) || defined(MSDOS)
- const char echo_off_str [] = { ' ' };
- const char echo_on_str [] = { ' ' };
- const char go_ahead_str [] = { ' ' };
- #endif
- #if defined(unix)
- #include <fcntl.h>
- #ifndef WIN32s // @@@
- #include <netdb.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <arpa/telnet.h>
- const char echo_off_str [] = { IAC, WILL, TELOPT_ECHO, ' ' };
- const char echo_on_str [] = { IAC, WONT, TELOPT_ECHO, ' ' };
- const char go_ahead_str [] = { IAC, GA, ' ' };
- #endif
- #endif
- /*
- * OS-dependent declarations.
- */
- #if defined(_AIX)
- #include <sys/select.h>
- int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
- int bind args( ( int s, struct sockaddr *name, int namelen ) );
- void bzero args( ( char *b, int length ) );
- int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
- int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
- int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
- int listen args( ( int s, int backlog ) );
- int setsockopt args( ( int s, int level, int optname, void *optval,
- int optlen ) );
- int socket args( ( int domain, int type, int protocol ) );
- #endif
- #if defined(apollo)
- #include <unistd.h>
- void bzero args( ( char *b, int length ) );
- #endif
- #if defined(__hpux)
- int accept args( ( int s, void *addr, int *addrlen ) );
- int bind args( ( int s, const void *addr, int addrlen ) );
- void bzero args( ( char *b, int length ) );
- int getpeername args( ( int s, void *addr, int *addrlen ) );
- int getsockname args( ( int s, void *name, int *addrlen ) );
- int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
- int listen args( ( int s, int backlog ) );
- int setsockopt args( ( int s, int level, int optname,
- const void *optval, int optlen ) );
- int socket args( ( int domain, int type, int protocol ) );
- #endif
- #if defined(interactive)
- #include <net/errno.h>
- #include <sys/fcntl.h>
- #endif
- #if defined(linux)
- int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
- int bind args( ( int s, struct sockaddr *name, int namelen ) );
- int close args( ( int fd ) );
- int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
- int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
- int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
- int listen args( ( int s, int backlog ) );
- int read args( ( int fd, char *buf, int nbyte ) );
- int select args( ( int width, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout ) );
- int socket args( ( int domain, int type, int protocol ) );
- int write args( ( int fd, char *buf, int nbyte ) );
- #endif
- #if defined(macintosh)
- #include <console.h>
- #include <fcntl.h>
- #include <unix.h>
- struct timeval
- {
- time_t tv_sec;
- time_t tv_usec;
- };
- #if !defined(isascii)
- #define isascii(c) ( (c) < 0200 )
- #endif
- static long theKeys [4];
- int gettimeofday args( ( struct timeval *tp, void *tzp ) );
- #endif
- #if defined(MIPS_OS)
- extern int errno;
- #endif
- #if defined(MSDOS)
- int gettimeofday args( ( struct timeval *tp, void *tzp ) );
- int kbhit args( ( void ) );
- #endif
- #if defined(WIN32s)
- int gettimeofday args( ( struct timeval *tp, void *tzp ) );
- #endif
- #if defined(NeXT)
- int close args( ( int fd ) );
- int fcntl args( ( int fd, int cmd, int arg ) );
- #if !defined(htons)
- u_short htons args( ( u_short hostshort ) );
- #endif
- #if !defined(ntohl)
- u_long ntohl args( ( u_long hostlong ) );
- #endif
- int read args( ( int fd, char *buf, int nbyte ) );
- int select args( ( int width, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout ) );
- int write args( ( int fd, char *buf, int nbyte ) );
- #endif
- #if defined(sequent)
- int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
- int bind args( ( int s, struct sockaddr *name, int namelen ) );
- int close args( ( int fd ) );
- int fcntl args( ( int fd, int cmd, int arg ) );
- int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
- int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
- int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
- #if !defined(htons)
- u_short htons args( ( u_short hostshort ) );
- #endif
- int listen args( ( int s, int backlog ) );
- #if !defined(ntohl)
- u_long ntohl args( ( u_long hostlong ) );
- #endif
- int read args( ( int fd, char *buf, int nbyte ) );
- int select args( ( int width, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout ) );
- int setsockopt args( ( int s, int level, int optname, caddr_t optval,
- int optlen ) );
- int socket args( ( int domain, int type, int protocol ) );
- int write args( ( int fd, char *buf, int nbyte ) );
- #endif
- /*
- * This includes Solaris SYSV as well
- */
- #if defined(sun)
- int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
- int bind args( ( int s, struct sockaddr *name, int namelen ) );
- void bzero args( ( char *b, int length ) );
- int close args( ( int fd ) );
- int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
- int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
- int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
- int listen args( ( int s, int backlog ) );
- int read args( ( int fd, char *buf, int nbyte ) );
- int select args( ( int width, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout ) );
- #if defined(SYSV)
- int setsockopt args( ( int s, int level, int optname,
- const char *optval, int optlen ) );
- #else
- int setsockopt args( ( int s, int level, int optname, void *optval,
- int optlen ) );
- #endif
- int socket args( ( int domain, int type, int protocol ) );
- int write args( ( int fd, char *buf, int nbyte ) );
- #endif
- #if defined(ultrix)
- int accept args( ( int s, struct sockaddr *addr, int *addrlen ) );
- int bind args( ( int s, struct sockaddr *name, int namelen ) );
- void bzero args( ( char *b, int length ) );
- int close args( ( int fd ) );
- int getpeername args( ( int s, struct sockaddr *name, int *namelen ) );
- int getsockname args( ( int s, struct sockaddr *name, int *namelen ) );
- int gettimeofday args( ( struct timeval *tp, struct timezone *tzp ) );
- int listen args( ( int s, int backlog ) );
- int read args( ( int fd, char *buf, int nbyte ) );
- int select args( ( int width, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout ) );
- int setsockopt args( ( int s, int level, int optname, void *optval,
- int optlen ) );
- int socket args( ( int domain, int type, int protocol ) );
- int write args( ( int fd, char *buf, int nbyte ) );
- #endif
- /*
- * Global variables.
- */
- DESCRIPTOR_DATA * descriptor_free; /* Free list for descriptors */
- DESCRIPTOR_DATA * descriptor_list; /* All open descriptors */
- DESCRIPTOR_DATA * d_next; /* Next descriptor in loop */
- FILE * fpReserve; /* Reserved file handle */
- bool god; /* All new chars are gods! */
- bool merc_down; /* Shutdown */
- bool wizlock; /* Game is wizlocked */
- char str_boot_time[MAX_INPUT_LENGTH];
- time_t current_time; /* Time of this pulse */
- /*
- * OS-dependent local functions.
- */
- #if defined(macintosh) || defined(MSDOS)
- void game_loop_mac_msdos args( ( void ) );
- bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) );
- bool write_to_descriptor args( ( int desc, char *txt, int length ) );
- #endif
- #if defined(unix)
- void game_loop_unix args( ( int control ) );
- int init_socket args( ( int port ) );
- void new_descriptor args( ( int control ) );
- bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) );
- bool write_to_descriptor args( ( int desc, char *txt, int length ) );
- #endif
- /*
- * Other local functions (OS-independent).
- */
- bool check_parse_name args( ( char *name ) );
- bool check_reconnect args( ( DESCRIPTOR_DATA *d, char *name,
- bool fConn ) );
- bool check_playing args( ( DESCRIPTOR_DATA *d, char *name ) );
- int main args( ( int argc, char **argv ) );
- void nanny args( ( DESCRIPTOR_DATA *d, char *argument ) );
- bool process_output args( ( DESCRIPTOR_DATA *d, bool fPrompt ) );
- void read_from_buffer args( ( DESCRIPTOR_DATA *d ) );
- void stop_idling args( ( CHAR_DATA *ch ) );
- void bust_a_prompt args( ( CHAR_DATA *ch ) );
- #ifdef WIN32s
- #include <winsock.h>
- int close(SOCKET s) { return closesocket(s); }
- #endif
- int main( int argc, char **argv )
- {
- struct timeval now_time;
- int port;
- #if defined(unix)
- int control;
- #endif
- /*
- * Memory debugging if needed.
- */
- #if defined(MALLOC_DEBUG)
- malloc_debug( 2 );
- #endif
- /*
- * Init time.
- */
- gettimeofday( &now_time, NULL );
- current_time = (time_t) now_time.tv_sec;
- strcpy( str_boot_time, ctime( ¤t_time ) );
- /*
- * Macintosh console initialization.
- */
- #if defined(macintosh)
- console_options.nrows = 31;
- cshow( stdout );
- csetmode( C_RAW, stdin );
- cecho2file( "log file", 1, stderr );
- #endif
- /*
- * Reserve one channel for our use.
- */
- if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
- {
- perror( NULL_FILE );
- exit( 1 );
- }
- /*
- * Get the port number.
- */
- port = 1234;
- if ( argc > 1 )
- {
- if ( !is_number( argv[1] ) )
- {
- fprintf( stderr, "Usage: %s [port #]n", argv[0] );
- exit( 1 );
- }
- else if ( ( port = atoi( argv[1] ) ) <= 1024 )
- {
- fprintf( stderr, "Port number must be above 1024.n" );
- exit( 1 );
- }
- }
- /*
- * Run the game.
- */
- #if defined(macintosh) || defined(MSDOS)
- boot_db( );
- log_string( "Merc is ready to rock." );
- game_loop_mac_msdos( );
- #endif
- #if defined(unix)
- control = init_socket( port );
- boot_db( );
- sprintf( log_buf, "Merc is ready to rock on port %d.", port );
- log_string( log_buf );
- game_loop_unix( control );
- close( control );
- #endif
- /*
- * That's all, folks.
- */
- log_string( "Normal termination of game." );
- exit( 0 );
- return 0;
- }
- #if defined(unix)
- int init_socket( int port )
- {
- static struct sockaddr_in sa_zero;
- struct sockaddr_in sa;
- int x = 1;
- int fd;
- if ( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
- {
- perror( "Init_socket: socket" );
- exit( 1 );
- }
- if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
- (char *) &x, sizeof(x) ) < 0 )
- {
- perror( "Init_socket: SO_REUSEADDR" );
- close( fd );
- exit( 1 );
- }
- #if defined(SO_DONTLINGER) && !defined(SYSV)
- {
- struct linger ld;
- ld.l_onoff = 1;
- ld.l_linger = 1000;
- if ( setsockopt( fd, SOL_SOCKET, SO_DONTLINGER,
- (char *) &ld, sizeof(ld) ) < 0 )
- {
- perror( "Init_socket: SO_DONTLINGER" );
- close( fd );
- exit( 1 );
- }
- }
- #endif
- sa = sa_zero;
- sa.sin_family = AF_INET;
- sa.sin_port = htons( port );
- if ( bind( fd, (struct sockaddr *) &sa, sizeof(sa) ) < 0 )
- {
- perror( "Init_socket: bind" );
- close( fd );
- exit( 1 );
- }
- if ( listen( fd, 3 ) < 0 )
- {
- perror( "Init_socket: listen" );
- close( fd );
- exit( 1 );
- }
- return fd;
- }
- #endif
- #if defined(macintosh) || defined(MSDOS)
- void game_loop_mac_msdos( void )
- {
- struct timeval last_time;
- struct timeval now_time;
- static DESCRIPTOR_DATA dcon;
- gettimeofday( &last_time, NULL );
- current_time = (time_t) last_time.tv_sec;
- /*
- * New_descriptor analogue.
- */
- dcon.descriptor = 0;
- dcon.connected = CON_GET_NAME;
- dcon.host = str_dup( "localhost" );
- dcon.outsize = 2000;
- dcon.outbuf = alloc_mem( dcon.outsize );
- dcon.next = descriptor_list;
- descriptor_list = &dcon;
- /*
- * Send the greeting.
- */
- {
- extern char * help_greeting;
- if ( help_greeting[0] == '.' )
- write_to_buffer( &dcon, help_greeting+1, 0 );
- else
- write_to_buffer( &dcon, help_greeting , 0 );
- }
- /* Main loop */
- while ( !merc_down )
- {
- DESCRIPTOR_DATA *d;
- /*
- * Process input.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- d_next = d->next;
- d->fcommand = FALSE;
- #if defined(MSDOS)
- if ( kbhit( ) )
- #endif
- {
- if ( d->character != NULL )
- d->character->timer = 0;
- if ( !read_from_descriptor( d ) )
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- continue;
- }
- }
- if ( d->character != NULL && d->character->wait > 0 )
- {
- --d->character->wait;
- continue;
- }
- read_from_buffer( d );
- if ( d->incomm[0] != ' ' )
- {
- d->fcommand = TRUE;
- stop_idling( d->character );
- if ( d->connected == CON_PLAYING )
- if ( d->showstr_point )
- show_string( d, d->incomm );
- else
- interpret( d->character, d->incomm );
- else
- nanny( d, d->incomm );
- d->incomm[0] = ' ';
- }
- }
- /*
- * Autonomous game motion.
- */
- update_handler( );
- /*
- * Output.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- d_next = d->next;
- if ( ( d->fcommand || d->outtop > 0 ) )
- {
- if ( !process_output( d, TRUE ) )
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- }
- }
- /*
- * Synchronize to a clock.
- * Busy wait (blargh).
- */
- now_time = last_time;
- for ( ; ; )
- {
- int delta;
- #if defined(MSDOS)
- if ( kbhit( ) )
- #endif
- {
- if ( dcon.character != NULL )
- dcon.character->timer = 0;
- if ( !read_from_descriptor( &dcon ) )
- {
- if ( dcon.character != NULL )
- save_char_obj( d->character );
- dcon.outtop = 0;
- close_socket( &dcon );
- }
- #if defined(MSDOS)
- break;
- #endif
- }
- gettimeofday( &now_time, NULL );
- delta = ( now_time.tv_sec - last_time.tv_sec ) * 1000 * 1000
- + ( now_time.tv_usec - last_time.tv_usec );
- if ( delta >= 1000000 / PULSE_PER_SECOND )
- break;
- }
- last_time = now_time;
- current_time = (time_t) last_time.tv_sec;
- }
- return;
- }
- #endif
- #if defined(unix)
- void game_loop_unix( int control )
- {
- static struct timeval null_time;
- struct timeval last_time;
- #ifndef WIN32s
- signal( SIGPIPE, SIG_IGN );
- #endif
- gettimeofday( &last_time, NULL );
- current_time = (time_t) last_time.tv_sec;
- /* Main loop */
- while ( !merc_down )
- {
- fd_set in_set;
- fd_set out_set;
- fd_set exc_set;
- DESCRIPTOR_DATA *d;
- int maxdesc;
- #if defined(MALLOC_DEBUG)
- if ( malloc_verify( ) != 1 )
- abort( );
- #endif
- /*
- * Poll all active descriptors.
- */
- FD_ZERO( &in_set );
- FD_ZERO( &out_set );
- FD_ZERO( &exc_set );
- FD_SET( control, &in_set );
- maxdesc = control;
- for ( d = descriptor_list; d; d = d->next )
- {
- maxdesc = UMAX( maxdesc, d->descriptor );
- FD_SET( d->descriptor, &in_set );
- FD_SET( d->descriptor, &out_set );
- FD_SET( d->descriptor, &exc_set );
- }
- if ( select( maxdesc+1, &in_set, &out_set, &exc_set, &null_time ) < 0 )
- {
- perror( "Game_loop: select: poll" );
- exit( 1 );
- }
- /*
- * New connection?
- */
- if ( FD_ISSET( control, &in_set ) )
- new_descriptor( control );
- /*
- * Kick out the freaky folks.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- d_next = d->next;
- if ( FD_ISSET( d->descriptor, &exc_set ) )
- {
- FD_CLR( d->descriptor, &in_set );
- FD_CLR( d->descriptor, &out_set );
- if ( d->character )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- }
- /*
- * Process input.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- d_next = d->next;
- d->fcommand = FALSE;
- if ( FD_ISSET( d->descriptor, &in_set ) )
- {
- if ( d->character != NULL )
- d->character->timer = 0;
- if ( !read_from_descriptor( d ) )
- {
- FD_CLR( d->descriptor, &out_set );
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- continue;
- }
- }
- if ( d->character != NULL && d->character->wait > 0 )
- {
- --d->character->wait;
- continue;
- }
- read_from_buffer( d );
- if ( d->incomm[0] != ' ' )
- {
- d->fcommand = TRUE;
- stop_idling( d->character );
- if ( d->connected == CON_PLAYING )
- if ( d->showstr_point )
- show_string( d, d->incomm );
- else
- interpret( d->character, d->incomm );
- else
- nanny( d, d->incomm );
- d->incomm[0] = ' ';
- }
- }
- /*
- * Autonomous game motion.
- */
- update_handler( );
- /*
- * Output.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- d_next = d->next;
- if ( ( d->fcommand || d->outtop > 0 )
- && FD_ISSET(d->descriptor, &out_set) )
- {
- if ( !process_output( d, TRUE ) )
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- }
- }
- /*
- * Synchronize to a clock.
- * Sleep( last_time + 1/PULSE_PER_SECOND - now ).
- * Careful here of signed versus unsigned arithmetic.
- */
- {
- struct timeval now_time;
- long secDelta;
- long usecDelta;
- gettimeofday( &now_time, NULL );
- usecDelta = ((int) last_time.tv_usec) - ((int) now_time.tv_usec)
- + 1000000 / PULSE_PER_SECOND;
- secDelta = ((int) last_time.tv_sec ) - ((int) now_time.tv_sec );
- while ( usecDelta < 0 )
- {
- usecDelta += 1000000;
- secDelta -= 1;
- }
- while ( usecDelta >= 1000000 )
- {
- usecDelta -= 1000000;
- secDelta += 1;
- }
- if ( secDelta > 0 || ( secDelta == 0 && usecDelta > 0 ) )
- {
- struct timeval stall_time;
- stall_time.tv_usec = usecDelta;
- stall_time.tv_sec = secDelta;
- if ( select( 0, NULL, NULL, NULL, &stall_time ) < 0 )
- {
- perror( "Game_loop: select: stall" );
- exit( 1 );
- }
- }
- }
- gettimeofday( &last_time, NULL );
- current_time = (time_t) last_time.tv_sec;
- }
- return;
- }
- #endif
- #if defined(unix)
- void new_descriptor( int control )
- {
- static DESCRIPTOR_DATA d_zero;
- char buf[MAX_STRING_LENGTH];
- DESCRIPTOR_DATA *dnew;
- BAN_DATA *pban;
- struct sockaddr_in sock;
- struct hostent *from;
- int desc;
- int size;
- size = sizeof(sock);
- getsockname( control, (struct sockaddr *) &sock, &size );
- if ( ( desc = accept( control, (struct sockaddr *) &sock, &size) ) < 0 )
- {
- perror( "New_descriptor: accept" );
- return;
- }
- #if !defined(FNDELAY)
- #define FNDELAY O_NDELAY
- #endif
- #ifndef WIN32s
- if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 )
- {
- perror( "New_descriptor: fcntl: FNDELAY" );
- return;
- }
- #endif
- /*
- * Cons a new descriptor.
- */
- if ( descriptor_free == NULL )
- {
- dnew = alloc_perm( sizeof(*dnew) );
- }
- else
- {
- dnew = descriptor_free;
- descriptor_free = descriptor_free->next;
- }
- *dnew = d_zero;
- dnew->descriptor = desc;
- dnew->connected = CON_GET_NAME;
- dnew->showstr_head = NULL;
- dnew->showstr_point = NULL;
- dnew->outsize = 2000;
- dnew->outbuf = alloc_mem( dnew->outsize );
- size = sizeof(sock);
- if ( getpeername( desc, (struct sockaddr *) &sock, &size ) < 0 )
- {
- perror( "New_descriptor: getpeername" );
- dnew->host = str_dup( "(unknown)" );
- }
- else
- {
- /*
- * Would be nice to use inet_ntoa here but it takes a struct arg,
- * which ain't very compatible between gcc and system libraries.
- */
- int addr;
- addr = ntohl( sock.sin_addr.s_addr );
- sprintf( buf, "%d.%d.%d.%d",
- ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
- ( addr >> 8 ) & 0xFF, ( addr ) & 0xFF
- );
- sprintf( log_buf, "Sock.sinaddr: %s", buf );
- log_string( log_buf );
- from = gethostbyaddr( (char *) &sock.sin_addr,
- sizeof(sock.sin_addr), AF_INET );
- dnew->host = str_dup( from ? from->h_name : buf );
- }
- /*
- * Swiftest: I added the following to ban sites. I don't
- * endorse banning of sites, but Copper has few descriptors now
- * and some people from certain sites keep abusing access by
- * using automated 'autodialers' and leaving connections hanging.
- *
- * Furey: added suffix check by request of Nickel of HiddenWorlds.
- */
- for ( pban = ban_list; pban != NULL; pban = pban->next )
- {
- if ( str_suffix( pban->name, dnew->host ) )
- {
- write_to_descriptor( desc,
- "Your site has been banned from this Mud.nr", 0 );
- close( desc );
- free_string( dnew->host );
- free_mem( dnew->outbuf, dnew->outsize );
- dnew->next = descriptor_free;
- descriptor_free = dnew;
- return;
- }
- }
- /*
- * Init descriptor data.
- */
- dnew->next = descriptor_list;
- descriptor_list = dnew;
- /*
- * Send the greeting.
- */
- {
- extern char * help_greeting;
- if ( help_greeting[0] == '.' )
- write_to_buffer( dnew, help_greeting+1, 0 );
- else
- write_to_buffer( dnew, help_greeting , 0 );
- }
- return;
- }
- #endif
- void close_socket( DESCRIPTOR_DATA *dclose )
- {
- CHAR_DATA *ch;
- if ( dclose->outtop > 0 )
- process_output( dclose, FALSE );
- if ( dclose->snoop_by != NULL )
- {
- write_to_buffer( dclose->snoop_by,
- "Your victim has left the game.nr", 0 );
- }
- {
- DESCRIPTOR_DATA *d;
- for ( d = descriptor_list; d != NULL; d = d->next )
- {
- if ( d->snoop_by == dclose )
- d->snoop_by = NULL;
- }
- }
- if ( ( ch = dclose->character ) != NULL )
- {
- sprintf( log_buf, "Closing link to %s.", ch->name );
- log_string( log_buf );
- if ( dclose->connected == CON_PLAYING )
- {
- act( "$n has lost $s link.", ch, NULL, NULL, TO_ROOM );
- ch->desc = NULL;
- }
- else
- {
- free_char( dclose->character );
- }
- }
- if ( d_next == dclose )
- d_next = d_next->next;
- if ( dclose == descriptor_list )
- {
- descriptor_list = descriptor_list->next;
- }
- else
- {
- DESCRIPTOR_DATA *d;
- for ( d = descriptor_list; d && d->next != dclose; d = d->next )
- ;
- if ( d != NULL )
- d->next = dclose->next;
- else
- bug( "Close_socket: dclose not found.", 0 );
- }
- close( dclose->descriptor );
- free_string( dclose->host );
- dclose->next = descriptor_free;
- descriptor_free = dclose;
- #if defined(MSDOS) || defined(macintosh)
- exit(1);
- #endif
- return;
- }
- bool read_from_descriptor( DESCRIPTOR_DATA *d )
- {
- int iStart;
- /* Hold horses if pending command already. */
- if ( d->incomm[0] != ' ' )
- return TRUE;
- /* Check for overflow. */
- iStart = strlen(d->inbuf);
- if ( iStart >= sizeof(d->inbuf) - 10 )
- {
- sprintf( log_buf, "%s input overflow!", d->host );
- log_string( log_buf );
- write_to_descriptor( d->descriptor,
- "nr*** PUT A LID ON IT!!! ***nr", 0 );
- return FALSE;
- }
- /* Snarf input. */
- #if defined(macintosh)
- for ( ; ; )
- {
- int c;
- c = getc( stdin );
- if ( c == ' ' || c == EOF )
- break;
- putc( c, stdout );
- if ( c == 'r' )
- putc( 'n', stdout );
- d->inbuf[iStart++] = c;
- if ( iStart > sizeof(d->inbuf) - 10 )
- break;
- }
- #endif
- #if defined(MSDOS) || defined(unix)
- for ( ; ; )
- {
- int nRead;
- nRead = read( d->descriptor, d->inbuf + iStart,
- sizeof(d->inbuf) - 10 - iStart );
- if ( nRead > 0 )
- {
- iStart += nRead;
- if ( d->inbuf[iStart-1] == 'n' || d->inbuf[iStart-1] == 'r' )
- break;
- }
- else if ( nRead == 0 )
- {
- log_string( "EOF encountered on read." );
- return FALSE;
- }
- else if ( errno == EWOULDBLOCK )
- break;
- else
- {
- perror( "Read_from_descriptor" );
- return FALSE;
- }
- }
- #endif
- d->inbuf[iStart] = ' ';
- return TRUE;
- }
- /*
- * Transfer one line from input buffer to input line.
- */
- void read_from_buffer( DESCRIPTOR_DATA *d )
- {
- int i, j, k;
- /*
- * Hold horses if pending command already.
- */
- if ( d->incomm[0] != ' ' )
- return;
- /*
- * Look for at least one new line.
- */
- for ( i = 0; d->inbuf[i] != 'n' && d->inbuf[i] != 'r'; i++ )
- {
- if ( d->inbuf[i] == ' ' )
- return;
- }
- /*
- * Canonical input processing.
- */
- for ( i = 0, k = 0; d->inbuf[i] != 'n' && d->inbuf[i] != 'r'; i++ )
- {
- if ( k >= MAX_INPUT_LENGTH - 2 )
- {
- write_to_descriptor( d->descriptor, "Line too long.nr", 0 );
- /* skip the rest of the line */
- for ( ; d->inbuf[i] != ' '; i++ )
- {
- if ( d->inbuf[i] == 'n' || d->inbuf[i] == 'r' )
- break;
- }
- d->inbuf[i] = 'n';
- d->inbuf[i+1] = ' ';
- break;
- }
- if ( d->inbuf[i] == 'b' && k > 0 )
- --k;
- else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) )
- d->incomm[k++] = d->inbuf[i];
- }
- /*
- * Finish off the line.
- */
- if ( k == 0 )
- d->incomm[k++] = ' ';
- d->incomm[k] = ' ';
- /*
- * Deal with bozos with #repeat 1000 ...
- */
- if ( k > 1 || d->incomm[0] == '!' )
- {
- if ( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) )
- {
- d->repeat = 0;
- }
- else
- {
- if ( ++d->repeat >= 20 )
- {
- sprintf( log_buf, "%s input spamming!", d->host );
- log_string( log_buf );
- write_to_descriptor( d->descriptor,
- "nr*** PUT A LID ON IT!!! ***nr", 0 );
- strcpy( d->incomm, "quit" );
- }
- }
- }
- /*
- * Do '!' substitution.
- */
- if ( d->incomm[0] == '!' )
- strcpy( d->incomm, d->inlast );
- else
- strcpy( d->inlast, d->incomm );
- /*
- * Shift the input buffer.
- */
- while ( d->inbuf[i] == 'n' || d->inbuf[i] == 'r' )
- i++;
- for ( j = 0; ( d->inbuf[j] = d->inbuf[i+j] ) != ' '; j++ )
- ;
- return;
- }
- /*
- * Low level output function.
- */
- bool process_output( DESCRIPTOR_DATA *d, bool fPrompt )
- {
- extern bool merc_down;
- /*
- * Bust a prompt.
- */
- if ( fPrompt && !merc_down && d->connected == CON_PLAYING )
- if ( d->showstr_point )
- write_to_buffer( d,
- "[Please type (c)ontinue, (r)efresh, (b)ack, (h)elp, (q)uit, or RETURN]: ",
- 0 );
- else
- {
- CHAR_DATA *ch;
- ch = d->original ? d->original : d->character;
- if ( IS_SET(ch->act, PLR_BLANK) )
- write_to_buffer( d, "nr", 2 );
- if ( IS_SET(ch->act, PLR_PROMPT) )
- bust_a_prompt( ch );
- if ( IS_SET(ch->act, PLR_TELNET_GA) )
- write_to_buffer( d, go_ahead_str, 0 );
- }
- /*
- * Short-circuit if nothing to write.
- */
- if ( d->outtop == 0 )
- return TRUE;
- /*
- * Snoop-o-rama.
- */
- if ( d->snoop_by != NULL )
- {
- write_to_buffer( d->snoop_by, "% ", 2 );
- write_to_buffer( d->snoop_by, d->outbuf, d->outtop );
- }
- /*
- * OS-dependent output.
- */
- if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) )
- {
- d->outtop = 0;
- return FALSE;
- }
- else
- {
- d->outtop = 0;
- return TRUE;
- }
- }
- /*
- * Bust a prompt (player settable prompt)
- * coded by Morgenes for Aldara Mud
- */
- void bust_a_prompt( CHAR_DATA *ch )
- {
- char buf[MAX_STRING_LENGTH];
- char buf2[MAX_STRING_LENGTH];
- const char *str;
- const char *i;
- char *point;
- if( ch->prompt == NULL || ch->prompt[0] == ' ' )
- {
- send_to_char( "nrnr", ch );
- return;
- }
- point = buf;
- str = ch->prompt;
- while( *str != ' ' )
- {
- if( *str != '%' )
- {
- *point++ = *str++;
- continue;
- }
- ++str;
- switch( *str )
- {
- default :
- i = " "; break;
- case 'h' :
- sprintf( buf2, "%d", ch->hit );
- i = buf2; break;
- case 'H' :
- sprintf( buf2, "%d", ch->max_hit );
- i = buf2; break;
- case 'm' :
- sprintf( buf2, "%d", ch->mana );
- i = buf2; break;
- case 'M' :
- sprintf( buf2, "%d", ch->max_mana );
- i = buf2; break;
- case 'v' :
- sprintf( buf2, "%d", ch->move );
- i = buf2; break;
- case 'V' :
- sprintf( buf2, "%d", ch->max_move );
- i = buf2; break;
- case 'x' :
- sprintf( buf2, "%d", ch->exp );
- i = buf2; break;
- case 'g' :
- sprintf( buf2, "%d", ch->gold);
- i = buf2; break;
- case 'a' :
- if( ch->level < 5 )
- sprintf( buf2, "%d", ch->alignment );
- else
- sprintf( buf2, "%s", IS_GOOD(ch) ? "good" : IS_EVIL(ch) ?
- "evil" : "neutral" );
- i = buf2; break;
- case 'r' :
- if( ch->in_room != NULL )
- sprintf( buf2, "%s", ch->in_room->name );
- else
- sprintf( buf2, " " );
- i = buf2; break;
- case 'R' :
- if( IS_IMMORTAL( ch ) && ch->in_room != NULL )
- sprintf( buf2, "%d", ch->in_room->vnum );
- else
- sprintf( buf2, " " );
- i = buf2; break;
- case 'z' :
- if( IS_IMMORTAL( ch ) && ch->in_room != NULL )
- sprintf( buf2, "%s", ch->in_room->area->name );
- else
- sprintf( buf2, " " );
- i = buf2; break;
- case '%' :
- sprintf( buf2, "%%" );
- i = buf2; break;
- }
- ++str;
- while( (*point = *i) != ' ' )
- ++point, ++i;
- }
- write_to_buffer( ch->desc, buf, point - buf );
- return;
- }
- /*
- * Append onto an output buffer.
- */
- void write_to_buffer( DESCRIPTOR_DATA *d, const char *txt, int length )
- {
- /*
- * Find length in case caller didn't.
- */
- if ( length <= 0 )
- length = strlen(txt);
- /*
- * Initial nr if needed.
- */
- if ( d->outtop == 0 && !d->fcommand )
- {
- d->outbuf[0] = 'n';
- d->outbuf[1] = 'r';
- d->outtop = 2;
- }
- /*
- * Expand the buffer as needed.
- */
- while ( d->outtop + length >= d->outsize )
- {
- char *outbuf;
- outbuf = alloc_mem( 2 * d->outsize );
- strncpy( outbuf, d->outbuf, d->outtop );
- free_mem( d->outbuf, d->outsize );
- d->outbuf = outbuf;
- d->outsize *= 2;
- }
- /*
- * Copy.
- */
- strcpy( d->outbuf + d->outtop, txt );
- d->outtop += length;
- return;
- }
- /*
- * Lowest level output function.
- * Write a block of text to the file descriptor.
- * If this gives errors on very long blocks (like 'ofind all'),
- * try lowering the max block size.
- */
- bool write_to_descriptor( int desc, char *txt, int length )
- {
- int iStart;
- int nWrite;
- int nBlock;
- #if defined(macintosh) || defined(MSDOS)
- if ( desc == 0 )
- desc = 1;
- #endif
- if ( length <= 0 )
- length = strlen(txt);
- for ( iStart = 0; iStart < length; iStart += nWrite )
- {
- nBlock = UMIN( length - iStart, 4096 );
- if ( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 )
- { perror( "Write_to_descriptor" ); return FALSE; }
- }
- return TRUE;
- }
- /*
- * Deal with sockets that haven't logged in yet.
- */
- void nanny( DESCRIPTOR_DATA *d, char *argument )
- {
- char buf[MAX_STRING_LENGTH];
- CHAR_DATA *ch;
- NOTE_DATA *pnote;
- char *pwdnew;
- char *p;
- int iClass;
- int lines;
- int notes;
- bool fOld;
- while ( isspace(*argument) )
- argument++;
- ch = d->character;
- switch ( d->connected )
- {
- default:
- bug( "Nanny: bad d->connected %d.", d->connected );
- close_socket( d );
- return;
- case CON_GET_NAME:
- if ( argument[0] == ' ' )
- {
- close_socket( d );
- return;
- }
- argument[0] = UPPER(argument[0]);
- if ( !check_parse_name( argument ) )
- {
- write_to_buffer( d, "Illegal name, try another.nrName: ", 0 );
- return;
- }
- fOld = load_char_obj( d, argument );
- ch = d->character;
- if ( IS_SET(ch->act, PLR_DENY) )
- {
- sprintf( log_buf, "Denying access to %s@%s.", argument, d->host );
- log_string( log_buf );
- write_to_buffer( d, "You are denied access.nr", 0 );
- close_socket( d );
- return;
- }
- if ( check_reconnect( d, argument, FALSE ) )
- {
- fOld = TRUE;
- }
- else
- {
- if ( wizlock && !IS_HERO( ch ) && !ch->wizbit )
- {
- write_to_buffer( d, "The game is wizlocked.nr", 0 );
- close_socket( d );
- return;
- }
- }
- if ( fOld )
- {
- /* Old player */
- write_to_buffer( d, "Password: ", 0 );
- write_to_buffer( d, echo_off_str, 0 );
- d->connected = CON_GET_OLD_PASSWORD;
- return;
- }
- else
- {
- /* New player */
- /* New characters with same name fix by Salem's Lot */
- if ( check_playing( d, ch->name ) )
- return;
- sprintf( buf, "Did I get that right, %s (Y/N)? ", argument );
- write_to_buffer( d, buf, 0 );
- d->connected = CON_CONFIRM_NEW_NAME;
- return;
- }
- break;
- case CON_GET_OLD_PASSWORD:
- #if defined(unix)
- write_to_buffer( d, "nr", 2 );
- #endif
- if ( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
- {
- write_to_buffer( d, "Wrong password.nr", 0 );
- close_socket( d );
- return;
- }
- write_to_buffer( d, echo_on_str, 0 );
- if ( check_reconnect( d, ch->name, TRUE ) )
- return;
- if ( check_playing( d, ch->name ) )
- return;
- sprintf( log_buf, "%s@%s has connected.", ch->name, d->host );
- log_string( log_buf );
- lines = ch->pcdata->pagelen;
- ch->pcdata->pagelen = 20;
- if ( IS_HERO(ch) )
- do_help( ch, "imotd" );
- do_help( ch, "motd" );
- ch->pcdata->pagelen = lines;
- d->connected = CON_READ_MOTD;
- break;
- case CON_CONFIRM_NEW_NAME:
- switch ( *argument )
- {
- case 'y': case 'Y':
- sprintf( buf, "New character.nrGive me a password for %s: %s",
- ch->name, echo_off_str );
- write_to_buffer( d, buf, 0 );
- d->connected = CON_GET_NEW_PASSWORD;
- break;
- case 'n': case 'N':
- write_to_buffer( d, "Ok, what IS it, then? ", 0 );
- free_char( d->character );
- d->character = NULL;
- d->connected = CON_GET_NAME;
- break;
- default:
- write_to_buffer( d, "Please type Yes or No? ", 0 );
- break;
- }
- break;
- case CON_GET_NEW_PASSWORD:
- #if defined(unix)
- write_to_buffer( d, "nr", 2 );
- #endif
- if ( strlen(argument) < 5 )
- {
- write_to_buffer( d,
- "Password must be at least five characters long.nrPassword: ",
- 0 );
- return;
- }
- pwdnew = crypt( argument, ch->name );
- for ( p = pwdnew; *p != ' '; p++ )
- {
- if ( *p == '~' )
- {
- write_to_buffer( d,
- "New password not acceptable, try again.nrPassword: ",
- 0 );
- return;
- }
- }
- free_string( ch->pcdata->pwd );
- ch->pcdata->pwd = str_dup( pwdnew );
- write_to_buffer( d, "Please retype password: ", 0 );
- d->connected = CON_CONFIRM_NEW_PASSWORD;
- break;
- case CON_CONFIRM_NEW_PASSWORD:
- #if defined(unix)
- write_to_buffer( d, "nr", 2 );
- #endif
- if ( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
- {
- write_to_buffer( d, "Passwords don't match.nrRetype password: ",
- 0 );
- d->connected = CON_GET_NEW_PASSWORD;
- return;
- }
- write_to_buffer( d, echo_on_str, 0 );
- write_to_buffer( d, "What is your sex (M/F/N)? ", 0 );
- d->connected = CON_GET_NEW_SEX;
- break;
- case CON_GET_NEW_SEX:
- switch ( argument[0] )
- {
- case 'm': case 'M': ch->sex = SEX_MALE; break;
- case 'f': case 'F': ch->sex = SEX_FEMALE; break;
- case 'n': case 'N': ch->sex = SEX_NEUTRAL; break;
- default:
- write_to_buffer( d, "That's not a sex.nrWhat IS your sex? ", 0 );
- return;
- }
- strcpy( buf, "Select a class [" );
- for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
- {
- if ( iClass > 0 )
- strcat( buf, " " );
- strcat( buf, class_table[iClass].who_name );
- }
- strcat( buf, "]: " );
- write_to_buffer( d, buf, 0 );
- d->connected = CON_GET_NEW_CLASS;
- break;
- case CON_GET_NEW_CLASS:
- for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
- {
- if ( !str_cmp( argument, class_table[iClass].who_name ) )
- {
- ch->class = iClass;
- break;
- }
- }
- if ( iClass == MAX_CLASS )
- {
- write_to_buffer( d,
- "That's not a class.nrWhat IS your class? ", 0 );
- return;
- }
- sprintf( log_buf, "%s@%s new player.", ch->name, d->host );
- log_string( log_buf );
- write_to_buffer( d, "nr", 2 );
- ch->pcdata->pagelen = 20;
- ch->prompt = "<%hhp %mm %vmv> ";
- do_help( ch, "motd" );
- d->connected = CON_READ_MOTD;
- break;
- case CON_READ_MOTD:
- ch->next = char_list;
- char_list = ch;
- d->connected = CON_PLAYING;
- send_to_char(
- "nrWelcome to Merc Diku Mud. May your visit here be ... Mercenary.nr",
- ch );
- if ( ch->level == 0 )
- {
- OBJ_DATA *obj;
- switch ( class_table[ch->class].attr_prime )
- {
- case APPLY_STR: ch->pcdata->perm_str = 16; break;
- case APPLY_INT: ch->pcdata->perm_int = 16; break;
- case APPLY_WIS: ch->pcdata->perm_wis = 16; break;
- case APPLY_DEX: ch->pcdata->perm_dex = 16; break;
- case APPLY_CON: ch->pcdata->perm_con = 16; break;
- }
- ch->level = 1;
- ch->exp = 1000;
- ch->hit = ch->max_hit;
- ch->mana = ch->max_mana;
- ch->move = ch->max_move;
- sprintf( buf, "the %s",
- title_table [ch->class] [ch->level]
- [ch->sex == SEX_FEMALE ? 1 : 0] );
- set_title( ch, buf );
- obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_BANNER), 0 );
- obj_to_char( obj, ch );
- equip_char( ch, obj, WEAR_LIGHT );
- obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_VEST), 0 );
- obj_to_char( obj, ch );
- equip_char( ch, obj, WEAR_BODY );
- obj = create_object( get_obj_index(OBJ_VNUM_SCHOOL_SHIELD), 0 );
- obj_to_char( obj, ch );
- equip_char( ch, obj, WEAR_SHIELD );
- obj = create_object( get_obj_index(class_table[ch->class].weapon),
- 0 );
- obj_to_char( obj, ch );
- equip_char( ch, obj, WEAR_WIELD );
- char_to_room( ch, get_room_index( ROOM_VNUM_SCHOOL ) );
- }
- else if ( ch->in_room != NULL )
- {
- char_to_room( ch, ch->in_room );
- }
- else if ( IS_IMMORTAL(ch) )
- {
- char_to_room( ch, get_room_index( ROOM_VNUM_CHAT ) );
- }
- else
- {
- char_to_room( ch, get_room_index( ROOM_VNUM_TEMPLE ) );
- }
- act( "$n has entered the game.", ch, NULL, NULL, TO_ROOM );
- do_look( ch, "auto" );
- /* check for new notes */
- notes = 0;
- for ( pnote = note_list; pnote != NULL; pnote = pnote->next )
- if ( is_note_to( ch, pnote ) && str_cmp( ch->name, pnote->sender )
- && pnote->date_stamp > ch->last_note )
- notes++;
- if ( notes == 1 )
- send_to_char( "nrYou have one new note waiting.nr", ch );
- else
- if ( notes > 1 )
- {
- sprintf( buf, "nrYou have %d new notes waiting.nr",
- notes );
- send_to_char( buf, ch );
- }
- break;
- }
- return;
- }
- /*
- * Parse a name for acceptability.
- */
- bool check_parse_name( char *name )
- {
- /*
- * Reserved words.
- */
- if ( is_name( name, "all auto immortal self someone" ) )
- return FALSE;
- /*
- * Length restrictions.
- */
- if ( strlen(name) < 3 )
- return FALSE;
- #if defined(MSDOS)
- if ( strlen(name) > 8 )
- return FALSE;
- #endif
- #if defined(macintosh) || defined(unix)
- if ( strlen(name) > 12 )
- return FALSE;
- #endif
- /*
- * Alphanumerics only.
- * Lock out IllIll twits.
- */
- {
- char *pc;
- bool fIll;
- fIll = TRUE;
- for ( pc = name; *pc != ' '; pc++ )
- {
- if ( !isalpha(*pc) )
- return FALSE;
- if ( LOWER(*pc) != 'i' && LOWER(*pc) != 'l' )
- fIll = FALSE;
- }
- if ( fIll )
- return FALSE;
- }
- /*
- * Prevent players from naming themselves after mobs.
- */
- {
- extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
- MOB_INDEX_DATA *pMobIndex;
- int iHash;
- for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
- {
- for ( pMobIndex = mob_index_hash[iHash];
- pMobIndex != NULL;
- pMobIndex = pMobIndex->next )
- {
- if ( is_name( name, pMobIndex->player_name ) )
- return FALSE;
- }
- }
- }
- return TRUE;
- }
- /*
- * Look for link-dead player to reconnect.
- */
- bool check_reconnect( DESCRIPTOR_DATA *d, char *name, bool fConn )
- {
- CHAR_DATA *ch;
- OBJ_DATA *obj;
- for ( ch = char_list; ch != NULL; ch = ch->next )
- {
- if ( !IS_NPC(ch)
- && ( !fConn || ch->desc == NULL )
- && !str_cmp( d->character->name, ch->name ) )
- {
- if ( fConn == FALSE )
- {
- free_string( d->character->pcdata->pwd );
- d->character->pcdata->pwd = str_dup( ch->pcdata->pwd );
- }
- else
- {
- free_char( d->character );
- d->character = ch;
- ch->desc = d;
- ch->timer = 0;
- send_to_char( "Reconnecting.nr", ch );
- act( "$n has reconnected.", ch, NULL, NULL, TO_ROOM );
- sprintf( log_buf, "%s@%s reconnected.", ch->name, d->host );
- log_string( log_buf );
- d->connected = CON_PLAYING;
- /*
- * Contributed by Gene Choi
- */
- if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL
- && obj->item_type == ITEM_LIGHT
- && obj->value[2] != 0
- && ch->in_room != NULL )
- ++ch->in_room->light;
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- /*
- * Check if already playing.
- */
- bool check_playing( DESCRIPTOR_DATA *d, char *name )
- {
- DESCRIPTOR_DATA *dold;
- for ( dold = descriptor_list; dold; dold = dold->next )
- {
- if ( dold != d
- && dold->character != NULL
- && dold->connected != CON_GET_NAME
- && dold->connected != CON_GET_OLD_PASSWORD
- && !str_cmp( name, dold->original
- ? dold->original->name : dold->character->name ) )
- {
- write_to_buffer( d, "Already playing.nrName: ", 0 );
- d->connected = CON_GET_NAME;
- if ( d->character != NULL )
- {
- free_char( d->character );
- d->character = NULL;
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- void stop_idling( CHAR_DATA *ch )
- {
- if ( ch == NULL
- || ch->desc == NULL
- || ch->desc->connected != CON_PLAYING
- || ch->was_in_room == NULL
- || ch->in_room != get_room_index( ROOM_VNUM_LIMBO ) )
- return;
- ch->timer = 0;
- char_from_room( ch );
- char_to_room( ch, ch->was_in_room );
- ch->was_in_room = NULL;
- act( "$n has returned from the void.", ch, NULL, NULL, TO_ROOM );
- return;
- }
- /*
- * Write to one char.
- */
- void send_to_char( const char *txt, CHAR_DATA *ch )
- {
- if ( txt == NULL || ch->desc == NULL )
- return;
- ch->desc->showstr_head = alloc_mem( strlen( txt ) + 1 );
- strcpy( ch->desc->showstr_head, txt );
- ch->desc->showstr_point = ch->desc->showstr_head;
- show_string( ch->desc, "" );
- }
- /* The heart of the pager. Thanks to N'Atas-Ha, ThePrincedom
- for porting this SillyMud code for MERC 2.0 and laying down the groundwork.
- Thanks to Blackstar, hopper.cs.uiowa.edu 4000 for which
- the improvements to the pager was modeled from. - Kahn */
- void show_string(struct descriptor_data *d, char *input)
- {
- char buffer[ MAX_STRING_LENGTH ];
- char buf[ MAX_INPUT_LENGTH ];
- register char *scan, *chk;
- int lines = 0, toggle=1;
- one_argument(input, buf);
- switch( UPPER( buf[0] ) )
- {
- case ' ':
- case 'C': /* show next page of text */
- lines = 0;
- break;
- case 'R': /* refresh current page of text */
- lines = - 1 - (d->character->pcdata->pagelen);
- break;
- case 'B': /* scroll back a page of text */
- lines = -(2*d->character->pcdata->pagelen);
- break;
- case 'H': /* Show some help */
- write_to_buffer( d,
- "C, or Return = continue, R = redraw this page,nr", 0 );
- write_to_buffer( d,
- "B = back one page, H = this help, Q or other keys = exit.nrnr",
- 0 );
- lines = - 1 - (d->character->pcdata->pagelen);
- break;
- default: /*otherwise, stop the text viewing */
- if ( d->showstr_head )
- {
- free_string( d->showstr_head );
- d->showstr_head = 0;
- }
- d->showstr_point = 0;
- return;
- }
- /* do any backing up necessary */
- if (lines < 0)
- {
- for ( scan = d->showstr_point; scan > d->showstr_head; scan-- )
- if ( ( *scan == 'n' ) || ( *scan == 'r' ) )
- {
- toggle = -toggle;
- if ( toggle < 0 )
- if ( !( ++lines ) )
- break;
- }
- d->showstr_point = scan;
- }
- /* show a chunk */
- lines = 0;
- toggle = 1;
- for ( scan = buffer; ; scan++, d->showstr_point++ )
- if ( ( ( *scan = *d->showstr_point ) == 'n' || *scan == 'r' )
- && ( toggle = -toggle ) < 0 )
- lines++;
- else
- if ( !*scan || ( d->character && !IS_NPC( d->character )
- && lines >= d->character->pcdata->pagelen) )
- {
- *scan = ' ';
- write_to_buffer( d, buffer, strlen( buffer ) );
- /* See if this is the end (or near the end) of the string */
- for ( chk = d->showstr_point; isspace( *chk ); chk++ );
- if ( !*chk )
- {
- if ( d->showstr_head )
- {
- free_string( d->showstr_head );
- d->showstr_head = 0;
- }
- d->showstr_point = 0;
- }
- return;
- }
- return;
- }
- /*
- * The primary output interface for formatted output.
- */
- void act( const char *format, CHAR_DATA *ch, const void *arg1,
- const void *arg2, int type )
- {
- static char * const he_she [] = { "it", "he", "she" };
- static char * const him_her [] = { "it", "him", "her" };
- static char * const his_her [] = { "its", "his", "her" };
- char buf[MAX_STRING_LENGTH];
- char fname[MAX_INPUT_LENGTH];
- CHAR_DATA *to;
- CHAR_DATA *vch = (CHAR_DATA *) arg2;
- OBJ_DATA *obj1 = (OBJ_DATA *) arg1;
- OBJ_DATA *obj2 = (OBJ_DATA *) arg2;
- const char *str;
- const char *i;
- char *point;
- /*
- * Discard null and zero-length messages.
- */
- if ( format == NULL || format[0] == ' ' )
- return;
- to = ch->in_room->people;
- if ( type == TO_VICT )
- {
- if ( vch == NULL )
- {
- bug( "Act: null vch with TO_VICT.", 0 );
- return;
- }
- to = vch->in_room->people;
- }
- for ( ; to != NULL; to = to->next_in_room )
- {
- if ( ( to->desc == NULL
- && ( IS_NPC( to ) && !(to->pIndexData->progtypes & ACT_PROG ) ) )
- || !IS_AWAKE(to) )
- continue;
- if ( type == TO_CHAR && to != ch )
- continue;
- if ( type == TO_VICT && ( to != vch || to == ch ) )
- continue;
- if ( type == TO_ROOM && to == ch )
- continue;
- if ( type == TO_NOTVICT && (to == ch || to == vch) )
- continue;
- point = buf;
- str = format;
- while ( *str != ' ' )
- {
- if ( *str != '$' )
- {
- *point++ = *str++;
- continue;
- }
- ++str;
- if ( arg2 == NULL && *str >= 'A' && *str <= 'Z' )
- {
- bug( "Act: missing arg2 for code %d.", *str );
- i = " <@@@> ";
- }
- else
- {
- switch ( *str )
- {
- default: bug( "Act: bad code %d.", *str );
- i = " <@@@> "; break;
- /* Thx alex for 't' idea */
- case 't': i = (char *) arg1; break;
- case 'T': i = (char *) arg2; break;
- case 'n': i = PERS( ch, to ); break;
- case 'N': i = PERS( vch, to ); break;
- case 'e': i = he_she [URANGE(0, ch ->sex, 2)]; break;
- case 'E': i = he_she [URANGE(0, vch ->sex, 2)]; break;
- case 'm': i = him_her [URANGE(0, ch ->sex, 2)]; break;
- case 'M': i = him_her [URANGE(0, vch ->sex, 2)]; break;
- case 's': i = his_her [URANGE(0, ch ->sex, 2)]; break;
- case 'S': i = his_her [URANGE(0, vch ->sex, 2)]; break;
- case 'p':
- i = can_see_obj( to, obj1 )
- ? obj1->short_descr
- : "something";
- break;
- case 'P':
- i = can_see_obj( to, obj2 )
- ? obj2->short_descr
- : "something";
- break;
- case 'd':
- if ( arg2 == NULL || ((char *) arg2)[0] == ' ' )
- {
- i = "door";
- }
- else
- {
- one_argument( (char *) arg2, fname );
- i = fname;
- }
- break;
- }
- }
- ++str;
- while ( ( *point = *i ) != ' ' )
- ++point, ++i;
- }
- *point++ = 'n';
- *point++ = 'r';
- buf[0] = UPPER(buf[0]);
- if (to->desc)
- write_to_buffer( to->desc, buf, point - buf );
- if (MOBtrigger)
- mprog_act_trigger( buf, to, ch, obj1, vch );
- /* Added by Kahn */
- }
- MOBtrigger = TRUE;
- return;
- }
- /*
- * Macintosh support functions.
- */
- #if defined(macintosh)
- int gettimeofday( struct timeval *tp, void *tzp )
- {
- tp->tv_sec = time( NULL );
- tp->tv_usec = 0;
- }
- #endif