/* * Tcp4u v 3.31 Last Revision 04/03/1998 3.30.02 * *=========================================================================== * * Project: Tcp4u, Library for tcp protocol * File: tn4u.c * Purpose: telnet based-functions * *=========================================================================== * * This software is Copyright (c) 1996-1998 by Philippe Jounin * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * * If you make modifications to this software that you feel * increases it usefulness for the rest of the community, please * email the changes, enhancements, bug fixes as well as any and * all ideas to me. This software is going to be maintained and * enhanced as deemed necessary by the community. * * * Philippe Jounin (ph.jounin@computer.org) */ #include "build.h" /* ******************************************************************* */ /* */ /* Partie II : Lecture des trames de type Telnet */ /* */ /* ******************************************************************* */ /* ------------------------------------------------------------ */ /* TnReadLine : Lit une ligne de donnees (jusqu'à ) */ /* retourne TN_ERROR, TN_TIMEOUT, TN_BUFFERFREED */ /* TN_OVERFLOW ou le nombre d'octets lus */ /* dans les deux derniers cas le buffer szBuf est */ /* renseigne. Si TN_SUCCESS il est -termine. */ /* ------------------------------------------------------------ */ int API4U TnReadLine (SOCKET s,LPSTR szBuf,UINT uBufSize,UINT uTimeOut,HFILE hf) { int Rc; Tcp4uLog (LOG4U_PROC, "TnReadLine"); Rc = InternalTnReadLine (s, szBuf, uBufSize, uTimeOut, hf); if (Rc==TN_SUCCESS) Tcp4uDump (szBuf, Strlen(szBuf), DUMP4U_RCVD); Tcp4uLog (LOG4U_EXIT, "TnReadLine"); return Rc; } /* TnReadLine */ int InternalTnReadLine (SOCKET s,LPSTR szBuf,UINT uBufSize,UINT uTimeOut, HFILE hf) { int Rc; if (s==INVALID_SOCKET || uBufSize==0) return TN_ERROR; /* ??? */ memset (szBuf, 0, uBufSize); Rc = InternalTcpRecvUntilStr (s, szBuf, & uBufSize, "\n", 1, TRUE, uTimeOut, hf); if (Rc>=TCP4U_SUCCESS && szBuf[uBufSize-1]=='\r') szBuf[uBufSize-1]=0 ; /* pas de translation des erreurs, timeout... */ return (Rc>=TCP4U_SUCCESS) ? TN_SUCCESS : Rc; } /* InternalTnReadLine */ /* ******************************************************************* */ /* */ /* Partie III : Etage Telnet Haut */ /* */ /* ******************************************************************* */ /* ------------------------------------------------------------ */ /* TnSend : Formatage d'une trame au format Telnet (terminée */ /* par */ /* Retour par TN_ERROR, ou TN_SUCCESS. */ /* ------------------------------------------------------------ */ int API4U TnSend (SOCKET s, LPCSTR szString, BOOL bHighPriority, HFILE hf) { int Rc, Z; LPSTR p; Tcp4uLog (LOG4U_PROC, "TnSend"); Z = Strlen (szString)+sizeof ("\r\n")-1; p = Calloc (Z+1, 1); if (p==NULL) return TCP4U_INSMEMORY; Strcpy (p, szString); Strcat (p, "\r\n"); Rc = InternalTcpSend (s, p, Z, bHighPriority, hf); if (Rc==TCP4U_SUCCESS) Tcp4uDump (p, Z, DUMP4U_SENT); Free (p); Tcp4uLog (LOG4U_EXIT, "TnSend : return code %d", Rc); return Rc==TCP4U_SUCCESS ? TN_SUCCESS : TN_ERROR; } /* TnSend */ /* ------------------------------------------------------------ */ /* TnReadMultiLine : waits for a message from the remote peer */ /* This message can contain several lines */ /* As said in Telnet RFC, it depends on the */ /* 4th char. */ /* - A TN_XX code is returned */ /* 20.02.1998: A bug has been found and fixed by Sergej Semenov.*/ /* The loop test was weak enough. */ /* 04.03.1998: rewritten according to the FTP spec (RFC 959) */ /* Should manage propoerly Text like : */ /* 123-First line */ /* Second line */ /* 234 A line beginning with numbers */ /* 123 The last line */ /* ------------------------------------------------------------ */ int API4U TnReadMultiLine (SOCKET ctrl_skt, LPSTR szInBuf, UINT uBufSize, UINT uTimeOut, HFILE hf) { int Rc, TnRc; unsigned nPos=0; Tcp4uLog (LOG4U_PROC, "TnReadMultiLine"); if (szInBuf==NULL || uBufSize==0) return TN_ERROR; memset (szInBuf, 0, uBufSize); do { /* add the character */ if (szInBuf[nPos] != 0) /* changed by Sergej */ { nPos+=Strlen (&szInBuf[nPos]); /* pointer sur la fin de ligne */ szInBuf[nPos++]='\n'; } Rc = InternalTnReadLine (ctrl_skt, &szInBuf[nPos], uBufSize-nPos-1, uTimeOut,hf); /* exit on - errors */ /* - buffer full */ /* - 3 digits at the beginning of the string */ /* not followed by HYPHEN */ } while ( nPos < uBufSize - 5 /* encore de la place (y compris pour \0) */ && Rc>=TCP4U_SUCCESS /* retour correct */ && ! (isdigit (szInBuf[nPos]) && szInBuf[nPos+3] != '-' ) ); /* supprime la derniere marque fin de ligne */ if (Rc>=TCP4U_SUCCESS) { Rc = TCP4U_SUCCESS; nPos+=Strlen (&szInBuf[nPos]); if (szInBuf[nPos-1]=='\r') szInBuf[nPos-1]=0; } /* translation du code de retour */ switch (Rc) { case TCP4U_TIMEOUT : TnRc = TN_TIMEOUT; break; case TCP4U_SUCCESS : Tcp4uDump (szInBuf, nPos, DUMP4U_RCVD); TnRc = TN_SUCCESS; break; case TCP4U_OVERFLOW : Tcp4uDump (szInBuf, nPos, "Overflow"); TnRc = TN_OVERFLOW; break; case TCP4U_SOCKETCLOSED : TnRc = TN_SOCKETCLOSED; break; case TCP4U_CANCELLED : TnRc = TN_CANCELLED; break; default : TnRc = TN_ERROR; break; } Tcp4uLog (LOG4U_EXIT, "TnReadMultiLine: return code %d", TnRc); return TnRc; } /* TnReadMultiLine */ /* ------------------------------------------------------------ */ /* TnSendMultiLine : Formatage d'une trame au format Telnet */ /* expanded into */ /* Retour par TN_ERROR, ou TN_SUCCESS. */ /* ------------------------------------------------------------ */ int API4U TnSendMultiLine (SOCKET s, LPCSTR szString, BOOL bEnd, HFILE hf) { int Rc, Z; LPCSTR p; LPSTR pString; Tcp4uLog (LOG4U_PROC, "TnSendMultiLine"); /* counts the number of char */ for ( Z=0, p=szString ; *p!=0 ; p++, Z++ ) if (*p=='\n') Z++; /* put the string into a new writeable buffer */ pString = Calloc (Z+sizeof ("\r\n"), 1); if (pString==NULL) return TCP4U_INSMEMORY; for ( Z=0, p=szString ; *p!=0 ; p++, Z++ ) { if (*p=='\n' && (p>szString && *(p-1)!='\r')) pString[Z++] = '\r'; pString[Z] = *p; } if (bEnd) { pString[Z++] = '\r'; pString[Z++] = '\n'; } pString[Z] = 0; /* Job has been done, send the string and exit */ Rc = InternalTcpSend (s, pString, Z, FALSE, hf); if (Rc==TCP4U_SUCCESS) Tcp4uDump (pString, Z, DUMP4U_SENT); Free (pString); Tcp4uLog (LOG4U_EXIT, "TnSendMultiLine : return code %d", Rc); return Rc==TCP4U_SUCCESS ? TN_SUCCESS : TN_ERROR; } /* TnSendMultiLine */ /* ------------------------------------------------------------ */ /* TnGetAnswerCode : Attend une réponse du serveur et rend le */ /* code numérique (les 3 premiers octets) */ /* renvoyé par le serveur. */ /* - Retourne un nombre entre 100 et 999 si la */ /* fonction s'est bien passée, sinon un code */ /* d'erreur TN_ERROR, TN_TIMEOUT... */ /* ------------------------------------------------------------ */ int API4U TnGetAnswerCode (SOCKET ctrl_skt, LPSTR szInBuf, UINT uBufSize, UINT uTimeOut, HFILE hf) { int Rc; Tcp4uLog (LOG4U_PROC, "TnReadAnswerCode"); Rc = TnReadMultiLine (ctrl_skt, szInBuf, uBufSize, uTimeOut, hf); if (Rc==TN_SUCCESS) Rc = Tcp4uAtoi (szInBuf); Tcp4uLog (LOG4U_EXIT, "TnReadAnswerCode: return code %d", Rc); return Rc; } /* TnGetAnswerCode */