diff options
Diffstat (limited to 'src/windows/wintel/telnet.c')
-rw-r--r-- | src/windows/wintel/telnet.c | 814 |
1 files changed, 814 insertions, 0 deletions
diff --git a/src/windows/wintel/telnet.c b/src/windows/wintel/telnet.c new file mode 100644 index 000000000..a334cf9e1 --- /dev/null +++ b/src/windows/wintel/telnet.c @@ -0,0 +1,814 @@ +/**************************************************************************** + + PROGRAM: telnet.c + + PURPOSE: Windows networking kernel - Telnet + + FUNCTIONS: + + WinMain() - calls initialization function, processes message loop + InitApplication() - initializes window data and registers window + InitInstance() - saves instance handle and creates main window + MainWndProc() - processes messages + About() - processes messages for "About" dialog box + + COMMENTS: + + Windows can have several copies of your application running at the + same time. The variable hInst keeps track of which instance this + application is so that processing will be to the correct window. + +****************************************************************************/ + +#include <windows.h> +#include <string.h> +#include "telnet.h" +#include "auth.h" + +HANDLE hInst; /* current instance */ +HWND hWnd; /* Main window handle. */ +CONFIG *tmpConfig; +GLOBALHANDLE hGlobalMem, hTitleMem; +CONNECTION *con = NULL; +char hostdata[MAXGETHOSTSTRUCT]; +HGLOBAL ghCon; +SCREEN *fpScr; +int debug = 1; + +char __near strTmp[1024]; + +BOOL bAutoConnection = FALSE; +char szAutoHostName[64]; +char szUserName[64]; +char szHostName[64]; + +#ifdef KRB4 + #define WINDOW_CLASS "telnetWClass_4" +#endif + +#ifdef KRB5 + krb5_context k5_context; + #define WINDOW_CLASS "telnetWClass" +#endif + +/*+************************************************************************** + + FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) + + PURPOSE: calls initialization function, processes message loop + + COMMENTS: + + Windows recognizes this function by name as the initial entry point + for the program. This function calls the application initialization + routine, if no other instance of the program is running, and always + calls the instance initialization routine. It then executes a message + retrieval and dispatch loop that is the top-level control structure + for the remainder of execution. The loop is terminated when a WM_QUIT + message is received, at which time this function exits the application + instance by returning the value passed by PostQuitMessage(). + + If this function must abort before entering the message loop, it + returns the conventional value NULL. + +****************************************************************************/ + +int PASCAL +WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow) +HANDLE hInstance; /* current instance */ +HANDLE hPrevInstance; /* previous instance */ +LPSTR lpCmdLine; /* command line */ +int nCmdShow; /* show-window type (open/icon) */ +{ + MSG msg; /* message */ + + if (!hPrevInstance) + if (!InitApplication(hInstance)) /* Initialize shared things */ + return (FALSE); /* Exits if unable to initialize */ + + /* Perform initializations that apply to a specific instance */ + + if (lpCmdLine[0]) { + bAutoConnection = TRUE; + lstrcpy((char *) szAutoHostName, lpCmdLine); + } + else bAutoConnection = FALSE; + + if (!InitInstance(hInstance, nCmdShow)) + return (FALSE); + + /* Acquire and dispatch messages until a WM_QUIT message is received. */ + + while (GetMessage(&msg, NULL, NULL, NULL)) { + TranslateMessage(&msg); /* Translates virtual key codes */ + DispatchMessage(&msg); /* Dispatches message to window */ + } + return (msg.wParam); /* Returns the value from PostQuitMessage */ +} + + +/*+************************************************************************** + + FUNCTION: InitApplication(HANDLE) + + PURPOSE: Initializes window data and registers window class + + COMMENTS: + + This function is called at initialization time only if no other + instances of the application are running. This function performs + initialization tasks that can be done once for any number of running + instances. + + In this case, we initialize a window class by filling out a data + structure of type WNDCLASS and calling the Windows RegisterClass() + function. Since all instances of this application use the same window + class, we only need to do this when the first instance is initialized. + + +****************************************************************************/ + +BOOL +InitApplication(hInstance) +HANDLE hInstance; /* current instance */ +{ + WNDCLASS wc; + + ScreenInit(hInstance); + + /* Fill in window class structure with parameters that describe the */ + /* main window. */ + + wc.style = CS_HREDRAW|CS_VREDRAW; /* Class style(s). */ + wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for */ + /* windows of this class. */ + wc.cbClsExtra = 0; /* No per-class extra data. */ + wc.cbWndExtra = 0; /* No per-window extra data. */ + wc.hInstance = hInstance; /* Application that owns the class. */ + wc.hIcon = NULL; //LoadIcon(hInstance, "NCSA"); + wc.hCursor = NULL; //Cursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; //GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; /* Name of menu resource in .RC file. */ + wc.lpszClassName = WINDOW_CLASS; /* Name used in call to CreateWindow. */ + + /* Register the window class and return success/failure code. */ + return (RegisterClass(&wc)); +} + + +/*+************************************************************************** + + FUNCTION: InitInstance(HANDLE, int) + + PURPOSE: Saves instance handle and creates main window + + COMMENTS: + + This function is called at initialization time for every instance of + this application. This function performs initialization tasks that + cannot be shared by multiple instances. + + In this case, we save the instance handle in a static variable and + create and display the main program window. + +****************************************************************************/ +BOOL +InitInstance(hInstance, nCmdShow) + HANDLE hInstance; /* Current instance identifier. */ + int nCmdShow; /* Param for first ShowWindow() call. */ +{ + int xScreen = 0, yScreen = 0; + + /* Save the instance handle in static variable, which will be used in */ + /* many subsequence calls from this application to Windows. */ + + hInst = hInstance; + + /* Create a main window for this application instance. */ + hWnd = CreateWindow( + WINDOW_CLASS, /* See RegisterClass() call. */ + "TCPWin", /* Text for window title bar. */ + WS_SYSMENU, /* Window style. */ + xScreen/3, /* Default horizontal position. */ + yScreen/3, /* Default vertical position. */ + xScreen/3, /* Default width. */ + yScreen/3, /* Default height. */ + NULL, /* Overlapped windows have no parent. */ + NULL, /* Use the window class menu. */ + hInstance, /* This instance owns this window. */ + NULL /* Pointer not needed. */ + ); + if (!hWnd) + return (FALSE); + +// ShowWindow(hWnd, SW_SHOW); /* Show the window */ +// UpdateWindow(hWnd); /* Sends WM_PAINT message */ + + { + WSADATA wsaData; + if (WSAStartup(0x0101, &wsaData) != 0) { /* Initialize the network */ + MessageBox(NULL, "Couldn't initialize Winsock!", + NULL, MB_OK | MB_ICONEXCLAMATION); + return FALSE; + } + } + + if (! OpenTelnetConnection()) { + WSACleanup(); + return(FALSE); + } + + #ifdef KRB5 + krb5_init_context(&k5_context); + krb5_init_ets(k5_context); + #endif + return (TRUE); +} + +/*+*************************************************************************** + + FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM) + + PURPOSE: Processes messages + + MESSAGES: + + WM_COMMAND - application menu (About dialog box) + WM_DESTROY - destroy window + +****************************************************************************/ + +long FAR PASCAL +MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + HSCREEN hgScr; + SCREEN *fpScr; + HGLOBAL hBuffer; + LPSTR lpBuffer; + char c; + int iEvent, namelen, cnt, ret; + char buf[1024]; + struct sockaddr_in name; + struct sockaddr_in remote_addr; + struct hostent *remote_host; + char *tmpCommaLoc; + + switch (message) { + + case WM_MYSCREENCHANGEBKSP: + if (!con) break; + con->backspace = wParam; + if (con->backspace == VK_BACK) { + con->ctrl_backspace = 0x7f; + WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, + INI_BACKSPACE_BS, TELNET_INI); + } + else { + con->ctrl_backspace = VK_BACK; + WritePrivateProfileString(INI_TELNET, INI_BACKSPACE, + INI_BACKSPACE_DEL, TELNET_INI); + } + GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", buf, 128, + TELNET_INI); + tmpCommaLoc = strchr(buf, ','); + if (tmpCommaLoc) { + tmpCommaLoc++; + if (con->backspace == VK_BACK) + strcpy(tmpCommaLoc, INI_HOST_BS); + else + strcpy(tmpCommaLoc, INI_HOST_DEL); + } + WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI); + break; + + case WM_MYSCREENCHAR: + if (!con) break; + if (wParam == VK_BACK) + wParam = con->backspace; + else + if (wParam == 0x7f) + wParam = con->ctrl_backspace; + TelnetSend(con->ks, (char *)&wParam, 1, NULL); + break; + + case WM_MYSYSCHAR: + if (!con) break; + c = (char) wParam; + switch (c) { + case 'f': + getsockname(con->socket, (struct sockaddr *) &name, + (int *) &namelen); + wsprintf(buf, "ftp %d.%d.%d.%d\n", + name.sin_addr.S_un.S_un_b.s_b1, + name.sin_addr.S_un.S_un_b.s_b2, + name.sin_addr.S_un.S_un_b.s_b3, + name.sin_addr.S_un.S_un_b.s_b4); + TelnetSend(con->ks, buf, lstrlen(buf), NULL); + break; + case 'x': + hgScr = con->hScreen; + fpScr = (SCREEN *) GlobalLock(hgScr); + if (fpScr == NULL) break; + PostMessage(fpScr->hWnd, WM_CLOSE, NULL, NULL); + break; + + } + break; + + case WM_MYSCREENBLOCK: + if (!con) break; + hBuffer = (HGLOBAL) wParam; + lpBuffer = GlobalLock(hBuffer); + TelnetSend(con->ks, lpBuffer, lstrlen(lpBuffer), NULL); + GlobalUnlock(hBuffer); + break; + + case WM_MYSCREENCLOSE: + if (!con) break; + kstream_destroy(con->ks); + DestroyWindow(hWnd); + break; + + case WM_QUERYOPEN: + return(0); + break; + + case WM_DESTROY: /* message: window being destroyed */ + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + + case WM_NETWORKEVENT: + iEvent = WSAGETSELECTEVENT(lParam); + + switch (iEvent) { + + case FD_READ: + cnt = recv(con->socket, buf, 1024, NULL); + /* + The following line has been removed until kstream supports + non-blocking IO or larger size reads (jrivlin@fusion.com). + */ + /* cnt = kstream_read(con->ks, buf, 1024); */ + buf[cnt] = 0; + parse((CONNECTION *) con, (unsigned char *) buf, cnt); + ScreenEm(buf, cnt, con->hScreen); + break; + + case FD_CLOSE: + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + + case FD_CONNECT: + ret = WSAGETSELECTERROR(lParam); + if (ret) { + wsprintf(buf, "Error %d on Connect", ret); + OutputDebugString (buf); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + } + start_negotiation(con->ks); + break; + } + break; + + case WM_HOSTNAMEFOUND: + ret = WSAGETASYNCERROR(lParam); + if (ret) { + wsprintf(buf, "Error %d on GetHostbyName", ret); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + kstream_destroy(con->ks); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + WSACleanup(); + PostQuitMessage(0); + break; + } + remote_host = (struct hostent *) hostdata; + remote_addr.sin_family = AF_INET; + remote_addr.sin_addr.S_un.S_un_b.s_b1 = remote_host->h_addr[0]; + remote_addr.sin_addr.S_un.S_un_b.s_b2 = remote_host->h_addr[1]; + remote_addr.sin_addr.S_un.S_un_b.s_b3 = remote_host->h_addr[2]; + remote_addr.sin_addr.S_un.S_un_b.s_b4 = remote_host->h_addr[3]; + #ifdef KRB4 + remote_addr.sin_port = htons(23); + #endif + #ifdef KRB5 + remote_addr.sin_port = htons(13131); + #endif + + connect(con->socket, (struct sockaddr*) &remote_addr, + sizeof(struct sockaddr)); + break; + + case WM_MYSCREENSIZE: + con->width = LOWORD(lParam); /* width in characters */ + con->height = HIWORD(lParam); /* height in characters */ + if (con->bResizeable && con->ks) + send_naws(con); + wsprintf(buf, "%d", con->height); + WritePrivateProfileString(INI_TELNET, INI_HEIGHT, buf, TELNET_INI); + wsprintf(buf, "%d", con->width); + WritePrivateProfileString(INI_TELNET, INI_WIDTH, buf, TELNET_INI); + break; + + default: /* Passes it on if unproccessed */ + return(DefWindowProc(hWnd, message, wParam, lParam)); + } + return (NULL); +} + + +/*+*************************************************************************** + + FUNCTION: SaveHostName(hostname) + + PURPOSE: Saves the currently selected host name in the KERBEROS.INI file + and returns the preferred backspace setting if one exists for + that host. + + RETURNS: VK_BACK or 0x7f depending on the desired backspace setting. + +****************************************************************************/ + +int +SaveHostName(char *host) +{ + char buf[128]; + char hostName[10][128]; + char *tmpCommaLoc; + char tmpName[128]; + char tmpBuf[80]; + int nhosts; + int n; + int iHostNum; + int bs; + + nhosts = 0; + for (iHostNum = 0; iHostNum < 10; iHostNum++) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", hostName[iHostNum], + 128, TELNET_INI); + strcpy(tmpName, hostName[iHostNum]); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) { + *tmpCommaLoc = '\0'; + while (tmpCommaLoc[1] == ' ') + tmpCommaLoc++; + } + if (!hostName[iHostNum][0]) + break; + nhosts++; + if (strcmp(tmpName, host) == 0) + break; + } + + for (iHostNum++; iHostNum < 10; iHostNum++) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", hostName[iHostNum], + 128, TELNET_INI); + if (!hostName[iHostNum][0]) + break; + nhosts++; + } + + if (tmpCommaLoc) + tmpCommaLoc++; + + if (tmpName[0] && tmpCommaLoc) { + if (_stricmp(tmpCommaLoc, INI_HOST_DEL) == 0) + bs = 0x7f; + else if (_stricmp(tmpCommaLoc, INI_HOST_BS) == 0) + bs = VK_BACK; + } + else { + GetPrivateProfileString(INI_TELNET, INI_BACKSPACE, INI_BACKSPACE_BS, + tmpBuf, sizeof(tmpBuf), TELNET_INI); + if (_stricmp(tmpBuf, INI_BACKSPACE_DEL) == 0) + bs = 0x7f; + else + bs = VK_BACK; + } + + strcpy(buf, tmpConfig->title); + strcat(buf, ", "); + if (bs == VK_BACK) + strcat(buf, INI_BACKSPACE_BS); + else + strcat(buf, INI_BACKSPACE_DEL); + + WritePrivateProfileString(INI_HOSTS, INI_HOST "0", buf, TELNET_INI); + n = 1; + for (iHostNum = 0; iHostNum < nhosts; iHostNum++) { + strcpy(tmpName, hostName[iHostNum]); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) { + *tmpCommaLoc = '\0'; + while (tmpCommaLoc[1] == ' ') + tmpCommaLoc++; + } + if (strcmp(tmpName, host) != 0) { + wsprintf(tmpBuf, INI_HOST "%d", n++); + WritePrivateProfileString(INI_HOSTS, tmpBuf, hostName[iHostNum], + TELNET_INI); + } + } + return (bs); +} + +/*+*/ +int +OpenTelnetConnection(void) { + int nReturn, ret; + struct sockaddr_in sockaddr; + char *p; + static struct kstream_crypt_ctl_block ctl; + char buf[128]; + + hGlobalMem = GlobalAlloc(GPTR, sizeof(CONFIG)); + tmpConfig = (CONFIG *) GlobalLock(hGlobalMem); + + if (bAutoConnection) { + hTitleMem = GlobalAlloc(GPTR, lstrlen(szAutoHostName)); + tmpConfig->title = (char *) GlobalLock(hTitleMem); + lstrcpy(tmpConfig->title, (char *) szAutoHostName); + } else { + nReturn = DoDialog("OPENTELNETDLG", OpenTelnetDlg); + if (nReturn == FALSE) return(FALSE); + } + + con = (CONNECTION *) GetNewConnection(); + if (con == NULL) return(0); + + tmpConfig->width = GetPrivateProfileInt(INI_TELNET, INI_WIDTH, + DEF_WIDTH, TELNET_INI); + tmpConfig->height = GetPrivateProfileInt(INI_TELNET, INI_HEIGHT, + DEF_HEIGHT, TELNET_INI); + con->width = tmpConfig->width; + con->height = tmpConfig->height; + + con->backspace = SaveHostName(tmpConfig->title); + + if (con->backspace == VK_BACK) { + tmpConfig->backspace = TRUE; + con->ctrl_backspace = 0x7f; + } else { + tmpConfig->backspace = FALSE; + con->ctrl_backspace = 0x08; + } + + tmpConfig->hwndTel = hWnd; + con->hScreen = (HSCREEN) InitNewScreen((CONFIG *) tmpConfig); + if (!(con->hScreen)) { + OutputDebugString("Failed to initialize new screen! \r\n"); + GlobalUnlock(con->hScreen); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + return(-1); + } + + ret = (SOCKET) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (ret == SOCKET_ERROR) { + wsprintf(buf, "Socket error on socket = %d!", WSAGetLastError()); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + fpScr = (SCREEN *) GlobalLock(con->hScreen); + if (fpScr != NULL) + DestroyWindow(fpScr->hWnd); + GlobalUnlock(con->hScreen); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + return(-1); + } + + con->socket = ret; + + sockaddr.sin_family = AF_INET ; + sockaddr.sin_addr.s_addr = htonl( INADDR_ANY ); + sockaddr.sin_port = htons( 0 ) ; + + ret = bind(con->socket, (struct sockaddr *) &sockaddr, + (int) sizeof(struct sockaddr_in)); + + if (ret == SOCKET_ERROR) { + wsprintf(buf, "Socket error on bind!"); + MessageBox(NULL, buf, NULL, MB_OK|MB_ICONEXCLAMATION); + fpScr = (SCREEN *) GlobalLock(con->hScreen); + if (fpScr != NULL) + DestroyWindow(fpScr->hWnd); + GlobalUnlock(con->hScreen); + GlobalUnlock(ghCon); + GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + return(-1); + } + WSAAsyncSelect(con->socket, hWnd, WM_NETWORKEVENT, + FD_READ | FD_CLOSE | FD_CONNECT); + + lstrcpy(szHostName, tmpConfig->title); + p = strchr(szHostName, '@'); + if (p != NULL) { + *p = 0; + strcpy (szUserName, szHostName); + strcpy(szHostName, ++p); + } + + WSAAsyncGetHostByName(hWnd, WM_HOSTNAMEFOUND, szHostName, hostdata, + MAXGETHOSTSTRUCT); + GlobalUnlock(con->hScreen); +// GlobalUnlock(ghCon); +// GlobalFree(ghCon); + GlobalUnlock(hGlobalMem); + GlobalFree(hGlobalMem); + + ctl.encrypt = auth_encrypt; + ctl.decrypt = auth_decrypt; + ctl.init = auth_init; + ctl.destroy = auth_destroy; + + con->ks = kstream_create_from_fd(con->socket, &ctl, NULL); + + kstream_set_buffer_mode(con->ks, 0); + + if (con->ks == NULL) + return(-1); + + return(1); +} + +/*+*/ +CONNECTION * +GetNewConnection(void) { + CONNECTION *fpCon; + + ghCon = GlobalAlloc(GHND, sizeof(CONNECTION)); + if (ghCon == NULL) return NULL; + fpCon = (CONNECTION *) GlobalLock(ghCon); + if (fpCon == NULL) return NULL; + fpCon->backspace = TRUE; + fpCon->bResizeable = TRUE; + return(fpCon); +} + +/*+***************************************************************************/ +int NEAR +DoDialog(char *szDialog, FARPROC lpfnDlgProc) { + int nReturn; + + lpfnDlgProc = MakeProcInstance(lpfnDlgProc, hInst); + if (lpfnDlgProc == NULL) + MessageBox(hWnd, "Couldn't make procedure instance", NULL, MB_OK); + + nReturn = DialogBox(hInst, szDialog, hWnd, lpfnDlgProc); + FreeProcInstance(lpfnDlgProc); + return (nReturn); +} + +/*+*************************************************************************** + + FUNCTION: OpenTelnetDlg(HWND, unsigned, WORD, LONG) + + PURPOSE: Processes messages for "Open New Telnet Connection" dialog box + + MESSAGES: + + WM_INITDIALOG - initialize dialog box + WM_COMMAND - Input received + +****************************************************************************/ + +BOOL FAR PASCAL +OpenTelnetDlg(HWND hDlg, WORD message, WORD wParam, LONG lParam) { + char szConnectName[256]; + HDC hDC; + int xExt, yExt; + DWORD Ext; + HWND hEdit; + int nLen; + int iHostNum = 0; + char tmpName[128], tmpBuf[80]; + char *tmpCommaLoc; + + switch (message) { + case WM_INITDIALOG: /* message: initialize dialog box */ + hDC = GetDC(hDlg); + Ext = GetDialogBaseUnits(); + xExt = (190 *LOWORD(Ext)) /4 ; + yExt = (72 * HIWORD(Ext)) /8 ; + GetPrivateProfileString(INI_HOSTS, INI_HOST "0", "", tmpName, + 128, TELNET_INI); + if (tmpName[0]) { + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) + *tmpCommaLoc = '\0'; + SetDlgItemText(hDlg, TEL_CONNECT_NAME, tmpName); + } + hEdit = GetWindow(GetDlgItem(hDlg, TEL_CONNECT_NAME), GW_CHILD); + while (TRUE) { + wsprintf(tmpBuf, INI_HOST "%d", iHostNum++); + GetPrivateProfileString(INI_HOSTS, tmpBuf, "", tmpName, + 128, TELNET_INI); + tmpCommaLoc = strchr(tmpName, ','); + if (tmpCommaLoc) + *tmpCommaLoc = '\0'; + if (tmpName[0]) + SendDlgItemMessage(hDlg, TEL_CONNECT_NAME, CB_ADDSTRING, 0, + (LPARAM) ((LPSTR) tmpName)); + else + break; + } + SetWindowPos(hDlg, NULL, (GetSystemMetrics(SM_CXSCREEN)/2)-(xExt/2), + (GetSystemMetrics(SM_CYSCREEN)/2)-(yExt/2), 0, 0, + SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW); + ReleaseDC(hDlg, hDC); + SendMessage(hEdit, WM_USER+1, NULL, NULL); + SendMessage(hDlg, WM_SETFOCUS, NULL, NULL); + return (TRUE); + + case WM_COMMAND: /* message: received a command */ + switch (wParam) { + case TEL_CANCEL: + EndDialog(hDlg, FALSE); /* Exits the dialog box */ + break; + + case TEL_OK: + GetDlgItemText(hDlg, TEL_CONNECT_NAME, szConnectName, 256); + nLen = lstrlen(szConnectName); + if (nLen == 0) { + MessageBox(hDlg, "You must enter a session name!", + NULL, MB_OK); + break; + } + hTitleMem = GlobalAlloc(GPTR, nLen); + tmpConfig->title = (char *) GlobalLock(hTitleMem); + lstrcpy(tmpConfig->title, szConnectName); + EndDialog(hDlg, TRUE); + break; + } + return (FALSE); + } + return (FALSE); /* Didn't process a message */ +} + +/*+*************************************************************************** + + FUNCTION: TelnetSend(kstream ks, char *buf, int len, int flags) + + PURPOSE: This is a replacement for the WinSock send() function, to + send a buffer of characters to an output socket. It differs + by retrying endlessly if sending the bytes would cause + the send() to block. <gnu@cygnus.com> observed EWOULDBLOCK + errors when running using TCP Software's PC/TCP 3.0 stack, + even when writing as little as 109 bytes into a socket + that had no more than 9 bytes queued for output. Note also that + a kstream is used during output rather than a socket to facilitate + encryption. + + Eventually, for cleanliness and responsiveness, this + routine should not loop; instead, if the send doesn't + send all the bytes, it should put them into a buffer + and return. Message handling code would send out the + buffer whenever it gets an FD_WRITE message. + +****************************************************************************/ + +int +TelnetSend(kstream ks, char *buf, int len, int flags) { + + int writelen; + int origlen = len; + + while (TRUE) { + writelen = kstream_write(ks, buf, len); + + if (writelen == len) /* Success, first or Nth time */ + return (origlen); + + if (writelen == SOCKET_ERROR) { + if (WSAGetLastError() != WSAEWOULDBLOCK) + return (SOCKET_ERROR); /* Some error */ + /* For WOULDBLOCK, immediately repeat the send. */ + } + else { + /* Partial write; update the pointers and retry. */ + len -= writelen; + buf += writelen; + } + } +} |