📄 hclecho.cpp
字号:
// hclecho.cpp// a Hummingbird inetd-compatible echo server// copyright SafeTP Development Group, Inc., 2000 Terms of use are as specified in license.txt#include <stdio.h> // perror, FILE fns#include <errno.h> // _sys_errlist#include <stdlib.h> // exit#include <string.h> // strcpy, strlen#include <dir.h> // getcwd#include <ctype.h> // isdigit#include "minwin.h" // api#include <winsock.h> // SOCKET#include <winreg.h> // registry stuff//#include "hcllib.h" // InitInetd, ShutdownInetd#include "syserr.h" // xsyserror// global log fileFILE *log = NULL;// this differs from xsyserror in that this fn returns (while// xsyserror throws an exception)void sockerr(char const *msg){ fprintf(log, "%s\n", (char const*)sysErrorString(msg));}void sockerrcode(char const *msg, int code){ fprintf(log, "%s\n", (char const*)sysErrorCodeString(code, msg));}// more hackingHINSTANCE getInstance(){ return (HINSTANCE)GetModuleHandle(NULL);}// what I eventually want to wrap in its own moduleSOCKET inetdStartupHook(int &argc, char **&argv){ // first, test to see if we've been started under HCL inetd if (!( argc > 1 && isdigit(argv[1][0]) )) { // the first character is always a digit under HCL inetd, and // since it was not in this case, we are not running under HCL inetd return INVALID_SOCKET; } // try to load the DLL that communicates with the inetd server HINSTANCE hHCLDLLInst = LoadLibrary("HCLLIB.DLL"); if (hHCLDLLInst == NULL) { xsyserror("LoadLibrary", "couldn't load HCLLIB.DLL, required for HCL inetd operation."); } // get a pointer to the function we need typedef SOCKET (*LPDLLInitInetd)(LPSTR lpszCmdLine); LPDLLInitInetd DLLInitInetd; DLLInitInetd = (LPDLLInitInetd)GetProcAddress(hHCLDLLInst, "DLLInitInetd"); if (!DLLInitInetd) { xsyserror("GetProcAddress", "trying to get address of DLLInitInetd from HCLLIB.DLL"); } // get the acceptance socket SOCKET socket; socket = DLLInitInetd(argv[1]); // This must be the command line passed // to the daemon application or argv[1] // for console applications. // On return lpszCmdLine will have // The optional parameters as specified // in Inetd. // SM: Since we're passing argv[1], inetd will toast it (no // big deal), and we'll increment argv on return (and assume // the caller won't try to read argv[0] as its executable name). // SM: I just noticed that DLLInitInetd returns SOCKET_ERROR instead // of INVALID_SOCKET on error.. that's a mistake on the part of // the interface designer, because technically SOCKET_ERROR is // in the range of valid socket descriptors (whereas // INVALID_SOCKET is not). // SM: Turns out they're the same... oh well. if (socket == SOCKET_ERROR) { // this is not just a simple failure to run under inetd, because // we already detected that the first argument was numeric xfailure("DLLInitInetd claims not to recognize my first argument.. " "did you specify a numeric first argument by mistake?"); } // having successfully processed the first argument, adjust argc // and argv so it looks like it wasn't there at all (note that this // is slightly problematic, in that argv[0], which wasn't involved // at all, has now effectively been clobbered) argc--; argv++; // put socket in blocking mode { // we need a dummy window handle... HWND dummyWindow = CreateWindow( "STATIC", // address of registered class name "", // address of window name WS_OVERLAPPED, // window style 0, // horizontal position of window 0, // vertical position of window 0, // window width 0, // window height NULL, // handle of parent or owner window NULL, // handle of menu or child-window identifier getInstance(), // handle of application instance NULL // address of window-creation data ); if (!dummyWindow) { xsyserror("CreateWindow", "making a dummy window"); } // must "reset" WSAAsyncSelect first, it appears if (0 != WSAAsyncSelect(socket, dummyWindow, 0,0)) { xsyserror("WSAAsyncSelect"); } // do the damned mode change unsigned long blockmode = 0; if (0 != ioctlsocket(socket, FIONBIO, &blockmode)) { xsyserror("ioctlsocket"); } // get rid of the dummy window if (!DestroyWindow(dummyWindow)) { sockerr("DestroyWindow"); // continue anyway } } // ok, we're in business return socket;}int entry(int argc, char *argv[]){ // try to log stuff FILE *log = fopen("d:\\temp\\hclecho.log", "a");// FILE *log = fopen("c:\\sftpd\\hclecho\\hclecho.log", "a"); if (!log) { // cause a distinguished segfault (I'm sure to see it) *((char*)0xabcd0001) = 0; } // log initial arguments { fprintf(log, "echo server started, arguments:"); loopi(argc) { fprintf(log, " %s", argv[i]); } fprintf(log, "\n"); } // who am i? { char buf[80]; DWORD buflen=80; if (!GetUserName(buf, &buflen)) { sockerr("GetUserName"); } fprintf(log, "user name is \"%s\"\n", buf); } // where am I? { char buf[80]; if (!getcwd(buf, 80)) { sockerr("getcwd"); } else { fprintf(log, "getcwd returned \"%s\"\n", buf); } } // try to access a protected registry key { DWORD err; #define CKERR(msg) \ if (err != ERROR_SUCCESS) { \ sockerrcode(msg, err); \ break; \ } HKEY hkey = NULL; do { // open the Protected key // (assumption: hkey is unchanged when RegOpenKeyEx fails) // the return value for 'access denied' is 5 err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, // handle of open key "SOFTWARE\\UCB\\SafeTP\\Protected", // address of name of subkey to open 0, // reserved KEY_ALL_ACCESS, // security access mask &hkey // address of handle of open key ); CKERR("RegOpenKeyEx"); // read something // (on my system, I created the 'secret' value in regedit) DWORD type; char buf[80]; DWORD buflen = 80; err = RegQueryValueEx( hkey, // handle of key to query "secret", // address of name of value to query NULL, // reserved &type, // address of buffer for value type buf, // address of data buffer &buflen // address of data buffer size ); CKERR("RegQueryValueEx"); fprintf(log, "read \"%s\" from secret value\n", buf); // write something strcpy(buf, "hehe, a new secret!"); err = RegSetValueEx( hkey, // handle of key to set value for "writtenSecret", // address of value to set 0, // reserved REG_SZ, // flag for value type buf, // address of value data strlen(buf) // size of value data ); CKERR("RegSetValueEx"); } while (0); // above, let 'break' mean 'goto here' // close the registry key if we successfully opened it if (hkey != NULL) { err = RegCloseKey(hkey); if (err != ERROR_SUCCESS) { sockerrcode("RegCloseKey", err); } else { fprintf(log, "all registry operations succeeded\n"); } } #undef CKERR } // WSAStartup MUST be called before InitInetd { WSADATA wsdata; if (0 != WSAStartup(0x0101, &wsdata)) { sockerr("WSAStartup"); return 1; } } // get the acceptance socket SOCKET socket = inetdStartupHook(argc, argv); if (socket == INVALID_SOCKET) { fprintf(log, "exiting because not run from inetd\n"); MessageBox(NULL, "Must be run from Inetd", "HCL Echo", MB_OK); return 1; } // log final arguments { fprintf(log, "final arguments:"); loopi(argc) { fprintf(log, " %s", argv[i]); } fprintf(log, "\n"); } // do what the echo server does int charCount = 0; for (;; charCount++) { // read a character char ch; int len = recv(socket, &ch, 1, 0); if (len == 0) { // eof break; } if (len < 0) { xsyserror("recv"); } // write that character len = send(socket, &ch, 1, 0); if (len != 1) { xsyserror("recv"); } } if (0 != closesocket(socket)) { sockerr("closesocket"); } if (0 != WSACleanup()) { sockerr("WSACleanup"); } fprintf(log, "done, echoed %d characters\n", charCount); fclose(log); return 0;}int main(int argc, char *argv[]){ try { return entry(argc, argv); } catch (xBase &x) { printf("Exception caught: %s\n", x.why()); WSACleanup(); return 4; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -