Version resource added to ping and roshttpd.
svn path=/trunk/; revision=1575
TARGETNAME=ping
CFLAGS = -I../../../include
-OBJECTS = $(TARGETNAME).o
+OBJECTS = $(TARGETNAME).o $(TARGETNAME).coff
PROGS = $(TARGETNAME).exe
LIBS = ../../../lib/ntdll/ntdll.a \
../../../lib/ws2_32/ws2_32.a
-/*
+/* $Id: ping.c,v 1.3 2001/01/27 22:38:42 ea Exp $
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS ping utility
* FILE: apps/net/ping/ping.c
--- /dev/null
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "ReactOS TCP/IPv4 Win32 Ping\0"
+ VALUE "FileVersion", RES_STR_FILE_VERSION
+ VALUE "InternalName", "ping\0"
+ VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
+ VALUE "OriginalCopyright", "Casper S. Hornstrup (chorns@users.sourceforge.net)\0"
+ VALUE "OriginalFilename", "ping.exe\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
--- /dev/null
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "ReactOS HTTP Win32 Server\0"
+ VALUE "FileVersion", RES_STR_FILE_VERSION
+ VALUE "InternalName", "roshttpd\0"
+ VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
+ VALUE "OriginalCopyright", "Casper S. Hornstrup (chorns@users.sourceforge.net)\0"
+ VALUE "OriginalFilename", "roshttpd.exe\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
CFLAGS = -Iinclude -DUNICODE -D_UNICODE -DDBG
MAIN_OBJECTS = $(TARGETNAME).o config.o error.o http.o httpd.o
-COMMON_OBJECTS = common/list.o common/socket.o common/thread.o
+COMMON_OBJECTS = common/list.o common/socket.o common/thread.o common/$(TARGETNAME).coff
OBJECTS = $(MAIN_OBJECTS) $(COMMON_OBJECTS)
PROGS = $(TARGETNAME).exe
--- /dev/null
+# $Id: Makefile,v 1.1 2001/01/27 22:38:43 ea Exp $
+#
+# ReactOS Network Virtual Terminal (telnet) console client
+#
+PATH_TO_TOP=../../..
+PATH_TO_LIB=$(PATH_TO_TOP)/lib
+
+TARGET_NAME=telnet
+
+OBJECTS=\
+ ansi.o \
+ console.o \
+ helpsock.o \
+ main.o \
+ nvt.o \
+ telnet.o \
+ vm.o \
+ $(TARGET_NAME).coff
+
+LIBRARIES=\
+ $(PATH_TO_LIB)/crtdll/crtdll.a \
+ $(PATH_TO_LIB)/kernel32/kernel32.a \
+ $(PATH_TO_LIB)/ws2_32/ws2_32.a
+
+PROGS=$(TARGET_NAME).exe
+
+ifeq ($(DOSCLI), yes)
+CLEAN_FILES = *.o $(TARGET_NAME).exe $(TARGET_NAME).sym
+else
+CLEAN_FILES = *.o $(TARGET_NAME).exe $(TARGET_NAME).sym
+endif
+
+all: $(TARGET_NAME).exe
+
+clean: $(CLEAN_FILES:%=%_clean)
+
+$(CLEAN_FILES:%=%_clean): %_clean:
+ - $(RM) $*
+
+.phony: clean $(CLEAN_FILES:%=%_clean)
+
+install: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
+
+$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
+ifeq ($(DOSCLI),yes)
+ $(CP) $* $(FLOPPY_DIR)\apps\$*
+else
+ $(CP) $* $(FLOPPY_DIR)/apps/$*
+endif
+
+dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
+
+$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
+ifeq ($(DOSCLI),yes)
+ $(CP) $* ..\..\$(DIST_DIR)\apps\$*
+else
+ $(CP) $* ../../$(DIST_DIR)/apps/$*
+endif
+
+ansi.o: telnet.h
+
+helpsock.o: telnet.h
+
+main.o: telnet.h
+
+nvt.o: telnet.h
+
+telnet.o: telnet.h
+
+telnet.coff: $(PATH_TO_TOP)/include/reactos/resource.h
+
+vm.o: telnet.h
+
+$(TARGET_NAME).exe: $(OBJECTS) $(LIBRARIES)
+ $(CC) $(OBJECTS) $(LIBRARIES) -o $(TARGET_NAME).exe
+
+include $(PATH_TO_TOP)/rules.mak
+
+# EOF
--- /dev/null
+/* $Id: ansi.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : ansi.cpp
+ * AUTHOR : unknown (sources found on www.telnet.org)
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea Modified to compile under 0.0.16 src tree
+ */
+#include <winsock.h>
+#include <windows.h>
+
+#include "telnet.h"
+
+// Need to implement a Keymapper.
+// here are some example key maps
+
+// vt100 f1 - \eOP
+// vt100 f2 - \eOQ
+
+// ansi f5 - \e[17~
+// f6 - \e[18~
+// f7 - \e[20~
+// f10- \e[[V
+
+enum _ansi_state
+{
+ as_normal,
+ as_esc,
+ as_esc1
+};
+
+//SetConsoleMode
+
+///////////////////////////////////////////////////////////////////////////////
+// SET SCREEN ATTRIBUTE
+/*
+ESC [ Ps..Ps m Ps refers to selective parameter. Multiple parameters are
+ separated by the semicolon character (073 octal). The param-
+ eters are executed in order and have the following meaning:
+
+ 0 or none All attributes off
+ 1 Bold on
+ 4 Underscore on
+ 5 Blink on
+ 7 Reverse video on
+
+ 3x set foreground color to x
+ nx set background color to x
+
+ Any other parameters are ignored.
+*/
+static int sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+
+void ansi_set_screen_attribute(char* buffer)
+{
+ while(*buffer)
+ {
+ switch(*buffer++)
+ {
+ case '0': //Normal
+ sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+ break;
+ case '1': //Hign Intensity
+ sa |= FOREGROUND_INTENSITY;
+ break;
+ case '4': //Underscore
+ break;
+ case '5': //Blink.
+ sa |= BACKGROUND_INTENSITY;
+ break;
+ case '7':
+ sa = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
+ break;
+ case '8':
+ sa = 0;
+ break;
+ case '3':
+ sa = sa & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY) |
+ (*buffer & 1)?FOREGROUND_RED:0 |
+ (*buffer & 2)?FOREGROUND_GREEN:0 |
+ (*buffer & 4)?FOREGROUND_BLUE:0;
+ if(*buffer)
+ buffer++;
+ break;
+ case '6':
+ sa = sa & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY) |
+ (*buffer & 1)?BACKGROUND_RED:0 |
+ (*buffer & 2)?BACKGROUND_GREEN:0 |
+ (*buffer & 4)?BACKGROUND_BLUE:0;
+ if(*buffer)
+ buffer++;
+ break;
+ }
+ if(*buffer && *buffer == ';')
+ buffer++;
+ }
+ SetConsoleTextAttribute(StandardOutput,sa);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ERASE LINE
+/*
+ESC [ 0K Same *default*
+ESC [ 1K Erase from beginning of line to cursor
+ESC [ 2K Erase line containing cursor
+*/
+
+void ansi_erase_line(char* buffer)
+{
+ int act = 0;
+ while(*buffer)
+ {
+ act = (*buffer++) - '0';
+ }
+
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(StandardOutput,&csbi);
+
+ COORD pos;
+ DWORD n;
+
+ switch(act)
+ {
+ case 0: //erase to end of line
+ pos.X = csbi.dwCursorPosition.X;
+ pos.Y = csbi.dwCursorPosition.Y;
+ n = csbi.dwSize.X - csbi.dwCursorPosition.X;
+ break;
+ case 1: //erase from beginning
+ pos.X = 0;
+ pos.Y = csbi.dwCursorPosition.Y;
+ n = csbi.dwCursorPosition.X;
+ break;
+ case 2: // erase whole line
+ pos.X = 0;
+ pos.Y = csbi.dwCursorPosition.Y;
+ n = csbi.dwSize.X;
+ break;
+ }
+
+ DWORD w;
+ FillConsoleOutputCharacter(StandardOutput,' ',n,pos,&w);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SET POSITION
+// ESC [ Pl;PcH Direct cursor addressing, where Pl is line#, Pc is column#
+// default = (1,1)
+
+void ansi_set_position(char* buffer)
+{
+ COORD pos = {0,0};
+
+ // Grab line
+ while(*buffer && *buffer != ';')
+ pos.Y = pos.Y*10 + *buffer++ - '0';
+
+ if(*buffer)
+ buffer++;
+
+ // Grab y
+ while(*buffer && *buffer != ';')
+ pos.X = pos.X*10 + *buffer++ - '0';
+
+ (pos.X)?pos.X--:0;
+ (pos.Y)?pos.Y--:0;
+
+ SetConsoleCursorPosition(StandardOutput,pos);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ERASE SCREEN
+/*
+ESC [ 0J Same *default*
+ESC [ 2J Erase entire screen
+*/
+
+void ansi_erase_screen(char* buffer)
+{
+ int act = 0;
+ while(*buffer)
+ {
+ act = (*buffer++) - '0';
+ }
+
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(StandardOutput,&csbi);
+
+ COORD pos;
+ DWORD n;
+
+ switch(act)
+ {
+ case 0:
+ pos.X = csbi.dwCursorPosition.X;
+ pos.Y = csbi.dwCursorPosition.Y;
+ n = csbi.dwSize.X*csbi.dwSize.Y;
+ break;
+ case 2:
+ pos.X = 0;
+ pos.Y = 0;
+ n = csbi.dwSize.X*csbi.dwSize.Y;
+ break;
+ }
+
+ DWORD w;
+ FillConsoleOutputCharacter(StandardOutput,' ',n,pos,&w);
+ SetConsoleCursorPosition(StandardOutput,pos);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MOVE UP
+// ESC [ Pn A Cursor up Pn lines (Pn default=1)
+
+void ansi_move_up(char* buffer)
+{
+ int cnt = *buffer?0:1;
+ while(*buffer)
+ {
+ cnt = cnt*10 + (*buffer++) - '0';
+ }
+
+ COORD pos;
+
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(StandardOutput,&csbi);
+
+ pos.X = csbi.dwCursorPosition.X;
+ pos.Y = ((csbi.dwCursorPosition.Y-cnt)>=0)?(csbi.dwCursorPosition.Y-cnt):0;
+
+ SetConsoleCursorPosition(StandardOutput,pos);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+char codebuf[256];
+unsigned char codeptr;
+
+#define NUM_CODEC 6
+
+typedef void (*LPCODEPROC)(char*);
+
+struct
+{
+ unsigned char cmd;
+ LPCODEPROC proc;
+} codec[NUM_CODEC] = {
+ {'m',ansi_set_screen_attribute},
+ {'H',ansi_set_position},
+ {'K',ansi_erase_line},
+ {'J',ansi_erase_screen},
+ {'A',ansi_move_up},
+ {0,0}
+};
+
+void ansi(SOCKET server,unsigned char data)
+{
+ static _ansi_state state = as_normal;
+ DWORD z;
+ switch( state)
+ {
+ case as_normal:
+ switch(data)
+ {
+ case 0: //eat null codes.
+ break;
+ case 27: //ANSI esc.
+ state = as_esc;
+ break;
+ default: //Send all else to the console.
+ WriteConsole(StandardOutput,&data,1,&z,NULL);
+ break;
+ }
+ break;
+ case as_esc:
+ state = as_esc1;
+ codeptr=0;
+ codebuf[codeptr] = 0;
+ break;
+ case as_esc1:
+ if(data > 64)
+ {
+ int i = 0;
+ codebuf[codeptr] = 0;
+ for(i=0; codec[i].cmd && codec[i].cmd != data; i++);
+ if(codec[i].proc)
+ codec[i].proc(codebuf);
+#ifdef _DEBUG
+ else
+ {
+ char buf[256];
+ wsprintf(buf,"Unknown Ansi code:'%c' (%s)\n",data,codebuf);
+ OutputDebugString(buf);
+ }
+#endif
+ state = as_normal;
+ }
+ else
+ codebuf[codeptr++] = data;
+ break;
+ }
+}
+
+/* EOF */
--- /dev/null
+/* $Id: console.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : console.cpp
+ * AUTHOR : E.Aliberti
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea added to group console-related methods
+ */
+#include <windows.h>
+
+const char * title = "telnet - ";
+
+// Set console's title
+void console_title_connecting (
+ char const* pszHostName,
+ const int nPort
+ )
+{
+ char t[256];
+ wsprintf(t,"%sconnecting to %s:%i", title, pszHostName, nPort);
+ SetConsoleTitle(t);
+}
+
+void console_title_connected (
+ char const* pszHostName,
+ const int nPort
+ )
+{
+ char t[256];
+ wsprintf(t,"%sconnected to %s:%i", title, pszHostName, nPort);
+ SetConsoleTitle(t);
+}
+
+void console_title_not_connected (void)
+{
+ char t[256];
+ wsprintf(t,"%snot connected", title);
+ SetConsoleTitle(t);
+}
+
+/* EOF */
--- /dev/null
+#ifndef _APPS_NET_TELNET_CONSOLE_H
+#define _APPS_NET_TELNET_CONSOLE_H
+void console_title_connecting (
+ char const* pszHostName,
+ const int nPort
+ );
+void console_title_connected (
+ char const* pszHostName,
+ const int nPort
+ );
+void console_title_not_connected (void);
+#endif /* _APPS_NET_TELNET_CONSOLE_H */
--- /dev/null
+/* $Id: helpsock.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : helpsock.cpp
+ * AUTHOR : unknown (sources found on www.telnet.org)
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea Modified to compile under 0.0.16 src tree
+ */
+#include <winsock.h>
+#include <windows.h>
+#include <process.h>
+
+#include "telnet.h"
+
+char const* sockmsg(int ecode)
+{
+ switch(ecode)
+ {
+// programming errors
+// (should never occour in release code?)
+ case WSASYSNOTREADY: return "tcp/ip network not ready";
+ case WSAEINVAL: return "invalid winsock version";
+ case WSAVERNOTSUPPORTED: return "wrong winsock version";
+ case WSANOTINITIALISED: return "winsock not initialized";
+ case WSAEINTR: "The call was canceled";
+ case WSAEINPROGRESS: "A blocking winsock operation is in progress";
+ default: return "unknown winsock error";
+// general TCP problems
+ case WSAENETDOWN: return "winsock has detected that the network subsystem has failed";
+// GetXbyY related errors:
+ case WSAHOST_NOT_FOUND: return "Authoritative Answer Host not found";
+ case WSATRY_AGAIN: return "Non-Authoritative Host not found, or SERVERFAIL";
+ case WSANO_RECOVERY: "Nonrecoverable errors: FORMERR, REFUSED, NOTIMP";
+ case WSANO_DATA: "Valid name, no data record of requested type";
+ }
+}
+
+/* EOF */
--- /dev/null
+/* $Id: main.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : main.cpp
+ * AUTHOR : unknown (sources found on www.telnet.org)
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea Modified to compile under 0.0.16 src tree
+ * 2001-02-27 ea If run with no argument, it asks for a hostname.
+ */
+///////////////////////////////////////////////////////////////////////////////
+//
+// File:
+// main.cpp
+//
+// Purpose:
+// This file provdes the main entry point for the project, and all the
+// global scope support routines.
+//
+// Notes:
+// This file expects to be linked without the C-Runtime. If compiling,
+// please force the entry point symbol to be "main", and do not link in
+// the default librarys.
+// This means that no c-runtime functions can be used anywhere in the
+// project. I expect this will also exclude any MFC based additions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <winsock.h>
+#include <windows.h>
+#include <process.h>
+#include <stdlib.h>
+
+#include "telnet.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// Our simple replacement for the c-runtime includes getting the StandardInput,
+// StandardOutput & StandardError handles, and providing new and delete operators, that work
+// with the win32 heap functions.
+//
+
+//
+// standard handles needed for CRT emulation
+//
+HANDLE hHeap;
+HANDLE StandardInput;
+HANDLE StandardOutput;
+HANDLE StandardError;
+
+//
+// new will use the win32 heap functions.
+//
+void* operator new(unsigned int nSize)
+{
+ return HeapAlloc(hHeap,0,nSize);
+}
+
+//
+// delete operator provides all memory de-allocation.
+// HeapFree doesn't accept NULL.
+//
+void operator delete(void* pMem)
+{
+ if(pMem) HeapFree(hHeap,0,pMem);
+}
+
+
+
+void err(char const* s, ...)
+{
+ char buf [1024];
+ DWORD nout;
+
+ wvsprintf (buf, s, (char*)(s + sizeof(int)));
+ WriteFile (StandardError,"Error: ", 7, & nout, NULL);
+ WriteFile (StandardError, buf, lstrlen(buf), & nout, NULL);
+ WriteFile (StandardError, "\r\n\r\n", 4, & nout, NULL);
+#ifdef _DEBUG
+ OutputDebugString(buf);
+ OutputDebugString("\n");
+#endif
+ ExitProcess (ERROR_SUCCESS);
+}
+
+
+int main(int argc, char * argv[])
+{
+ WSADATA wd;
+ int errn;
+ char name [256] = {'\0'};
+ short port = IPPORT_TELNET; /* default tcp port */
+
+ ///////////////////////////////////////
+ // CRT emulation init
+ // Get the IO handles
+ StandardInput = GetStdHandle(STD_INPUT_HANDLE);
+ StandardOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ StandardError = GetStdHandle(STD_ERROR_HANDLE);
+
+ // Get the heap
+ hHeap = GetProcessHeap();
+
+ // Explicitly force the console into a good mode (actually all we are doing is turning
+ // mouse input off.
+ SetConsoleMode (
+ StandardInput,
+ (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT)
+ );
+
+ ///////////////////////////////////////
+ // Init winsock
+
+ if (errn = WSAStartup (0x0101, & wd))
+ {
+ err(sockmsg(errn));
+ }
+
+ /* hostname */
+ if (1 < argc)
+ {
+ lstrcpy (name, argv [1]);
+ }
+ /*
+ * Default port is IPPORT_TELNET.
+ * User may hand one.
+ */
+ if (3 == argc)
+ {
+ port = atoi (argv[2]);
+ if (port <= 0)
+ {
+ struct servent * service = NULL;
+
+ service = getservbyname (argv[2], "tcp");
+ if (NULL == service)
+ {
+ err("Invalid service name specified");
+ }
+ port = service->s_port;
+ }
+ else
+ {
+ err("Invalid port specified");
+ }
+ }
+ /* Too many arguments */
+ if (3 < argc)
+ {
+ err("Usage: telnet <hostname> [<port>]");
+ }
+ /* No argument */
+ if (1 == argc)
+ {
+ DWORD Count;
+ char *c;
+
+ WriteFile (StandardError,"host: ", 6, & Count, NULL);
+ ReadFile (StandardInput, name, sizeof name, & Count, NULL);
+ c = name;
+ while (*c > ' ') ++ c;
+ *c = '\0';
+ }
+
+ // guess what this does.
+ telnet (name, port);
+
+ //Bye bye...
+ WSACleanup ();
+
+ // Exit process terminates any waiting threads.
+ // (Its the CRT that makes a process close when the main thread exits.
+ // The WinAPI will leave the process as is for as long as it has a
+ // thread any thread.
+ ExitProcess (EXIT_SUCCESS);
+}
+
+/* EOF */
--- /dev/null
+/* $Id: nvt.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : nvt.cpp
+ * AUTHOR : unknown (sources found on www.telnet.org)
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea Modified to compile under 0.0.16 src tree
+ */
+///////////////////////////////////////////////////////////////////////////////
+//
+// file: nvt.cpp
+//
+// purpose: Provides the "bare bones" telnet "Network Virtual Terminal"
+// that is our default. We only se a more capable terminal, if
+// properly requested via the telnet option.
+//
+// refrence: The following excerpt from rfc 854
+//
+///////////////////////////////////////////////////////////////////////////////
+/*
+THE NETWORK VIRTUAL TERMINAL
+
+ The Network Virtual Terminal (NVT) is a bi-directional character
+ device. The NVT has a printer and a keyboard. The printer responds
+ to incoming data and the keyboard produces outgoing data which is
+ sent over the TELNET connection and, if "echoes" are desired, to the
+ NVT's printer as well. "Echoes" will not be expected to traverse the
+ network (although options exist to enable a "remote" echoing mode of
+ operation, no host is required to implement this option). The code
+ set is seven-bit USASCII in an eight-bit field, except as modified
+ herein. Any code conversion and timing considerations are local
+ problems and do not affect the NVT.
+
+ TRANSMISSION OF DATA
+
+ Although a TELNET connection through the network is intrinsically
+ full duplex, the NVT is to be viewed as a half-duplex device
+ operating in a line-buffered mode. That is, unless and until
+ options are negotiated to the contrary, the following default
+ conditions pertain to the transmission of data over the TELNET
+ connection:
+
+ 1) Insofar as the availability of local buffer space permits,
+ data should be accumulated in the host where it is generated
+ until a complete line of data is ready for transmission, or
+ until some locally-defined explicit signal to transmit occurs.
+ This signal could be generated either by a process or by a
+ human user.
+
+ The motivation for this rule is the high cost, to some hosts,
+ of processing network input interrupts, coupled with the
+ default NVT specification that "echoes" do not traverse the
+ network. Thus, it is reasonable to buffer some amount of data
+ at its source. Many systems take some processing action at the
+ end of each input line (even line printers or card punches
+ frequently tend to work this way), so the transmission should
+ be triggered at the end of a line. On the other hand, a user
+ or process may sometimes find it necessary or desirable to
+ provide data which does not terminate at the end of a line;
+ therefore implementers are cautioned to provide methods of
+ locally signaling that all buffered data should be transmitted
+ immediately.
+
+ 2) When a process has completed sending data to an NVT printer
+ and has no queued input from the NVT keyboard for further
+ processing (i.e., when a process at one end of a TELNET
+ connection cannot proceed without input from the other end),
+ the process must transmit the TELNET Go Ahead (GA) command.
+
+ This rule is not intended to require that the TELNET GA command
+ be sent from a terminal at the end of each line, since server
+ hosts do not normally require a special signal (in addition to
+ end-of-line or other locally-defined characters) in order to
+ commence processing. Rather, the TELNET GA is designed to help
+ a user's local host operate a physically half duplex terminal
+ which has a "lockable" keyboard such as the IBM 2741. A
+ description of this type of terminal may help to explain the
+ proper use of the GA command.
+
+ The terminal-computer connection is always under control of
+ either the user or the computer. Neither can unilaterally
+ seize control from the other; rather the controlling end must
+ relinguish its control explicitly. At the terminal end, the
+ hardware is constructed so as to relinquish control each time
+ that a "line" is terminated (i.e., when the "New Line" key is
+ typed by the user). When this occurs, the attached (local)
+ computer processes the input data, decides if output should be
+ generated, and if not returns control to the terminal. If
+ output should be generated, control is retained by the computer
+ until all output has been transmitted.
+
+ The difficulties of using this type of terminal through the
+ network should be obvious. The "local" computer is no longer
+ able to decide whether to retain control after seeing an
+ end-of-line signal or not; this decision can only be made by
+ the "remote" computer which is processing the data. Therefore,
+ the TELNET GA command provides a mechanism whereby the "remote"
+ (server) computer can signal the "local" (user) computer that
+ it is time to pass control to the user of the terminal. It
+ should be transmitted at those times, and only at those times,
+ when the user should be given control of the terminal. Note
+ that premature transmission of the GA command may result in the
+ blocking of output, since the user is likely to assume that the
+ transmitting system has paused, and therefore he will fail to
+ turn the line around manually.
+
+ The foregoing, of course, does not apply to the user-to-server
+ direction of communication. In this direction, GAs may be sent at
+ any time, but need not ever be sent. Also, if the TELNET
+ connection is being used for process-to-process communication, GAs
+ need not be sent in either direction. Finally, for
+ terminal-to-terminal communication, GAs may be required in
+ neither, one, or both directions. If a host plans to support
+ terminal-to-terminal communication it is suggested that the host
+ provide the user with a means of manually signaling that it is
+ time for a GA to be sent over the TELNET connection; this,
+ however, is not a requirement on the implementer of a TELNET
+ process.
+
+ Note that the symmetry of the TELNET model requires that there is
+ an NVT at each end of the TELNET connection, at least
+ conceptually.
+*//*
+
+ THE NVT PRINTER AND KEYBOARD
+
+ The NVT printer has an unspecified carriage width and page length
+ and can produce representations of all 95 USASCII graphics (codes
+ 32 through 126). Of the 33 USASCII control codes (0 through 31
+ and 127), and the 128 uncovered codes (128 through 255), the
+ following have specified meaning to the NVT printer:
+
+ NAME CODE MEANING
+
+ NULL (NUL) 0 No Operation
+ Line Feed (LF) 10 Moves the printer to the
+ next print line, keeping the
+ same horizontal position.
+ Carriage Return (CR) 13 Moves the printer to the left
+ margin of the current line.
+
+ In addition, the following codes shall have defined, but not
+ required, effects on the NVT printer. Neither end of a TELNET
+ connection may assume that the other party will take, or will
+ have taken, any particular action upon receipt or transmission
+ of these:
+
+ BELL (BEL) 7 Produces an audible or
+ visible signal (which does
+ NOT move the print head).
+ Back Space (BS) 8 Moves the print head one
+ character position towards
+ the left margin.
+ Horizontal Tab (HT) 9 Moves the printer to the
+ next horizontal tab stop.
+ It remains unspecified how
+ either party determines or
+ establishes where such tab
+ stops are located.
+ Vertical Tab (VT) 11 Moves the printer to the
+ next vertical tab stop. It
+ remains unspecified how
+ either party determines or
+ establishes where such tab
+ stops are located.
+ Form Feed (FF) 12 Moves the printer to the top
+ of the next page, keeping
+ the same horizontal position.
+
+ All remaining codes do not cause the NVT printer to take any
+ action.
+
+ The sequence "CR LF", as defined, will cause the NVT to be
+ positioned at the left margin of the next print line (as would,
+ for example, the sequence "LF CR"). However, many systems and
+ terminals do not treat CR and LF independently, and will have to
+ go to some effort to simulate their effect. (For example, some
+ terminals do not have a CR independent of the LF, but on such
+ terminals it may be possible to simulate a CR by backspacing.)
+ Therefore, the sequence "CR LF" must be treated as a single "new
+ line" character and used whenever their combined action is
+ intended; the sequence "CR NUL" must be used where a carriage
+ return alone is actually desired; and the CR character must be
+ avoided in other contexts. This rule gives assurance to systems
+ which must decide whether to perform a "new line" function or a
+ multiple-backspace that the TELNET stream contains a character
+ following a CR that will allow a rational decision.
+
+ Note that "CR LF" or "CR NUL" is required in both directions
+ (in the default ASCII mode), to preserve the symmetry of the
+ NVT model. Even though it may be known in some situations
+ (e.g., with remote echo and suppress go ahead options in
+ effect) that characters are not being sent to an actual
+ printer, nonetheless, for the sake of consistency, the protocol
+ requires that a NUL be inserted following a CR not followed by
+ a LF in the data stream. The converse of this is that a NUL
+ received in the data stream after a CR (in the absence of
+ options negotiations which explicitly specify otherwise) should
+ be stripped out prior to applying the NVT to local character
+ set mapping.
+
+ The NVT keyboard has keys, or key combinations, or key sequences,
+ for generating all 128 USASCII codes. Note that although many
+ have no effect on the NVT printer, the NVT keyboard is capable of
+ generating them.
+
+ In addition to these codes, the NVT keyboard shall be capable of
+ generating the following additional codes which, except as noted,
+ have defined, but not reguired, meanings. The actual code
+ assignments for these "characters" are in the TELNET Command
+ section, because they are viewed as being, in some sense, generic
+ and should be available even when the data stream is interpreted
+ as being some other character set.
+
+ Synch
+
+ This key allows the user to clear his data path to the other
+ party. The activation of this key causes a DM (see command
+ section) to be sent in the data stream and a TCP Urgent
+ notification is associated with it. The pair DM-Urgent is to
+ have required meaning as defined previously.
+
+ Break (BRK)
+
+ This code is provided because it is a signal outside the
+ USASCII set which is currently given local meaning within many
+ systems. It is intended to indicate that the Break Key or the
+ Attention Key was hit. Note, however, that this is intended to
+ provide a 129th code for systems which require it, not as a
+ synonym for the IP standard representation.
+
+ Interrupt Process (IP)
+
+ Suspend, interrupt, abort or terminate the process to which the
+ NVT is connected. Also, part of the out-of-band signal for
+ other protocols which use TELNET.
+
+ Abort Output (AO)
+
+ Allow the current process to (appear to) run to completion, but
+ do not send its output to the user. Also, send a Synch to the
+ user.
+
+ Are You There (AYT)
+
+ Send back to the NVT some visible (i.e., printable) evidence
+ that the AYT was received.
+
+ Erase Character (EC)
+
+ The recipient should delete the last preceding undeleted
+ character or "print position" from the data stream.
+
+ Erase Line (EL)
+
+ The recipient should delete characters from the data stream
+ back to, but not including, the last "CR LF" sequence sent over
+ the TELNET connection.
+
+ The spirit of these "extra" keys, and also the printer format
+ effectors, is that they should represent a natural extension of
+ the mapping that already must be done from "NVT" into "local".
+ Just as the NVT data byte 68 (104 octal) should be mapped into
+ whatever the local code for "uppercase D" is, so the EC character
+ should be mapped into whatever the local "Erase Character"
+ function is. Further, just as the mapping for 124 (174 octal) is
+ somewhat arbitrary in an environment that has no "vertical bar"
+ character, the EL character may have a somewhat arbitrary mapping
+ (or none at all) if there is no local "Erase Line" facility.
+ Similarly for format effectors: if the terminal actually does
+ have a "Vertical Tab", then the mapping for VT is obvious, and
+ only when the terminal does not have a vertical tab should the
+
+*/
+
+#include <winsock.h>
+#include <windows.h>
+
+#include "telnet.h"
+
+void nvt(SOCKET server,unsigned char data)
+{
+ DWORD z;
+ switch(data)
+ {
+ case 0: //eat null codes.
+ break;
+ default: //Send all else to the console.
+ WriteConsole(StandardOutput, & data, 1, & z, NULL);
+ break;
+ }
+}
+
+/* EOF */
--- /dev/null
+/* $Id: telnet.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : telnet.cpp
+ * AUTHOR : unknown (sources found on www.telnet.org)
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea Modified to compile under 0.0.16 src tree
+ */
+#include <winsock.h>
+#include <windows.h>
+
+#include "telnet.h"
+#include "console.h"
+
+
+//
+// sock_loop is the thread dedicatd to reading socket input.
+// It waits for data from the socket, and then gives it one byte at a time
+// to the telnet vm to process.
+//
+
+DWORD sock_loop(SOCKET server)
+{
+ char buf[256];
+ unsigned long read;
+ char* scan;
+
+ while( (read = recv(server,buf,sizeof(buf),0)) && read != SOCKET_ERROR )
+ {
+ scan = buf;
+ while(read--)
+ vm(server,*scan++);
+ }
+ int x = WSAGetLastError();
+ return 0;
+}
+
+DWORD input_loop(SOCKET server)
+{
+ char buf[256];
+ DWORD read;
+
+ do
+ {
+ WaitForSingleObject(StandardInput, INFINITE);
+ ReadFile(StandardInput, buf, sizeof buf, & read, NULL);
+ }
+ while(SOCKET_ERROR != send(server, buf, read, 0));
+
+ return 0;
+
+}
+
+void telnet(SOCKET server)
+{
+ DWORD dwThreadIdsock;
+ DWORD dwThreadIdinput;
+ HANDLE threads[2];
+
+
+ threads[0] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) sock_loop, /* thread function */
+ (LPVOID)server, /* argument to thread function */
+ 0, /* use default creation flags */
+ &dwThreadIdsock); /* returns the thread identifier */
+
+ //wait for the other thread to complete any setup negotiation...
+ //Sleep(500); //- this is not the problem - its just bloody stuffing up!
+
+ threads[1] = CreateThread(
+ NULL, /* no security attributes */
+ 0, /* use default stack size */
+ (LPTHREAD_START_ROUTINE) input_loop, /* thread function */
+ (LPVOID)server, /* argument to thread function */
+ 0, /* use default creation flags */
+ &dwThreadIdinput); /* returns the thread identifier */
+
+
+ WaitForMultipleObjects(2,threads,FALSE,INFINITE);
+}
+
+
+//
+// connect to the hostname,port
+//
+void telnet(
+ char const* pszHostName,
+ const short nPort)
+{
+ unsigned long ip;
+ if((*pszHostName <= '9') && (*pszHostName >= '0'))
+ {
+ if((ip = inet_addr(pszHostName)) == INADDR_NONE)
+ err("invalid host IP address given");
+ }
+ else
+ {
+ hostent* ent = gethostbyname(pszHostName);
+ if(!ent)
+ err(sockmsg(WSAGetLastError()));
+ ip = *(unsigned long*)(ent->h_addr);
+ }
+
+ sockaddr_in name;
+ name.sin_family = AF_INET;
+ name.sin_port = htons(nPort);
+ name.sin_addr = *(in_addr*)&ip;
+
+ console_title_connecting (pszHostName, nPort);
+
+ SOCKET server;
+
+ if((server = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
+ err(sockmsg(WSAGetLastError()));
+
+ if(SOCKET_ERROR == connect(server,(sockaddr*)&name,sizeof(sockaddr)))
+ err(sockmsg(WSAGetLastError()));
+
+ console_title_connected (pszHostName, nPort);
+
+ telnet(server);
+
+ closesocket(server);
+}
+
+/* EOF */
--- /dev/null
+#ifndef _APPS_NET_TELNET_H
+#define _APPS_NET_TELNET_H
+//Global Handles
+extern HANDLE StandardInput;
+extern HANDLE StandardOutput;
+extern HANDLE StandardError;
+
+extern char const* sockmsg(int ecode);
+extern void err(char const* s,...);
+
+extern void telnet(char const* pszHostName,const short nPort);
+extern void vm(SOCKET,unsigned char);
+
+// terminal handlers:
+void ansi(SOCKET server,unsigned char data);
+void nvt(SOCKET server,unsigned char data);
+
+// helpsock
+char const* sockmsg(int ecode);
+
+// command shell
+int shell(char const* pszHostName,const int nPort);
+
+#endif /* ndef _APPS_NET_TELNET_H */
--- /dev/null
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "ReactOS Telnet Win32 Client\0"
+ VALUE "FileVersion", RES_STR_FILE_VERSION
+ VALUE "InternalName", "telnet\0"
+ VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
+ VALUE "OriginalCopyright", "Anonymous sources found at http://www.telnet.org/\0"
+ VALUE "OriginalFilename", "telnet.exe\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
--- /dev/null
+/* $Id: vm.cpp,v 1.1 2001/01/27 22:38:43 ea Exp $
+ *
+ * FILE : vm.cpp
+ * AUTHOR : unknown (sources found on www.telnet.org)
+ * PROJECT : ReactOS Operating System
+ * DESCRIPTION: telnet client for the W32 subsystem
+ * DATE : 2001-01-21
+ * REVISIONS
+ * 2001-02-21 ea Modified to compile under 0.0.16 src tree
+ */
+#include <winsock.h>
+#include <windows.h>
+
+#include "telnet.h"
+
+// NAME CODE MEANING
+// NVT codes
+#define NUL 0 // No Operation
+#define BEL 7 // BELL
+#define BS 8 // Back Space
+#define HT 9 // Horizontal Tab
+#define LF 10 // Line Feed
+#define VT 11 // Vertical Tab
+#define FF 12 // Form Feed
+#define CR 13 // Carriage Return
+
+// telnet command codes
+#define SE 240 // End of subnegotiation parameters.
+#define NOP 241 // No operation.
+#define DM 242 // Data Mark
+#define BRK 243 // Break
+#define IP 244 // Interrupt Process
+#define AO 245 // Abort output
+#define AYT 246 // Are You There
+#define EC 247 // Erase character
+#define EL 248 // Erase Line
+#define GA 249 // Go ahead
+#define SB 250 // SuBnegotiate
+#define WILL 251 //
+#define WONT 252 //
+#define DO 253 //
+#define DONT 254 //
+#define IAC 255 // Interpret As Command
+
+//Telnet options:
+// 0x00 - binary mode
+// 0x01 - Local Echo
+// 0x03 - Suppress GA (char at a time)
+// 0x05 - status
+// 0x06 - Timing Mark
+//
+// do 0x25 - zub?
+//
+// 0xff - Extended Options List
+
+enum _option
+{
+ TOPT_BIN = 0, // Binary Transmission
+ TOPT_ECHO = 1, // Echo
+ TOPT_RECN = 2, // Reconnection
+ TOPT_SUPP = 3, // Suppress Go Ahead
+ TOPT_APRX = 4, // Approx Message Size Negotiation
+ TOPT_STAT = 5, // Status
+ TOPT_TIM = 6, // Timing Mark
+ TOPT_REM = 7, // Remote Controlled Trans and Echo
+ TOPT_OLW = 8, // Output Line Width
+ TOPT_OPS = 9, // Output Page Size
+ TOPT_OCRD = 10, // Output Carriage-Return Disposition
+ TOPT_OHT = 11, // Output Horizontal Tabstops
+ TOPT_OHTD = 12, // Output Horizontal Tab Disposition
+ TOPT_OFD = 13, // Output Formfeed Disposition
+ TOPT_OVT = 14, // Output Vertical Tabstops
+ TOPT_OVTD = 15, // Output Vertical Tab Disposition
+ TOPT_OLD = 16, // Output Linefeed Disposition
+ TOPT_EXT = 17, // Extended ASCII
+ TOPT_LOGO = 18, // Logout
+ TOPT_BYTE = 19, // Byte Macro
+ TOPT_DATA = 20, // Data Entry Terminal
+ TOPT_SUP = 21, // SUPDUP
+ TOPT_SUPO = 22, // SUPDUP Output
+ TOPT_SNDL = 23, // Send Location
+ TOPT_TERM = 24, // Terminal Type
+ TOPT_EOR = 25, // End of Record
+ TOPT_TACACS = 26, // TACACS User Identification
+ TOPT_OM = 27, // Output Marking
+ TOPT_TLN = 28, // Terminal Location Number
+ TOPT_3270 = 29, // Telnet 3270 Regime
+ TOPT_X3 = 30, // X.3 PAD
+ TOPT_NAWS = 31, // Negotiate About Window Size
+ TOPT_TS = 32, // Terminal Speed
+ TOPT_RFC = 33, // Remote Flow Control
+ TOPT_LINE = 34, // Linemode
+ TOPT_XDL = 35, // X Display Location
+ TOPT_ENVIR = 36,// Telnet Environment Option
+ TOPT_AUTH = 37, // Telnet Authentication Option
+ TOPT_NENVIR = 39,// Telnet Environment Option
+ TOPT_EXTOP = 255, // Extended-Options-List
+ TOPT_ERROR = 256 // Magic number
+};
+
+// Wanted by linux box:
+// 37 - TOPT_AUTH
+// 24 - TOPT_TERM
+
+enum _verb
+{
+ verb_sb = 250,
+ verb_will = 251,
+ verb_wont = 252,
+ verb_do = 253,
+ verb_dont = 254
+};
+
+enum _state
+{
+ state_data, //we expect a data byte
+ state_code, //we expect a code
+ state_option //we expect an option
+};
+
+int option_error(_verb,_option,int,SOCKET);
+
+typedef void(*LPOPTIONPROC)(SOCKET,_verb,_option);
+typedef void(*LPDATAPROC)(SOCKET,unsigned char data);
+
+///////////////////////////////////////////////////////////////////////////////
+
+inline void yesreply(SOCKET server, _verb verb,_option option)
+{
+ unsigned char buf[3];
+ buf[0] = IAC;
+ buf[1] = (verb==verb_do)?WILL:(verb==verb_dont)?WONT:(verb==verb_will)?DO:DONT;
+ buf[2] = (unsigned char)option;
+ send(server,(char*)buf,3,0);
+}
+
+inline void noreply(SOCKET server, _verb verb,_option option)
+{
+ unsigned char buf[3];
+ buf[0] = IAC;
+ buf[1] = (verb==verb_do)?WONT:(verb==verb_dont)?WILL:(verb==verb_will)?DONT:DO;
+ buf[2] = (unsigned char)option;
+ send(server,(char*)buf,3,0);
+}
+
+inline void askfor(SOCKET server, _verb verb,_option option)
+{
+ unsigned char buf[3];
+ buf[0] = IAC;
+ buf[1] = (unsigned char)verb;
+ buf[2] = (unsigned char)option;
+ send(server,(char*)buf,3,0);
+}
+
+
+void ddww_error(SOCKET server,_verb verb,_option option)
+{
+#ifdef _DEBUG
+ char tmp[256];
+ wsprintf(tmp,"Unknown Option Code: %s, %i\n",(verb==verb_do)?"DO":(verb==verb_dont)?"DON'T":(verb==verb_will)?"WILL":"WONT",(int)option);
+ OutputDebugString(tmp);
+#endif
+
+ switch(verb)
+ {
+ case verb_will: // server wants to support something
+ noreply(server,verb,option); // I don't want that.
+ break;
+ case verb_wont: // server waants to disable support
+ return; // don't confirm - already disabled.
+ case verb_do: // server wants me to support something
+ noreply(server,verb,option); //I won't do that
+ break;
+ case verb_dont: // server wants me to disable something
+ return; // don't worry, we don't do that anyway (I hope :)
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Option ECHO & SUPPRESS GA
+//
+// These options are curiously intertwined...
+// The Win32 console doesn't support ECHO_INPUT (echo) if
+// LINE_INPUT (==GA) isn't set.
+// I can't see how to code this negotiation without using
+// some form of Lock-Step algorythm
+// ie: if("WILL ECHO")
+// Send "DO SUPP"
+// if("WILL SUPP")
+// Send "DO ECHO"
+// else
+// Send "DONT ECHO"
+
+
+void ddww_echo(SOCKET server,_verb verb, _option option)
+{
+ DWORD mode;
+ GetConsoleMode(StandardInput, & mode); // ENABLE_ECHO_INPUT
+
+ int set = !(mode & ENABLE_ECHO_INPUT);
+
+ switch(verb)
+ {
+ case verb_will: // server wants to echo stuff
+ if(set) return; //don't confirm - already set.
+ SetConsoleMode(StandardInput,mode & (~ENABLE_ECHO_INPUT));
+ break;
+ case verb_wont: // server don't want to echo
+ if(!set) return; //don't confirm - already unset.
+ SetConsoleMode(StandardInput,mode | ENABLE_ECHO_INPUT);
+ break;
+ case verb_do: // server wants me to loopback
+ noreply(server,verb,option);
+ return;
+ case verb_dont: // server doesn't want me to echo
+ break; // don't bother to reply - I don't
+ }
+ yesreply(server,verb,option);
+}
+
+
+void ddww_supp(SOCKET server,_verb verb,_option option) //Suppress GA
+{
+ DWORD mode;
+ GetConsoleMode(StandardInput,&mode); // ENABLE_LINE_INPUT
+
+ int set = !(mode & ENABLE_LINE_INPUT);
+
+ switch(verb)
+ {
+ case verb_will: // server wants to suppress GA's
+ if(set) break; //don't confirm - already set.
+ SetConsoleMode(StandardInput,mode & (~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)));
+ askfor(server,verb_do,TOPT_SUPP);
+ askfor(server,verb_will,TOPT_SUPP);
+ askfor(server,verb_do,TOPT_ECHO);
+ break;
+ case verb_wont: // server wants to send GA's
+ if(!set) break; //don't confirm - already unset.
+ SetConsoleMode(StandardInput,mode | ENABLE_LINE_INPUT);
+ askfor(server,verb_dont,TOPT_SUPP);
+ askfor(server,verb_wont,TOPT_SUPP);
+ break;
+ case verb_do: // server wants me to suppress GA's
+ if(set) break;
+ askfor(server,verb_do,TOPT_SUPP);
+ break;
+ case verb_dont: // server wants me to send GA's
+ if(!set) break;
+ askfor(server,verb_dont,TOPT_SUPP);
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Option TERMINAL-TYPE
+
+void ddww_term(SOCKET server,_verb verb,_option option) //Subnegotiate terminal type
+{
+ switch(verb)
+ {
+ case verb_will:
+ noreply(server,verb,option); // I don't want terminal info
+ break;
+ case verb_wont:
+ //dat be cool - its not going to send. no need to confirm
+ break;
+ case verb_do:
+ yesreply(server,verb,option); //I'll send it when asked
+ break;
+ case verb_dont://Ok - I won't
+ break;
+ }
+}
+
+// TERMINAL TYPE subnegotation
+enum
+{
+ SB_TERM_IS = 0,
+ SB_TERM_SEND = 1
+};
+
+#define NUM_TERMINALS 2
+
+struct
+{
+ char* name;
+ LPDATAPROC termproc;
+ //pre requsites.
+} terminal[NUM_TERMINALS] = {
+ { "NVT", nvt },
+ { "ANSI", ansi }
+};
+
+int term_index = 0;
+
+void sbproc_term(SOCKET server,unsigned char data)
+{
+
+ if(data == SB_TERM_SEND)
+ {
+ if(term_index == NUM_TERMINALS)
+ term_index = 0;
+ else
+ term_index++;
+ char buf[16]; //pls limit
+ buf[0] = IAC;
+ buf[1] = SB;
+ buf[2] = TOPT_TERM;
+ buf[3] = SB_TERM_IS;
+ lstrcpy(&buf[4],terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].name);
+ int nlen = lstrlen(&buf[4]);
+ buf[4+nlen] = IAC;
+ buf[5+nlen] = SE;
+ send(server,buf,4+nlen+2,0);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct
+{
+ _option option;
+ LPOPTIONPROC OptionProc;
+ LPDATAPROC DataProc;
+} ol[] = {
+ {TOPT_ECHO, ddww_echo, NULL},
+ {TOPT_SUPP, ddww_supp, NULL},
+ {TOPT_TERM, ddww_term, sbproc_term},
+ {TOPT_ERROR, ddww_error, NULL}
+};
+
+
+void vm(SOCKET server,unsigned char code)
+{
+//These vars are the finite state
+ static int state = state_data;
+ static _verb verb = verb_sb;
+ static LPDATAPROC DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc;
+// for index
+ int i=0;
+
+//Decide what to do (state based)
+ switch(state)
+ {
+ case state_data:
+ switch(code)
+ {
+ case IAC: state = state_code; break;
+ default: DataProc(server,code);
+ }
+ break;
+ case state_code:
+ state = state_data;
+ switch(code)
+ {
+ // State transition back to data
+ case IAC:
+ DataProc(server,code);
+ break;
+ // Code state transitions back to data
+ case SE:
+ DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc;
+ break;
+ case NOP:
+ break;
+ case DM:
+ break;
+ case BRK:
+ break;
+ case IP:
+ break;
+ case AO:
+ break;
+ case AYT:
+ break;
+ case EC:
+ break;
+ case EL:
+ break;
+ case GA:
+ break;
+ // Transitions to option state
+ case SB:
+ verb = verb_sb;
+ state = state_option;
+ break;
+ case WILL:
+ verb = verb_will;
+ state = state_option;
+ break;
+ case WONT:
+ verb = verb_wont;
+ state = state_option;
+ break;
+ case DO:
+ verb = verb_do;
+ state = state_option;
+ break;
+ case DONT:
+ verb = verb_dont;
+ state = state_option;
+ break;
+ }
+ break;
+ case state_option:
+ state = state_data;
+
+ //Find the option entry
+ for(
+ i = 0;
+ ol[i].option != TOPT_ERROR && ol[i].option != code;
+ i++);
+
+ //Do some verb specific stuff
+ if(verb == verb_sb)
+ DataProc = ol[i].DataProc;
+ else
+ ol[i].OptionProc(server,verb,(_option)code);
+ break;
+ }
+}
+
+/* EOF */