WSCKCOMM.C
资源名称:mercwsrc.zip [点击查看]
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:74k
源码类别:
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. *
- * *
- * Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David *
- * Love, Guilherme 'Willie' Arnold, and Mitchell Tse. *
- * *
- * Windows sockets port by Slash. *
- * *
- * In order to use any part of this Envy Diku Mud, you must comply with *
- * the original Diku license in 'license.doc', the Merc license in *
- * 'license.txt', as well as the Envy license in 'license.nvy'. *
- * 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. *
- ***************************************************************************/
- #include <time.h>
- #include <stdio.h>
- #include <stdlib.h>
- //#include "telnet.h"
- #include "merc.h"
- #include "merc-win.rh"
- #include <windows.h>
- // Yes, we want mobprogram support
- #define MOBPROGS
- // Yes, we want support for Merc 2.2 for Windows additions
- #define MERCW32
- #define STDERR_FILE "stderr.txt" /* For what Unix writes to standard error */
- /*
- * Definitions for the TELNET protocol.
- */
- #define IAC 255 /* interpret as command: */
- #define WONT 252 /* I won't use option */
- #define WILL 251 /* I will use option */
- #define GA 249 /* you may reverse the line */
- /* telnet options */
- #define TELOPT_ECHO 1 /* echo */
- struct host_and_name_lookup {
- // These are used by WSAAsyncGetHostByAddr()
- char hostdata[MAXGETHOSTSTRUCT];
- HANDLE hRequestHandle;
- struct in_addr sin_addr;
- // These are used by the identd stuff
- char username[64];
- SOCKET sAuth;
- struct sockaddr_in authsock; // Address of the authentication
- struct sockaddr_in us; // Address of our socket to this player
- struct sockaddr_in them; // Address of our socket to this player
- };
- /* Local #defines for Win32 */
- //#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | (((WORD)((BYTE)(b))) << 8)))
- #define WM_NET_ACCEPT (WM_USER+500)
- #define WM_NET_READWRITE (WM_USER+501)
- #define WM_NET_GETHOST (WM_USER+502)
- #define WM_NET_AUTHCONNECT (WM_USER+503)
- /*
- * 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 */
- int numlock = 0; /* Game is numlocked at <level> (ENVY) */
- char str_boot_time[MAX_INPUT_LENGTH];
- time_t current_time; /* Time of this pulse */
- /* Windows version variables */
- SOCKET control;
- int nPlayers = 0;
- int nOldPlayers = 0;
- FILE *fpStderr;
- BOOL fWantsMessageBox = TRUE; // if TRUE, bring up message box on bugs, else log
- /*
- * 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 ) );
- void bust_a_prompt args( ( DESCRIPTOR_DATA *d ) );
- // @@@ My junk
- //char UserMessage[512];
- //BOOL fUserReady;
- 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, ' ' };
- bool write_to_descriptor args( ( int desc, char *txt, int length ) );
- bool BlastedTrumpet(SOCKET sSocket);
- LRESULT SocketAccept (WPARAM /*wParam*/, LPARAM lParam);
- LRESULT SocketReadWrite (WPARAM wParam, LPARAM lParam);
- LRESULT SocketGetHost(WPARAM wParam, LPARAM lParam);
- LRESULT SocketAuthConnect(WPARAM wParam, LPARAM lParam);
- SOCKET init_socket( int port );
- bool read_from_descriptor( DESCRIPTOR_DATA *d );
- void send_to_char args( ( const char *txt, CHAR_DATA *ch ) )
- {
- if ( txt == NULL || ch->desc == NULL )
- return;
- free_string( ch->desc->showstr_head );
- #if 0 // @@@ The next line is from sands, it seems wrong
- ch->desc->showstr_head = str_dup( txt );
- #else
- ch->desc->showstr_head = alloc_mem( strlen( txt ) + 1 );
- strcpy( ch->desc->showstr_head, txt );
- #endif
- ch->desc->showstr_point = ch->desc->showstr_head;
- show_string( ch->desc, "" );
- }
- void gettimeofday( struct timeval *tp, void *tzp )
- {
- tp->tv_sec = time( NULL );
- tp->tv_usec = 0;
- }
- #if 0 // @@@
- 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;
- }
- #if 0
- /* Snarf input. */
- 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;
- }
- #else
- if (fUserReady)
- {
- int nLen = strlen(UserMessage);
- fUserReady = FALSE;
- if (iStart + nLen <= sizeof d->inbuf - 10)
- {
- memcpy(d->inbuf + iStart, UserMessage, nLen);
- iStart += nLen;
- d->inbuf[iStart++] = 'r';
- }
- }
- #endif
- d->inbuf[iStart] = ' ';
- return TRUE;
- }
- #endif
- /*
- * 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;
- }
- void CloseMerc(void)
- {
- }
- HINSTANCE hInst;
- HWND hQryDlgBox; // handle of modeless dialog box
- HWND hWndMain;
- HWND hWndOutput;
- //char UserMessage[512];
- //bool fUserReady;
- LRESULT CALLBACK _export MercWndProc(HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam)
- {
- switch (message)
- {
- case WM_MOVE:
- // Move the dialog box on top of our main window every
- // time the main window moves.
- if (IsWindow(hQryDlgBox))
- SendMessage(hQryDlgBox, message, wParam, lParam);
- break;
- case WM_SETFOCUS:
- // Always set the input focus to the dialog box.
- if (IsWindow(hQryDlgBox))
- SendMessage(hQryDlgBox, message, wParam, lParam);
- break;
- case WM_CLOSE:
- // Tell windows to destroy our window.
- DestroyWindow(hWnd);
- break;
- case WM_QUERYENDSESSION:
- // If we return TRUE we are saying it's ok with us to end the
- // windows session.
- return((long) TRUE); // we agree to end session.
- case WM_ENDSESSION:
- // If wParam is not zero, it meany every application said ok
- // to WM_QUERYENDSESSION messages, so we are really ending.
- if (wParam) // if all apps aggreed to end session.
- CloseMerc(); // This is the end. We will not get a
- // WM_DESTROY message on end session.
- break;
- case WM_DESTROY:
- // This is the end if we were closed by a DestroyWindow call.
- CloseMerc();
- PostQuitMessage(0);
- break;
- default:
- return(DefWindowProc(hWnd, message, wParam, lParam));
- }
- return(0L);
- }
- BOOL CALLBACK _export MercDlgProc(HWND hDlg, UINT message,
- WPARAM wParam, LPARAM lParam)
- {
- static RECT wrect;
- int x, y, w, h, i;
- long rc;
- // char *cp, *cpd, tmp[30], sdrives[30];
- // HANDLE hCursor;
- HWND hWndInput;
- switch (message)
- {
- case WM_INITDIALOG:
- // Save the handle of this proc for use by main window proc.
- hQryDlgBox = hDlg;
- // Save the handle to the output window
- hWndOutput = GetDlgItem(hDlg, 102);
- // SendMessage(hWndOutput, WM_SETFONT,
- // (WPARAM) GetStockObject(SYSTEM_FIXED_FONT), 0);
- SetFocus(GetDlgItem(hDlg, 101));
- // Get position of dialog box window.
- GetWindowRect(hDlg, (LPRECT) &wrect);
- w = wrect.right - wrect.left;
- h = wrect.bottom - wrect.top;
- // Move main application window to same position.
- SetWindowPos(hWndMain, hDlg,
- wrect.left, wrect.top, w, h,
- 0);
- // Tell Winsock we are listening for accepted sockets
- WSAAsyncSelect(control, hDlg, WM_NET_ACCEPT, FD_ACCEPT);
- break;
- case WM_MOVE:
- // Always keep this dialog box on top of main window.
- GetWindowRect(hWndMain, (LPRECT) &wrect);
- x = wrect.left;
- y = wrect.top;
- w = wrect.right - wrect.left;
- h = wrect.bottom - wrect.top;
- MoveWindow(hDlg, x, y, w, h, 1);
- break;
- case WM_SYSCOMMAND:
- // Pass WM_SYSCOMMAND messages on to main window so both
- // main window and dialog box get iconized, minimized etc.
- // in parallel.
- SendMessage(hWndMain, message, wParam, lParam);
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- #if 0 // @@@
- case IDOK:
- hWndInput = GetDlgItem(hDlg, 101);
- SendMessage(hWndInput, WM_GETTEXT, sizeof UserMessage, (LPARAM) UserMessage);
- SendMessage(hWndInput, WM_SETTEXT, 0, (LPARAM) "");
- SetFocus(hWndInput);
- fUserReady = TRUE;
- break;
- #endif
- case IDCANCEL: // Cancel button
- // Tell main application window we want to quit.
- SendMessage(hWndMain, WM_CLOSE, 0, 0L);
- break;
- default:
- break;
- }
- break;
- case WM_CLOSE:
- // Unlock dialog resource we locked above.
- // Zero handle to this dialog window.
- hQryDlgBox = 0;
- // Tell main window to close.
- PostMessage(hWndMain, WM_CLOSE, 0, 0L);
- // Destroy ourseleves.
- DestroyWindow(hDlg);
- break;
- case WM_NET_ACCEPT:
- SocketAccept(wParam, lParam);
- break;
- case WM_NET_READWRITE:
- SocketReadWrite(wParam, lParam);
- break;
- case WM_NET_GETHOST:
- SocketGetHost(wParam, lParam);
- break;
- case WM_NET_AUTHCONNECT:
- SocketAuthConnect(wParam, lParam);
- break;
- default:
- return FALSE;
- }
- return(TRUE);
- }
- void InitMerc22(HINSTANCE hInstance, int cmdShow)
- {
- WNDCLASS wcMercClass;
- // Define the window class for this application.
- wcMercClass.lpszClassName = "Merc22";
- wcMercClass.hInstance = hInstance;
- wcMercClass.lpfnWndProc = MercWndProc;
- wcMercClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- // wcMercClass.hIcon = LoadIcon(hInstance, SetUpData.szAppName);
- wcMercClass.hIcon = 0;
- wcMercClass.lpszMenuName = (LPSTR) NULL;
- wcMercClass.hbrBackground = GetStockObject(WHITE_BRUSH);
- wcMercClass.style = CS_HREDRAW | CS_VREDRAW;
- wcMercClass.cbClsExtra = 0;
- wcMercClass.cbWndExtra = 0;
- // Register the class
- if (RegisterClass(&wcMercClass) == 0)
- {
- MessageBox(0, "Could not create Window", "@@@", MB_ICONHAND|MB_OK);
- exit(1);
- }
- hInst = hInstance; // save for use by window procs
- // Create applications main window.
- hWndMain = CreateWindow(
- "Merc22",
- "Welcome to Merc22/Win32",
- WS_BORDER |
- WS_CAPTION |
- WS_SYSMENU |
- WS_MINIMIZEBOX,
- 10,
- 19,
- 256,
- 123,
- NULL,
- NULL,
- hInstance,
- NULL
- );
- CreateDialog(hInst, MAKEINTRESOURCE(1), hWndMain, (DLGPROC) MercDlgProc);
- ShowWindow(hWndMain, cmdShow);
- UpdateWindow(hWndMain);
- }
- /*int SpinTheMessageLoop()
- {
- MSG msg;
- if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
- {
- if (msg.message == WM_QUIT)
- return FALSE;
- if (!IsDialogMessage(hQryDlgBox, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- return TRUE;
- }*/
- WPARAM game_loop_win32(HINSTANCE hInstance, HINSTANCE hPrevInstance, int nCmdShow)
- {
- // static DESCRIPTOR_DATA dcon;
- DESCRIPTOR_DATA *d;
- MSG msg;
- DWORD dwTick = 0;
- int fBackground;
- extern char * help_greeting;
- // HDC hDC;
- char szBuffer[128];
- extern int nAllocString;
- extern int sAllocString;
- extern int nAllocPerm;
- extern int sAllocPerm;
- static int nOldNString = -1;
- static int nOldSString = -1;
- static int nOldNPerm = -1;
- static int nOldSPerm = -1;
- /* Main loop */
- // // Go init this application.
- // InitMerc22(hInstance, nCmdShow);
- // Get and dispatch messages for this applicaton.
- fBackground = FALSE;
- for ( ;; )
- {
- // Always give Windows messages priority over Merc execution
- if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
- {
- if (msg.message == WM_QUIT)
- break;
- if (!IsDialogMessage(hQryDlgBox, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- else if (!fBackground)
- {
- fBackground++;
- time( ¤t_time );
- /*
- * Autonomous game motion.
- * (Synchronize to a clock.
- * Busy wait (blargh).)
- */
- if (GetTickCount() - dwTick >= 1000 / PULSE_PER_SECOND)
- {
- dwTick = GetTickCount();
- /*
- * Process input.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- // Give Windows a change to run other programs
- // if (!SpinTheMessageLoop())
- // goto merc_done;
- d_next = d->next;
- d->fcommand = FALSE;
- if ( d->character != NULL )
- d->character->timer = 0;
- #if 0
- // Did the user break connection?
- if ( !read_from_descriptor( d ) )
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- continue;
- }
- #endif
- 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] = ' ';
- }
- }
- update_handler( );
- // Update the screen
- if (nAllocString != nOldNString || sAllocString != nOldSString)
- {
- nOldNString = nAllocString;
- nOldSString = sAllocString;
- wsprintf( szBuffer, "Strings %5d strings of %7d bytes",
- nAllocString, sAllocString);
- SetDlgItemText(hQryDlgBox, 103, szBuffer);
- }
- if (nAllocPerm != nOldNPerm || sAllocPerm != nOldSPerm)
- {
- wsprintf( szBuffer, "Perms %5d blocks of %7d bytes",
- nAllocPerm, sAllocPerm );
- nOldNPerm = nAllocPerm;
- nOldSPerm = sAllocPerm;
- SetDlgItemText(hQryDlgBox, 104, szBuffer);
- }
- if (nPlayers != nOldPlayers)
- {
- wsprintf( szBuffer, "%d", nPlayers);
- nOldPlayers = nPlayers;
- SetDlgItemText(hQryDlgBox, 101, szBuffer);
- }
- /*
- * Output.
- */
- for ( d = descriptor_list; d != NULL; d = d_next )
- {
- // Give Windows a change to run other programs
- // if (!SpinTheMessageLoop())
- // goto merc_done;
- d_next = d->next;
- if ( ( d->fcommand || d->outtop > 0 ) )
- {
- if ( !process_output( d, TRUE ) && WSAGetLastError() != WSAEWOULDBLOCK)
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- }
- }
- #if 0
- now_time = last_time;
- for ( ; ; )
- {
- int delta;
- {
- 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;
- #endif
- }
- fBackground--;
- }
- }
- merc_done:
- return(msg.wParam);
- }
- //int main( int argc, char **argv )
- int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpszCmdLine, int nCmdShow)
- {
- extern char * help_greeting;
- struct timeval now_time;
- int port;
- //#if defined(unix)
- // int control;
- //#endif
- #ifdef WIN32
- WORD wVersionRequested = MAKEWORD( 1, 1 );
- WSADATA wsaData;
- int err;
- #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 ) );
- #if 0
- /*
- * Reserve one channel for our use.
- */
- if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL )
- {
- perror( NULL_FILE );
- return 1;
- }
- #endif
- #if 0 // @@@
- /*
- * Get the port number.
- */
- port = 1234;
- if ( lpszCmdLine[0] )
- {
- if ( !is_number( lpszCmdLine ) )
- {
- // fprintf( stderr, "Usage: Merc22sv [port #]n" );
- MessageBox(0, "Usage: Merc22sv [port #]", "Merc22", MB_ICONHAND|MB_OK);
- return 1;
- }
- #if 0
- else if ( ( port = atoi( lpszCmdLine ) ) <= 1024 )
- {
- fprintf( stderr, "Port number must be above 1024.n" );
- return 1;
- }
- #endif
- }
- #else
- port = GetProfileInt("MercW32", "PortNum", 23); // %%%
- #endif
- #ifdef WIN32
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 ) {
- MessageBox(0, "No useable WINSOCK.DLL, not loading sockets", "Serv",
- MB_ICONHAND|MB_OK);
- return INVALID_SOCKET;
- }
- /* Confirm that the Windows Sockets DLL supports 1.1.*/
- /* Note that if the DLL supports versions greater */
- /* than 1.1 in addition to 1.1, it will still return */
- /* 1.1 in wVersion since that is the version we */
- /* requested. */
- if ( LOBYTE( wsaData.wVersion ) != 1 ||
- HIBYTE( wsaData.wVersion ) != 1 ) {
- /* Tell the user that we couldn't find a useable */
- /* winsock.dll. */
- WSACleanup( );
- MessageBox(0, "Windows sockets version not 1.1, not loading sockets", "Serv",
- MB_ICONHAND|MB_OK);
- return INVALID_SOCKET;
- }
- /* Make sure that the version requested is >= 1.1. */
- /* The low byte is the major version and the high */
- /* byte is the minor version. */
- if ( LOBYTE( wVersionRequested ) < 1 ||
- ( LOBYTE( wVersionRequested ) == 1 &&
- HIBYTE( wVersionRequested ) < 1 )) {
- MessageBox(0, "Windows sockets version not 1.1, not loading sockets", "Serv",
- MB_ICONHAND|MB_OK);
- return INVALID_SOCKET;
- }
- /* Since we only support 1.1, set both wVersion and */
- /* wHighVersion to 1.1. */
- // wsaData.wVersion = MAKEWORD( 1, 1 );
- // wsaData.wHighVersion = MAKEWORD( 1, 1 );
- #endif
- // Go init this application.
- fpStderr = fopen( STDERR_FILE, "a" );
- InitMerc22(hInstance, nCmdShow);
- // Load the areas
- log_string( "Loading areas" );
- UpdateWindow(hWndOutput);
- boot_db( );
- // Validate enough of zones loaded to run Merc
- if (help_greeting == 0)
- log_string( "Error: areas.lst did not include help.are. Game will crash when players log in" );
- #ifdef MERCW32
- if (get_obj_index(OBJ_VNUM_ERROR) == 0)
- {
- log_string( "Error: Object #4 missing (check limbo.are). MercW32 needs object #4");
- log_string( " to prevent crashes when players with invalid equipment log in.");
- log_string( " check LIMBO.ARE");
- }
- #endif
- if (get_obj_index(OBJ_VNUM_MONEY_ONE) == 0 || get_obj_index(OBJ_VNUM_MONEY_SOME) == 0)
- log_string( "Error: Money objects #2 #3 did not load. Check LIMBO.ARE");
- if (get_obj_index(OBJ_VNUM_CORPSE_NPC) == 0 || get_obj_index(OBJ_VNUM_CORPSE_PC) == 0)
- log_string( "Error: Corpse templates did not load. Check LIMBO.ARE");
- if (get_obj_index(OBJ_VNUM_SEVERED_HEAD) == 0 || get_obj_index(OBJ_VNUM_TORN_HEART) == 0 ||
- get_obj_index(OBJ_VNUM_SLICED_ARM) == 0 || get_obj_index(OBJ_VNUM_SLICED_LEG) == 0 ||
- get_obj_index(OBJ_VNUM_FINAL_TURD) == 0)
- log_string( "Error: Severed body parts did not load. Check LIMBO.ARE");
- if (get_obj_index(OBJ_VNUM_MUSHROOM) == 0 || get_obj_index(OBJ_VNUM_LIGHT_BALL) == 0 ||
- get_obj_index(OBJ_VNUM_SPRING) == 0)
- log_string( "Error: Spell objects did not load. Check LIMBO.ARE #20 #21 #22");
- if (get_obj_index(OBJ_VNUM_SCHOOL_MACE) == 0 || get_obj_index(OBJ_VNUM_SCHOOL_DAGGER) == 0 ||
- get_obj_index(OBJ_VNUM_SCHOOL_SWORD) == 0 || get_obj_index(OBJ_VNUM_SCHOOL_VEST) == 0 ||
- get_obj_index(OBJ_VNUM_SCHOOL_SHIELD) == 0 || get_obj_index(OBJ_VNUM_SCHOOL_BANNER) == 0)
- log_string( "Error: New player equipment did not load. Check SCHOOL.ARE");
- if (get_room_index(ROOM_VNUM_LIMBO) == 0)
- log_string( "Error: The Void did not load. Check LIMBO.ARE");
- if (get_room_index(ROOM_VNUM_CHAT) == 0)
- log_string( "Error: Immortal chat-room did not load. Check HITOWER.ARE");
- if (get_room_index(ROOM_VNUM_TEMPLE) == 0 || get_room_index(ROOM_VNUM_ALTAR) == 0)
- log_string( "Error: Midgaard temple and Alter necessary for game. Check MIDGAARD.ARE");
- if (get_room_index(ROOM_VNUM_SCHOOL) == 0)
- log_string( "Error: New player initial room did not load. Check SCHOOL.ARE" );
- // #define MOB_VNUM_CITYGUARD 3060
- // #define MOB_VNUM_VAMPIRE 3404
- // #define MOB_VNUM_WALKING_DEAD 20
- // Initialize sockets
- log_string( "Initializing sockets" );
- UpdateWindow(hWndOutput);
- control = init_socket( port );
- // Tell Winsock we are listening for accepted sockets
- WSAAsyncSelect(control, hQryDlgBox, WM_NET_ACCEPT, FD_ACCEPT);
- sprintf( log_buf, "Merc is ready to rock on port %d.", port );
- log_string( log_buf );
- game_loop_win32(hInstance, hPrev, nCmdShow);
- closesocket( control );
- /*
- * That's all, folks.
- */
- log_string( "Normal termination of game." );
- fclose(fpStderr);
- #ifdef WIN32
- WSACleanup( );
- #endif
- return 0;
- }
- // @@@ Orig junk
- /*
- * 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';
- // @@@ Following line added by Slash, to prevent bugs where stuff in the
- // buffers fires mobprogs. Particularly bad when a player enters the game
- // and gets the greet_prog over and over.
- *point = ' ';
- buf[0] = UPPER(buf[0]);
- if (to->desc)
- write_to_buffer( to->desc, buf, point - buf );
- #ifdef MOBPROGS
- if (MOBtrigger)
- mprog_act_trigger( buf, to, ch, obj1, vch );
- /* Added by Kahn */
- #endif
- }
- #ifdef MOBPROGS
- MOBtrigger = TRUE;
- #endif
- return;
- }
- /*
- * Append onto an output buffer.
- */
- void write_to_buffer( DESCRIPTOR_DATA *d, const char *txt, int length )
- {
- /* @@@ ECS */
- if (d == 0)
- return;
- /*
- * Find length in case caller didn't.
- */
- if ( length <= 0 )
- length = strlen(txt);
- // @@@
- // else if (length < strlen(txt))
- // MessageBox(0, "Length Error", "Merc22Sv", MB_ICONHAND|MB_OK);
- /*
- * 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 );
- #if 1 // @@@ Deal with too large a memory increment...
- if (!outbuf)
- {
- length = d->outsize - d->outtop - 1;
- break;
- }
- #endif
- strncpy( outbuf, d->outbuf, d->outtop );
- free_mem( d->outbuf, d->outsize );
- d->outbuf = outbuf;
- d->outsize *= 2;
- }
- /*
- * Copy.
- */
- //@@@ Ack! strcpy( d->outbuf + d->outtop, txt );
- #if 1
- if (length > 0)
- {
- #endif
- memcpy(d->outbuf + d->outtop, txt, length);
- d->outtop += length;
- #if 1
- }
- #endif
- #ifdef WIN32
- // Tell Winsock to wake us when the socket becomes ready
- if (!BlastedTrumpet(d->descriptor))
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- #endif
- return;
- }
- 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 );
- }
- closesocket( dclose->descriptor );
- free_string( dclose->host );
- dclose->next = descriptor_free;
- descriptor_free = dclose;
- nPlayers--;
- return;
- }
- // Write_to_descriptor bypasses the whole buffered output system. Blech!
- bool write_to_descriptor( int desc, char *txt, int length )
- {
- int iStart;
- int nWrite;
- int nBlock;
- if ( length <= 0 )
- length = strlen(txt);
- for ( iStart = 0; iStart < length; iStart += nWrite )
- {
- nBlock = UMIN( length - iStart, 4096 );
- // @@@ Should check WSAEWOULDBLOCK, and we don't want MessageBox...
- if ( ( nWrite = send( desc, txt + iStart, nBlock, 0 ) ) == SOCKET_ERROR ||
- nWrite != nBlock)
- {
- log_string( "Write_to_descriptor" );
- return FALSE;
- }
- }
- #ifdef WIN32
- // Tell Winsock to wake us when the socket becomes ready
- BlastedTrumpet(desc);
- #endif
- 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 iRace;
- 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) < 3 )
- {
- write_to_buffer( d,
- "Password must be at least three 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;
- }
- #ifdef RACES
- strcpy( buf, "Select a race [" );
- for ( iRace = 0; iRace < MAX_RACE; iRace++ )
- {
- if ( iRace > 0 )
- strcat( buf, " " );
- strcat( buf, race_table[iRace].who_name );
- }
- strcat( buf, "]: " );
- write_to_buffer( d, buf, 0 );
- d->connected = CON_GET_NEW_RACE;
- break;
- case CON_GET_NEW_RACE:
- for ( iRace = 0; iRace < MAX_RACE; iRace++ )
- {
- if ( !str_cmp( argument, race_table[iRace].who_name ) )
- {
- ch->race = iRace;
- break;
- }
- }
- if ( iRace == MAX_RACE )
- {
- write_to_buffer( d,
- "That's not a race.nrWhat IS your race? ", 0 );
- return;
- }
- #endif
- 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;
- }
- #ifdef RACES
- ch->pcdata->perm_str += race_table[ch->race].mod_str;
- ch->pcdata->perm_int += race_table[ch->race].mod_int;
- ch->pcdata->perm_wis += race_table[ch->race].mod_wis;
- ch->pcdata->perm_dex += race_table[ch->race].mod_dex;
- ch->pcdata->perm_con += race_table[ch->race].mod_con;
- #endif
- ch->level = 1;
- ch->exp = 1000;
- ch->hit = ch->max_hit;
- ch->mana = ch->max_mana;
- ch->move = ch->max_move;
- #ifdef RACES
- ch->affected_by = race_table[ch->race].bitvector;
- #else
- ch->affected_by = 0;
- #endif
- 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
- {
- #ifdef RACES
- char_to_room( ch, get_room_index( race_table[ch->race].city_temple ) );
- #else
- char_to_room( ch, get_room_index( ROOM_VNUM_TEMPLE ) );
- #endif
- }
- 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;
- }
- /*
- * 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 );
- bust_a_prompt( d );
- 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 );
- }
- #if 0
- /*
- * OS-dependent output.
- */
- if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) )
- {
- d->outtop = 0;
- return FALSE;
- }
- else
- {
- d->outtop = 0;
- return TRUE;
- }
- #endif
- // Wake up Winsock, if necessary
- if (!BlastedTrumpet(d->descriptor))
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- return FALSE;
- }
- return TRUE;
- }
- /*
- * Bust a prompt (player settable prompt)
- * coded by Morgenes for Aldara Mud
- */
- //void bust_a_prompt( CHAR_DATA *ch )
- void bust_a_prompt( DESCRIPTOR_DATA *d )
- {
- char buf[MAX_STRING_LENGTH];
- char buf2[MAX_STRING_LENGTH];
- const char *str;
- const char *i;
- char *point;
- CHAR_DATA *ch;
- CHAR_DATA *victim;
- ch = d->character;
- if( ch->prompt == NULL || ch->prompt[0] == ' ' )
- {
- send_to_char( "nrnr", ch );
- return;
- }
- point = buf;
- // str = ch->prompt;
- str = d->original != NULL ? d->original->prompt : /* VERY VERY NEW */
- d->character->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;
- }
- /* battle prompt */
- if ((victim = ch->fighting) != NULL)
- {
- int percent;
- char wound[100];
- char buf[MAX_STRING_LENGTH];
- write_to_buffer( d, "nr", 0);
- if (victim->max_hit > 0)
- percent = victim->hit * 100 / victim->max_hit;
- else
- percent = -1;
- if (percent >= 100)
- sprintf(wound,"is in excellent condition.");
- else if (percent >= 90)
- sprintf(wound,"has a few scratches.");
- else if (percent >= 75)
- sprintf(wound,"has some small wounds and bruises.");
- else if (percent >= 50)
- sprintf(wound,"has quite a few wounds.");
- else if (percent >= 30)
- sprintf(wound,"has some big nasty wounds and scratches.");
- else if (percent >= 15)
- sprintf(wound,"looks pretty hurt.");
- else if (percent >= 0)
- sprintf(wound,"is in awful condition.");
- else
- sprintf(wound,"is bleeding to death.");
- sprintf(buf,"%s %s nr",
- IS_NPC(victim) ? victim->short_descr : victim->name,wound);
- buf[0] = UPPER(buf[0]);
- write_to_buffer( d, buf, 0);
- }
- write_to_buffer( ch->desc, buf, point - buf );
- return;
- }
- /* 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 */
- // @@@ Sands had some changes here that lead to double freeing
- if ( d->showstr_head )
- {
- free_string( d->showstr_head );
- // d->showstr_head = str_dup( "" );
- d->showstr_head = 0;
- }
- // free_string( d->showstr_point );
- // d->showstr_point = str_dup( "" );
- 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;
- }
- SOCKET init_socket( int port )
- {
- // Assume there aren't any sockets
- //@@@ fSockets = FALSE;
- static struct sockaddr_in sa_zero;
- struct sockaddr_in sa;
- SOCKET newsock;
- int x = 1;
- #if 0
- WORD wVersionRequested = MAKEWORD( 1, 1 );
- WSADATA wsaData;
- int err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 ) {
- MessageBox(0, "No useable WINSOCK.DLL, not loading sockets", "Serv",
- MB_ICONHAND|MB_OK);
- return INVALID_SOCKET;
- }
- /* Confirm that the Windows Sockets DLL supports 1.1.*/
- /* Note that if the DLL supports versions greater */
- /* than 1.1 in addition to 1.1, it will still return */
- /* 1.1 in wVersion since that is the version we */
- /* requested. */
- if ( LOBYTE( wsaData.wVersion ) != 1 ||
- HIBYTE( wsaData.wVersion ) != 1 ) {
- /* Tell the user that we couldn't find a useable */
- /* winsock.dll. */
- WSACleanup( );
- MessageBox(0, "Windows sockets version not 1.1, not loading sockets", "Serv",
- MB_ICONHAND|MB_OK);
- return INVALID_SOCKET;
- }
- /* Make sure that the version requested is >= 1.1. */
- /* The low byte is the major version and the high */
- /* byte is the minor version. */
- if ( LOBYTE( wVersionRequested ) < 1 ||
- ( LOBYTE( wVersionRequested ) == 1 &&
- HIBYTE( wVersionRequested ) < 1 )) {
- MessageBox(0, "Windows sockets version not 1.1, not loading sockets", "Serv",
- MB_ICONHAND|MB_OK);
- return INVALID_SOCKET;
- }
- /* Since we only support 1.1, set both wVersion and */
- /* wHighVersion to 1.1. */
- wsaData.wVersion = MAKEWORD( 1, 1 );
- wsaData.wHighVersion = MAKEWORD( 1, 1 );
- #endif
- // fSockets = TRUE;
- if ( ( newsock = socket( PF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
- {
- MessageBox(0, "Init_socket: socket", __FILE__, MB_OK);
- return INVALID_SOCKET;
- }
- if ( setsockopt( newsock, SOL_SOCKET, SO_REUSEADDR, (char *) &x, sizeof(x) )
- == SOCKET_ERROR )
- {
- MessageBox(0, "Init_socket: SO_REUSEADDR", __FILE__, MB_OK);
- closesocket(newsock);
- return INVALID_SOCKET;
- }
- #if 0
- {
- struct linger ld;
- ld.l_onoff = 1;
- ld.l_linger = 1000;
- if ( setsockopt( fd, SOL_SOCKET, SO_DONTLINGER, (char *) &ld, sizeof(ld) ) < 0 )
- {
- MessageBox(0, 0, "Init_socket: SO_DONTLINGER", __FILE__, MB_OK );
- closesocket( fd );
- return INVALID_SOCKET;
- }
- }
- #endif
- sa = sa_zero;
- sa.sin_family = AF_INET;
- sa.sin_port = htons( port );
- if ( bind( newsock, (struct sockaddr *) &sa, sizeof(sa) ) == SOCKET_ERROR )
- {
- MessageBox(0, "Init_socket: bind", __FILE__, MB_OK );
- closesocket( newsock );
- return INVALID_SOCKET;
- }
- if ( listen( newsock, 3 ) == SOCKET_ERROR )
- {
- MessageBox(0, "Init_socket: listen", __FILE__, MB_OK );
- closesocket( newsock );
- return INVALID_SOCKET;
- }
- return newsock;
- }
- LRESULT SocketAccept (WPARAM wParam, LPARAM lParam)
- {
- static DESCRIPTOR_DATA d_zero;
- SOCKET sSocket;
- SOCKADDR_IN saPeer;
- int iAddrSize;
- // int iError;
- char buf[512];
- DESCRIPTOR_DATA *dnew;
- switch(WSAGETSELECTEVENT(lParam))
- {
- default:
- MessageBeep(-1);
- break;
- case FD_ACCEPT:
- {
- // LPSOCKADDR_IN lpsaHostAddr;
- // LPHOSTENT lpheHostEnt;
- // struct sockaddr_in isa;
- // int i = sizeof(isa);
- // getsockname(s, &isa, &i);
- struct sockaddr_in sock;
- int size = sizeof(sock);
- // MessageBeep(-1);
- /* Get a pending accept */
- iAddrSize = sizeof(SOCKADDR_IN);
- sSocket = accept( control, (LPSOCKADDR) &saPeer, (LPINT) &iAddrSize );
- if ( sSocket == INVALID_SOCKET )
- {
- // MessageBox(0, "Couldn't accept() connection.", "Serv",
- // MB_ICONHAND|MB_OK);
- log_string("Couldn't accept() connection");
- return FALSE;
- }
- // Cons a new descriptor.
- if ( descriptor_free )
- {
- dnew = descriptor_free;
- descriptor_free = descriptor_free->next;
- dnew->descriptor = sSocket;
- }
- else
- dnew = alloc_perm( sizeof(*dnew) );
- *dnew = d_zero;
- dnew->descriptor = sSocket;
- dnew->connected = CON_GET_NAME;
- dnew->showstr_head = NULL;
- dnew->showstr_point = NULL;
- dnew->outsize = 2000;
- dnew->outbuf = alloc_mem( dnew->outsize );
- dnew->host_and_name = alloc_mem( sizeof *dnew->host_and_name );
- strcpy(dnew->host_and_name->username, "<waiting>");
- if ( getpeername( sSocket, (struct sockaddr *) &sock, &size ) == SOCKET_ERROR )
- {
- #if 1
- wsprintf(buf, "new_descriptor(): getpeername() == %d",
- WSAGetLastError());
- log_string( buf );
- #else
- log_string("New_descriptor: getpeername");
- #endif
- dnew->host = str_dup( "(unknown)" );
- }
- else
- {
- int ulen = sizeof dnew->host_and_name->us;
- // Get the caller's machine in quad format
- u_long addr = ntohl( sock.sin_addr.s_addr );
- struct hostent *from;
- wsprintf( buf, "%d.%d.%d.%d",
- ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
- ( addr >> 8 ) & 0xFF, ( addr ) & 0xFF);
- wsprintf( log_buf, "Sock.sinaddr: %s", buf );
- log_string( log_buf );
- // Request the name of the caller's machine from DNS
- dnew->host = str_dup( buf );
- dnew->host_and_name->sin_addr = sock.sin_addr;
- dnew->host_and_name->hRequestHandle = WSAAsyncGetHostByAddr( hQryDlgBox,
- WM_NET_GETHOST, (LPSTR) &dnew->host_and_name->sin_addr, sizeof dnew->host_and_name->sin_addr,
- PF_INET, dnew->host_and_name->hostdata, sizeof dnew->host_and_name->hostdata);
- // Look up the local name for this socket
- if (getsockname(sSocket, (struct sockaddr *)&dnew->host_and_name->us, &ulen) ==
- SOCKET_ERROR)
- {
- wsprintf(dnew->host_and_name->username, "(getsockname)#%d", WSAGetLastError());
- goto failure;
- }
- // Create a socket to connect to the user's ident port
- if ((dnew->host_and_name->sAuth = socket(PF_INET, SOCK_STREAM, AF_UNSPEC)) ==
- INVALID_SOCKET)
- {
- wsprintf(dnew->host_and_name->username, "(socket)#%d", WSAGetLastError());
- goto failure;
- }
- // Save the address of their side of the socket
- dnew->host_and_name->them = sock;
- // htons convers a u_short from host to network byte order. 113 is
- // the auth socket
- dnew->host_and_name->authsock.sin_port = htons(113);
- // Use Internet protocol
- dnew->host_and_name->authsock.sin_family = AF_INET;
- // Look up the other end of our socket
- dnew->host_and_name->authsock.sin_addr = sock.sin_addr;
- WSAAsyncSelect(dnew->host_and_name->sAuth, hQryDlgBox, WM_NET_AUTHCONNECT,
- FD_CONNECT|FD_READ|FD_WRITE);
- if (connect(dnew->host_and_name->sAuth, (struct sockaddr *)&dnew->host_and_name->authsock,
- sizeof(dnew->host_and_name->authsock)) == SOCKET_ERROR)
- {
- int nError = WSAGetLastError();
- if (nError != WSAEWOULDBLOCK)
- {
- wsprintf(dnew->host_and_name->username, "(connect)#%d", nError);
- goto failure;
- }
- }
- }
- failure:
- // Init descriptor data.
- dnew->next = descriptor_list;
- descriptor_list = dnew;
- nPlayers++;
- // OK now get messages from this socket
- BlastedTrumpet(sSocket);
- // 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 );
- }
- } // FD_ACCEPT
- }
- return FALSE;
- }
- LRESULT SocketReadWrite (WPARAM wParam, LPARAM lParam)
- {
- SOCKET sSocket = (SOCKET) wParam;
- // SOCKADDR_IN saPeer;
- // int iAddrSize;
- // int iError;
- // char szBuffer[64];
- // int len;
- switch(WSAGETSELECTEVENT(lParam))
- {
- default:
- MessageBeep(-1);
- break;
- case FD_READ: // WinSock has something for us
- {
- // Find the descriptor for this FD_READ
- DESCRIPTOR_DATA *d;
- for (d = descriptor_list; d; d = d_next )
- {
- d_next = d->next;
- if (d->descriptor == sSocket)
- {
- d->fcommand = FALSE;
- if ( d->character != NULL )
- d->character->timer = 0;
- if ( !read_from_descriptor( d ) )
- {
- //@@@Dunno what this does? FD_CLR( d->descriptor, &out_set );
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- //@@@ continue;
- }
- break;
- }
- }
- } // FD_READ
- break;
- case FD_WRITE: // WinSock ready to send data on this socket
- {
- #if 0
- if (!BlastedTrumpet(sSocket))
- return FALSE;
- #endif
- #if 0
- send(sSocket, szMessage, strlen(szMessage), 0);
- #else
- // Output.
- DESCRIPTOR_DATA *d;
- for (d = descriptor_list; d != NULL; d = d_next )
- {
- d_next = d->next;
- if (d->descriptor == sSocket)
- if ( d->fcommand || d->outtop > 0 )
- {
- #if 0
- if ( !process_output( d, TRUE ) && WSAGetLastError() != WSAEWOULDBLOCK )
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- #endif
- int iStart, nWrite;
- for ( iStart = 0; iStart < d->outtop; iStart += nWrite )
- {
- int nBlock = UMIN( d->outtop - iStart, 4096 );
- if ( ( nWrite = send( d->descriptor, d->outbuf + iStart, nBlock, 0 ) ) == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- {
- log_string( "Write_to_descriptor" );
- if ( d->character != NULL )
- save_char_obj( d->character );
- close_socket( d );
- }
- break;
- }
- }
- // @@@ It would be better at this point to resend if we got
- // EWOULDBLOCK, but we throw all data away...
- d->outtop = 0;
- }
- }
- #endif
- } // FD_WRITE
- break;
- case FD_CLOSE: // Hey, it closed on us...
- // MessageBox(0, "Closing", "Serv", MB_ICONINFORMATION|MB_OK);
- // log_string("Closing");
- break;
- }
- return FALSE;
- }
- bool BlastedTrumpet(SOCKET sSocket)
- {
- if ( WSAAsyncSelect( sSocket, hQryDlgBox, WM_NET_READWRITE,
- FD_READ|FD_WRITE|FD_CLOSE) == SOCKET_ERROR)
- {
- // MessageBox(0, "Couldn't select() on client socket.", "Serv",
- // MB_ICONHAND|MB_OK);
- log_string("Couldn't select() on client socket.");
- return FALSE;
- }
- return TRUE;
- }
- bool read_from_descriptor( DESCRIPTOR_DATA *d )
- {
- int iStart;
- /* Hold horses if pending command already. */
- if ( d->incomm[0] != ' ' )
- {
- if (!BlastedTrumpet(d->descriptor))
- {
- if ( d->character != NULL )
- save_char_obj( d->character );
- d->outtop = 0;
- close_socket( d );
- }
- // BlastedTrumpet(d->descriptor);
- return TRUE;
- }
- /* Check for overflow. */
- iStart = strlen(d->inbuf);
- if ( iStart >= sizeof(d->inbuf) - 10 )
- {
- wsprintf( log_buf, "%s input overflow!", d->host );
- log_string( log_buf );
- BlastedTrumpet(d->descriptor);
- //@@@ MessageBox(0, "input overflow!", "Serv", MB_ICONHAND|MB_OK);
- write_to_descriptor( d->descriptor,
- "nr*** PUT A LID ON IT!!! ***nr", 0 );
- return FALSE;
- }
- /* Snarf input. */
- for ( ; ; )
- {
- int nRead;
- nRead = recv( d->descriptor, d->inbuf + iStart,
- sizeof(d->inbuf) - 10 - iStart, 0 );
- 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 ( WSAGetLastError() == WSAEWOULDBLOCK )
- break;
- else
- {
- // perror( "Read_from_descriptor" );
- // MessageBox(0, "Read_from_descriptor", "Serv", MB_ICONHAND|MB_OK);
- log_string("read_from_descriptor() got error");
- return FALSE;
- }
- }
- d->inbuf[iStart] = ' ';
- return TRUE;
- }
- /*
- * Writes a string to the log.
- */
- void log_string( const char *str )
- {
- char *strtime;
- if (IsWindow(hWndOutput))
- SendMessage(hWndOutput, LB_ADDSTRING, 0, (LPARAM)(LPCSTR) str);
- strtime = ctime( ¤t_time );
- strtime[strlen(strtime)-1] = ' ';
- fprintf( fpStderr, "%s :: %sn", strtime, str );
- }
- LRESULT SocketGetHost(WPARAM wParam, LPARAM lParam)
- {
- DESCRIPTOR_DATA *des = descriptor_list;
- WORD wError;
- // MessageBeep(-1);
- while (des && des->host_and_name->hRequestHandle != (HANDLE) wParam)
- des = des->next;
- if (!des)
- {
- log_string("Got Host info for unknown descriptor");
- return FALSE;
- }
- wError = WSAGETASYNCERROR(lParam);
- if (wError)
- {
- char szBuf[512];
- char *p = "(Unknown Error)";
- if (wError == WSAHOST_NOT_FOUND)
- p = "(Authoritative Answer: Host Not Found)";
- else if (wError == WSATRY_AGAIN)
- p = "(Host not found, or Server Failure)";
- else if (wError == WSANO_RECOVERY)
- p = "(Former, Refused, or Not Implemented)";
- else if (wError == WSANO_DATA)
- p = "(Valid name, no data record)";
- else if (wError == WSANO_DATA)
- p = "(No Address)";
- wsprintf(szBuf, "%s %s", des->host, p);
- free_string( des->host );
- des->host = str_dup( szBuf );
- }
- else
- {
- free_string( des->host );
- des->host = str_dup( ((struct hostent FAR *)(des->host_and_name->hostdata))->h_name );
- }
- return TRUE;
- }
- LRESULT SocketAuthConnect(WPARAM wParam, LPARAM lParam)
- {
- char szIdentRequest[32];
- char szIdentReply[256];
- char szUserID[32];
- u_short port1, port2;
- char *p;
- DESCRIPTOR_DATA *des = descriptor_list;
- while (des && des->host_and_name->sAuth != (SOCKET) wParam)
- des = des->next;
- if (!des)
- {
- log_string("Ident message info for unknown descriptor");
- return FALSE;
- }
- switch(WSAGETSELECTEVENT(lParam))
- {
- default:
- MessageBeep(-1);
- break;
- case FD_CONNECT:
- // log_string("FD_CONNECT to IDENTD port");
- // break;
- //
- // case FD_WRITE:
- // Failure?
- if (WSAGETSELECTERROR(lParam))
- {
- wsprintf(des->host_and_name->username, "(FD_CONNECT)#%d", WSAGetLastError());
- closesocket((SOCKET) wParam);
- return FALSE;
- }
- // Create a string of the form <port>, <port>rn
- wsprintf(szIdentRequest, "%u , %urn",
- ntohs(des->host_and_name->them.sin_port),
- ntohs(des->host_and_name->us.sin_port));
- send((SOCKET) wParam, szIdentRequest, strlen(szIdentRequest), 0);
- // @@@ Should check return value
- break;
- case FD_READ:
- // Read the response from the IDENT port
- recv((SOCKET) wParam, szIdentReply, sizeof szIdentReply, 0);
- // @@@ Should check return value
- // Extract the user name provided by IDENT
- sscanf(szIdentReply, "%hd , %hd : USERID : %*[^:]: %10s",
- &port1, &port2, szUserID);
- log_string(szIdentReply); // @@@
- // Remove any trailing newline from the user name
- for (p = szUserID; *p && *p != 'n' && *p != 'r'; p++)
- ;
- *p = ' ';
- // Save the user name in the descriptor
- strcpy(des->host_and_name->username, szUserID);
- // Close this socket
- closesocket((SOCKET) wParam);
- break;
- }
- return TRUE;
- }
- /*
- * Write to all characters.
- */
- void send_to_all_char( const char *text )
- {
- DESCRIPTOR_DATA *d;
- if ( !text )
- return;
- for ( d = descriptor_list; d; d = d->next )
- if ( d->connected == CON_PLAYING )
- send_to_char( text, d->character );
- return;
- }
- /*
- * Reports a bug.
- */
- void bug( const char *str, int param )
- {
- extern FILE * fpArea;
- extern char strArea[ MAX_INPUT_LENGTH ];
- FILE *fp;
- char buf [ MAX_STRING_LENGTH ];
- char buf2[ MAX_STRING_LENGTH ];
- if ( fpArea )
- {
- int iLine;
- int iChar;
- if ( fpArea == stdin )
- {
- iLine = 0;
- }
- else
- {
- iChar = ftell( fpArea );
- fseek( fpArea, 0, 0 );
- for ( iLine = 0; ftell( fpArea ) < iChar; iLine++ )
- {
- while ( getc( fpArea ) != 'n' )
- ;
- }
- fseek( fpArea, iChar, 0 );
- }
- sprintf( buf2, "[*****] FILE: %s LINE: %d", strArea, iLine );
- log_string( buf2 );
- if ( ( fp = fopen( "shutdown.txt", "a" ) ) )
- {
- fprintf( fp, "[*****] %sn", buf2 );
- fclose( fp );
- }
- }
- else
- buf2[0] = 0;
- strcpy( buf, "[*****] BUG: " );
- sprintf( buf + strlen( buf ), str, param );
- log_string( buf );
- fclose( fpReserve );
- if ( ( fp = fopen( BUG_FILE, "a" ) ) )
- {
- fprintf( fp, "%sn", buf );
- fclose( fp );
- }
- fpReserve = fopen( NULL_FILE, "r" );
- if (fWantsMessageBox)
- MessageBox(0, buf, buf2, MB_ICONHAND|MB_OK);
- return;
- }
- // This was moved out of act_wiz so that I can use the host_and_name member
- void do_users( CHAR_DATA *ch, char *argument )
- {
- char buf[MAX_STRING_LENGTH];
- char buf2[MAX_STRING_LENGTH];
- DESCRIPTOR_DATA *d;
- int count;
- count = 0;
- buf[0] = ' ';
- buf2[0] = ' ';
- for ( d = descriptor_list; d != NULL; d = d->next )
- {
- if ( d->character != NULL && can_see( ch, d->character ) )
- {
- count++;
- sprintf( buf + strlen(buf), "[%3d %2d] %s (%s@%s)nr",
- d->descriptor,
- d->connected,
- d->original ? d->original->name :
- d->character ? d->character->name : "(none)",
- d->host_and_name->username, d->host
- );
- }
- }
- sprintf( buf2, "%d user%snr", count, count == 1 ? "" : "s" );
- strcat( buf, buf2 );
- send_to_char( buf, ch );
- return;
- }