📄 comm.c
字号:
/***************************************************************************
* 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 [] = { '\0' };
const char echo_on_str [] = { '\0' };
const char go_ahead_str [] = { '\0' };
#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, '\0' };
const char echo_on_str [] = { IAC, WONT, TELOPT_ECHO, '\0' };
const char go_ahead_str [] = { IAC, GA, '\0' };
#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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -