home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
WADS of WADS
/
WadsOfWads.1994.zip
/
ZIPS
/
U_Z
/
WNFTPSRC.ZIP
/
WS_CON.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-10
|
41KB
|
1,266 lines
#include "ws_glob.h"
#include "winftp.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <time.h>
// extern int errno;
extern BOOL bAborted; // timer routine may set this
extern BOOL bDebugLog;
char szDbgLogFile[_MAX_PATH];
//***********************************************************************
//***********************************************************************
int WriteDebugLog (int nCode, int nRetCode, LPSTR lpStr)
{
FILE *fp;
FARPROC lpfnMsgProc;
int nRC;
if (!bDebugLog) return 0;
if (lstrlen (szDbgLogFile)==0)
{
lstrcpy (szDlgPrompt,"Enter log file name:");
lstrcpy (szDlgEdit, "C:\\WNFTPDBG.LOG");
lpfnMsgProc = MakeProcInstance ((FARPROC) WS_InputMsgProc, hInst);
nRC = DialogBox (hInst, (LPSTR) "DLG_INPUT", hWndMain, lpfnMsgProc);
FreeProcInstance (lpfnMsgProc);
if (nRC==IDCANCEL) return 0;
lstrcpy (szDbgLogFile, szDlgEdit);
}
fp = fopen (szDbgLogFile, "at");
switch (nCode)
{
case 0: fprintf (fp, "SEND: %s\n", lpStr); break;
case 1: fprintf (fp, "RESULT: %4d %3d %-16s %s\n", nRetCode, iCode,
(nRetCode==FTP_PRELIM) ? "Prelim" :
(nRetCode==FTP_COMPLETE) ? "Complete" :
(nRetCode==FTP_CONTINUE) ? "Continue" :
(nRetCode==FTP_RETRY) ? "Retry" :
(nRetCode==FTP_ERROR) ? "Error" : "Unknown",
lpStr); break;
}
fclose (fp);
return 0;
}
//***********************************************************************
// Print statistics on the transfer
//***********************************************************************
void PrintTransferStatus (LPSTR lpTyp, LONG lBytes, long nSecs)
{
LONG lSecs = nSecs;
if (lSecs==0) lSecs=1;
DoPrintf ("%sed %ld characters in %ld seconds (%ld bytes/sec)", lpTyp,
lBytes, (long) nSecs, (long) lBytes/lSecs);
}
static UINT nDirNum=0;
//***********************************************************************
// Send in a Command line and return a code indicating type of reply
// send a message on the control socket, read and display the resulting
// message and return the result value
//***********************************************************************
int getreply (SOCKET ctrl_skt,LPSTR cmdstring, BOOL bForce)
{
int iRetCode=0;
iCode=0;
if (strncmp (cmdstring,"PASS ",5)==0) DoAddLine ("PASS xxxxxx");
else DoAddLine (cmdstring);
if (ctrl_skt==INVALID_SOCKET)
{
DoAddLine ("Not connected");
}
else
{
if (bDebugLog) WriteDebugLog (0, iRetCode, cmdstring);
switch (bForce)
{
case TRUE : if (ForcePacket (ctrl_skt,cmdstring)!=-1) iRetCode = ReadDisplayLine (ctrl_skt);
case FALSE: if (SendPacket (ctrl_skt,cmdstring)!=-1) iRetCode = ReadDisplayLine (ctrl_skt);
}
if (bDebugLog) WriteDebugLog (1, iRetCode, cmdstring);
}
return iRetCode; // 0 - 5
}
//***********************************************************************
// Send in a Command line and return a code indicating type of reply
//***********************************************************************
int command (SOCKET ctrl_skt, char *fmt,...)
{
va_list args;
char szBuf[90];
va_start (args, fmt);
vsprintf (szBuf, fmt, args);
va_end (args);
return getreply (ctrl_skt, szBuf, FALSE);
}
//***********************************************************************
// Send in a Command line and return a code indicating type of reply
//***********************************************************************
int ForceCommand (SOCKET ctrl_skt, char *fmt,...)
{
va_list args;
char szBuf[90];
va_start (args, fmt);
vsprintf (szBuf, fmt, args);
va_end (args);
return getreply (ctrl_skt, szBuf, TRUE);
}
//***********************************************************************
// return a string pointer to ON or OFF based on the flag
//***********************************************************************
char *onoff(BOOL flag)
{
if (flag) return("ON"); else return("OFF");
}
//***********************************************************************
// process CWD
//***********************************************************************
int DoCWD(SOCKET ctrl_skt,LPSTR path)
{
char szPath[100];
if (command (ctrl_skt,"CWD %s",path)==FTP_ERROR)
{
if (iCode==500) command (ctrl_skt,"XCWD %s",path);
else
{
lstrcpy (szPath, path);
ConvertTargetDir (szPath, 95);
command (ctrl_skt,"CWD %s", szPath);
}
}
return(iCode/100);
}
//***********************************************************************
// process System Type
//***********************************************************************
int DoSystemCommand (SOCKET ctrl_skt)
{
LPSTR lp;
char szBuf[100];
if (command (ctrl_skt,"SYST")!=FTP_ERROR)
{
lstrcpy (szBuf, szMsgBuf);
strupr (szBuf);
if (strstr (szBuf, "UNIX") != NULL) nHostType = HOST_UNIX;
else if (strstr (szBuf, "ULTRIX") != NULL) nHostType = HOST_UNIX;
else if (strstr (szBuf, "MVS") != NULL) nHostType = HOST_MVS;
else if (strstr (szBuf, "QVT") != NULL) nHostType = HOST_QVT;
else if (strstr (szBuf, "NCSA") != NULL) nHostType = HOST_NCSA;
else if (strstr (szBuf, "CHAMELEON")!=NULL) nHostType = HOST_CHAMELEON;
else if (strstr (szMsgBuf, "VMS") != NULL)
{
lp = strstr (szMsgBuf, "MultiNet");
nHostType = (lp!=NULL)? HOST_VMS_MULTINET : HOST_VMS_UCX;
}
}
return(iCode/100);
}
//***********************************************************************
// proces PWD
//***********************************************************************
int DoPWD(SOCKET ctrl_skt)
{
if (command(ctrl_skt,"PWD")==FTP_ERROR && iCode==500)
{
command(ctrl_skt,"XPWD");
}
return(iCode/100);
}
//***********************************************************************
// process MKD
//***********************************************************************
int DoMKD(SOCKET ctrl_skt,LPSTR pathname)
{
char szPath[100];
if (command (ctrl_skt,"MKD %s",pathname)==FTP_ERROR)
{
if (iCode==500) command (ctrl_skt,"XMKD %s",pathname);
else
{
lstrcpy (szPath, pathname);
ConvertTargetDir (szPath, 95);
command (ctrl_skt,"MKD %s", szPath);
}
}
return(iCode/100);
}
//***********************************************************************
// process RMD
//***********************************************************************
int DoRMD(SOCKET ctrl_skt,LPSTR pathname)
{
char szPath[100];
if (command (ctrl_skt,"RMD %s",pathname)==FTP_ERROR)
{
if (iCode==500) command (ctrl_skt,"XRMD %s",pathname);
else
{
lstrcpy (szPath, pathname);
ConvertTargetDir (szPath, 95);
command (ctrl_skt,"RMD %s", szPath);
}
}
return(iCode/100);
}
//***********************************************************************
// process DELE
//***********************************************************************
int DoDELE(SOCKET ctrl_skt,LPSTR pathname)
{
command(ctrl_skt,"DELE %s",pathname);
return(iCode/100);
}
//***********************************************************************
// Send the Quit Command
//***********************************************************************
int DoDisconnect (SOCKET ctrl_skt)
{
int nRC=-1;
if (ctrl_skt!=INVALID_SOCKET)
{
nRC=command (ctrl_skt, "quit");
shutdown (ctrl_skt, 2);
}
return nRC;
}
//***********************************************************************
// process user command
//***********************************************************************
int DoQUOTE(SOCKET ctrl_skt,LPSTR string)
{
if(strncmp(string,"LIST",4)==0 ||
strncmp(string,"NLST",4)==0)
DoDirList(ctrl_skt,string);
else
command(ctrl_skt,string);
return(iCode/100);
}
//***********************************************************************
// process chmod
//***********************************************************************
int DoCHMOD(SOCKET ctrl_skt,LPSTR modes,LPSTR filename)
{
return (command(ctrl_skt,"SITE CHMOD %s %s",modes,filename));
}
extern BOOL bHELP,bIs5000;
LPSTR szAcctAttempt="Attempting to send Account Password...";
//***********************************************************************
// initial connection
//***********************************************************************
SOCKET DoConnect (LPSTR lpHost)
{
int iLength,iRetCode;
int iFlag=1;
SOCKET ctrl_skt;
LPSTR lpSite;
if (bConnected)
{
DoAddLine("Already connected!");
return (INVALID_SOCKET);
}
//***************************************************************
// if connecting through a Firewall Host, trick the connect code
// into connecting to the FireWall Host instead.
//***************************************************************
if (bFireWall)
{
if (lstrlen (szFireWallHost)==0)
{
DoPrintf ("FireWall Host name not specified. Can not Connect.");
SetDebugWindowText (lpDebugWindow);
return INVALID_SOCKET;
}
lpHost = szFireWallHost;
}
bHELP=bIs5000=FALSE;
SetDebugWindowText ("WINFTP Connecting...");
lpSite = lpHost;
//***************************************************************
// let other routines know that we are busy
//***************************************************************
bCmdInProgress++;
//***************************************************************
// create a connected socket
//***************************************************************
if ((ctrl_skt=connectTCP (lpHost,"ftp"))==INVALID_SOCKET)
{
DoPrintf ("Connection to %s failed", lpHost);
bCmdInProgress--;
SetDebugWindowText (lpDebugWindow);
return INVALID_SOCKET;
}
//***************************************************************
// get information about local end of the connection
//***************************************************************
iLength = sizeof (saCtrlAddr);
if (getsockname (ctrl_skt, (struct sockaddr *) &saCtrlAddr, &iLength)==SOCKET_ERROR)
{
ReportWSError ("getsockname", WSAGetLastError());
bCmdInProgress--;
DoClose (ctrl_skt);
SetDebugWindowText (lpDebugWindow);
return (INVALID_SOCKET);
}
//***************************************************************
// show remote end address
//***************************************************************
DoPrintf ("[%u] from %s port %u", ctrl_skt, inet_ntoa (saCtrlAddr.sin_addr), ntohs (saCtrlAddr.sin_port));
//***************************************************************
// get initial message from remote end
//***************************************************************
while ((iRetCode=ReadDisplayLine(ctrl_skt))==FTP_PRELIM)
{
if (strstr(szMsgBuf,"(EXOS")!=NULL) bIs5000=TRUE;
}
//***************************************************************
// if it succeeded
//***************************************************************
if (iRetCode!=FTP_COMPLETE)
{
DoPrintf ("Unknown open msg \"%s\" %u",szMsgBuf,iCode);
// allow other processes to work
bCmdInProgress--;
DoClose ((SOCKET) ctrl_skt);
SetDebugWindowText (lpDebugWindow);
return (INVALID_SOCKET);
}
if (setsockopt (ctrl_skt, SOL_SOCKET, SO_OOBINLINE, (LPSTR) &iFlag, sizeof (iFlag))==SOCKET_ERROR)
{
ReportWSError("setsockopt",WSAGetLastError());
}
//***************************************************************
// have to reset this so "command" will work
//***************************************************************
bCmdInProgress--;
if (bFireWall)
{
if ((iRetCode=command(ctrl_skt,"USER %s", szFireWallUserID))==FTP_CONTINUE)
{
iRetCode = command (ctrl_skt, "PASS %s", szFireWallUserPass);
}
if (iRetCode!=FTP_COMPLETE)
{
DoPrintf ("Failed to log in to Firewall Host %s", lpHost);
DoClose ((SOCKET) ctrl_skt);
return INVALID_SOCKET;
}
//***************************************************************
//Okay, gets here if logged in to FireWall Host
//***************************************************************
wsprintf (szString, "site %s", lpSite);
if ((iRetCode=command (ctrl_skt, szString))==FTP_ERROR)
{
DoPrintf ("Could not connect to %s through FireWall Host", lpSite);
DoClose ((SOCKET) ctrl_skt);
bConnected=0;
return INVALID_SOCKET;
}
//***************************************************************
// if here, we did get through to remote host, so do regular login
//***************************************************************
bConnected=1;
}
//***************************************************************
// send our userid
//***************************************************************
SetDebugWindowText ("WINFTP UserName");
if ((iRetCode=command (ctrl_skt, "USER %s", szUserID))==FTP_CONTINUE)
{
//***************************************************************
// if the remote system requires a password, send it.
//***************************************************************
SetDebugWindowText ("WINFTP Password");
iRetCode = command (ctrl_skt,"PASS %s",szPassWord);
//***************************************************************
// If the system requires an account password
//***************************************************************
if (bAccount)
{
nAcctType = 3;
switch (nAcctType)
{
case 0: break;
case 1: if (iRetCode!=FTP_CONTINUE) break;
case 2: DoAddLine (szAcctAttempt);
if ((iRetCode=command (ctrl_skt, "ACCOUNT"))==FTP_CONTINUE)
{
iRetCode = command (ctrl_skt, szAccountPass);
} break;
case 3: if (iRetCode!=FTP_CONTINUE) break;
case 4: DoAddLine (szAcctAttempt);
wsprintf (szString, "ACCT %s", szAccountPass);
iRetCode=command (ctrl_skt, szString);
break;
}
}
}
//***************************************************************
// if we are successfully logged on,.....
//***************************************************************
if (iRetCode!=FTP_COMPLETE)
{
DoPrintf ("Could not log on to remote host %s", lpSite);
DoClose ((SOCKET) ctrl_skt);
SetDebugWindowText (lpDebugWindow);
MessageBox (hWndMain, szMsgBuf+4, "Login Failed", MB_OK);
return INVALID_SOCKET;
}
bConnected=1;
wsprintf (szString,"WINFTP: %s",szRemoteHost);
SetWindowText (hWndMain, szString);
SetDebugWindowText (lpDebugWindow);
return ctrl_skt;
}
//***********************************************************************
//***********************************************************************
int DoDirList (SOCKET ctrl_skt,LPSTR szCMD)
{
int nRC,nBell;
nBell=bBell; bBell=0;
if (lstrlen (szCurrentDir)>0) unlink (szCurrentDir);
wsprintf (szCurrentDir, szTmpDirFile, nDirNum++);
nRC = RetrieveFile (ctrl_skt, szCMD, szCurrentDir, TYPE_A);
bBell = nBell;
return nRC;
}
//***********************************************************************
//***********************************************************************
int SendFile(SOCKET ctrl_skt,LPSTR szCMD,LPSTR localfile,char stype)
{
int iRetCode;
int iLength;
iCode=0;
// if we don't have a valid control socket, can't do anything
if(ctrl_skt==INVALID_SOCKET)
{
DoAddLine("no ctrl_skt, ignored");
return(0);
}
// if we are doing something, don't try to do this
if (bCmdInProgress)
{
DoAddLine("command in process, ignored");
return(0);
}
// if the requested type is not the same as the default type
if (cType!=stype)
{
if(stype==TYPE_L)
command(ctrl_skt,"TYPE L 8");
else
command(ctrl_skt,"TYPE %c",stype);
cType=stype;
}
// create a listener socket, if it is successful
if ((listen_socket=GetFTPListenSocket (ctrl_skt))!=INVALID_SOCKET)
{
// send command to see the result of this all
// read the control channel (should return 1xx if it worked)
iRetCode = command ((SOCKET) ctrl_skt, szCMD);
if (iRetCode==FTP_PRELIM)
{
// wait for connection back to us on the listen socket
nTimerID = SetTimer (hWndMain, 10, uiTimeOut, NULL);
// get our data connection
iLength=sizeof (saSockAddr1);
data_socket = accept (listen_socket, (struct sockaddr far *)&saSockAddr1, (int far *)&iLength);
// turn off the timeout timer
KillTimer (hWndMain, 10);
nTimerID = -1;
// if it failed, we have to quit this
if (data_socket==INVALID_SOCKET)
{
ReportWSError("accept",WSAGetLastError());
listen_socket = DoClose (listen_socket);
iRetCode = FTP_ERROR;
}
else
{
// we don't need the listener socket anymore
// inform user of the connection
listen_socket = DoClose (listen_socket);
DoPrintf ("[%u] accept from %s port %u", data_socket,
inet_ntoa (saSockAddr1.sin_addr), ntohs (saSockAddr1.sin_port));
// copy the file and close the socket
iRetCode = SendMass (data_socket, localfile, stype==TYPE_I);
data_socket = DoClose (data_socket);
// read the close control message (should return 2xx)
switch (iRetCode)
{
case FTP_ABORT: break; //ForcePacket (ctrl_skt, "ABOR"); break;
default : iRetCode = ReadDisplayLine (ctrl_skt);
}
}
}
else
{
listen_socket = DoClose (listen_socket);
iRetCode=0;
if (bBell) MessageBeep (MB_ICONEXCLAMATION);
}
}
else
{
listen_socket = DoClose (listen_socket);
iRetCode=FTP_ERROR;
if (bBell) MessageBeep (MB_ICONEXCLAMATION);
}
return iRetCode;
}
//*****************************************************************************
//*****************************************************************************
void ExtractFileSize()
{
char szBuf[100];
LONG nSiz=0;
LPSTR lp;
lstrcpy (szBuf, szMsgBuf);
strupr (szBuf);
if ((lp=strstr (szBuf, " BYTES"))!=NULL)
{
*lp-- = '\0';
while (*lp==' ') lp--;
while (isdigit (*lp)) lp--;
if (*lp!='\0') lp++;
nSiz = atol (lp);
if (nSiz>0)
{
CreateXferWindow();
SetTotalBytes (nSiz);
}
}
}
//*****************************************************************************
//*****************************************************************************
int RetrieveFile (SOCKET ctrl_skt, LPSTR szCMD, LPSTR localfile, char rtype)
{
int iRetCode;
int iLength;
iCode=0;
//*************************************************************
// if we don't have a valid control socket, can't do anything
//*************************************************************
if(ctrl_skt==INVALID_SOCKET)
{
DoAddLine("no ctrl_skt, ignored");
return(0);
}
//*************************************************************
// if we are doing something, don't try to do this
//*************************************************************
if(bCmdInProgress)
{
DoAddLine("command in process, ignored");
return(0);
}
//*************************************************************
// if the requested type is not the same as the default type
//*************************************************************
if (cType!=rtype)
{
switch (rtype)
{
case TYPE_L: command(ctrl_skt,"TYPE L 8"); break;
default : command(ctrl_skt,"TYPE %c",rtype);
}
cType=rtype;
}
//*************************************************************
// create a listener socket, if it is successful
//*************************************************************
if ((listen_socket=GetFTPListenSocket (ctrl_skt))!=INVALID_SOCKET)
{
//*************************************************************
// send command to see the result of this all
// read the control channel (should return 1xx if it worked)
//*************************************************************
iRetCode = command ((SOCKET)ctrl_skt,szCMD);
if (iRetCode==FTP_PRELIM)
{
// wait for connection back to us on the listen socket
ExtractFileSize();
iLength = sizeof (saSockAddr1);
nTimerID = SetTimer (hWndMain, 10, uiTimeOut, NULL);
// get our data connection
data_socket = accept (listen_socket, (struct sockaddr far *) &saSockAddr1,
(int far *)&iLength);
// turn off the timeout timer
KillTimer (hWndMain, 10);
nTimerID = -1;
// if it failed, we have to quit this
if (data_socket==INVALID_SOCKET)
{
ReportWSError ("accept",WSAGetLastError());
listen_socket = DoClose (listen_socket);
iRetCode=0;
}
else
{
// we don't need the listener socket anymore
listen_socket = DoClose (listen_socket);
// inform user of the connection
DoPrintf ("[%u] accept from %s port %u", data_socket,
inet_ntoa (saSockAddr1.sin_addr), ntohs (saSockAddr1.sin_port));
// copy the file
iRetCode = ReadMass (data_socket, localfile, rtype==TYPE_I);
// shut the data socket down
if (iRetCode!=FTP_ABORT)
{
//************************************************
// close the data socket
// read the close control message (should return 2xx)
//************************************************
if (shutdown (data_socket, 2)!=0) ReportWSError ("ShutDown", WSAGetLastError());
data_socket = DoClose (data_socket);
iRetCode = ReadDisplayLine (ctrl_skt);
}
else
{
//************************************************
// Transfer was aborted, try to shut down gracefully
//************************************************
// ForcePacket (ctrl_skt, "ABOR");
shutdown (data_socket, 2);
data_socket = DoClose (data_socket);
}
}
}
else
{
listen_socket = DoClose (listen_socket);
iRetCode=0;
if (bBell) MessageBeep (MB_ICONEXCLAMATION);
}
}
else
{
listen_socket = DoClose (listen_socket);
iRetCode=0;
if (bBell) MessageBeep (MB_ICONEXCLAMATION);
}
return iRetCode;
}
//***********************************************************************
// user close routine
//***********************************************************************
SOCKET DoClose(SOCKET sockfd)
{
LINGER linger;
if (sockfd!=INVALID_SOCKET)
{
if (WSAIsBlocking())
{
DoPrintf ("[%u] Cancelled blocking call", sockfd);
WSACancelBlockingCall();
bAborted=TRUE;
}
linger.l_onoff = TRUE;
linger.l_linger = 0;
// Patch to make Lanera Stack work
//setsockopt (sockfd, SOL_SOCKET, SO_LINGER, (LPSTR)&linger, sizeof (linger) );
if (closesocket (sockfd)==SOCKET_ERROR)
ReportWSError("CloseSocket", WSAGetLastError());
else
{
DoPrintf("[%u] Socket closed.",sockfd);
sockfd=INVALID_SOCKET;
}
}
if (sockfd!=INVALID_SOCKET)
DoPrintf("[%u] Failed to close socket.", sockfd);
return (sockfd);
}
//***********************************************************************
//***********************************************************************
int SendPacket (SOCKET sockfd,LPSTR msg)
{
int i, nRetCode;
if (sockfd==INVALID_SOCKET) return -1;
if ((bCmdInProgress)&&(lstrcmpi (msg, "quit")!=0))
{
DoAddLine ("Command already in progress, ignored New Cmd");
return -1;
}
bCmdInProgress++;
i=lstrlen (msg);
lstrcpy (szSendPkt, msg);
// append a CRLF to the end of outgoing messages
szSendPkt[i++]='\r';
szSendPkt[i++]='\n';
szSendPkt[i]=0;
i = sendstr (sockfd, szSendPkt, i, &nRetCode);
bCmdInProgress--;
return i;
}
//***********************************************************************
//***********************************************************************
int ForcePacket (SOCKET sockfd, LPSTR msg)
{
int i, nRetCode;
if (sockfd==INVALID_SOCKET) return -1;
bCmdInProgress++;
i=lstrlen (msg);
lstrcpy (szSendPkt, msg);
// append a CRLF to the end of outgoing messages
if (szSendPkt[i-1]!='\n') lstrcat (szSendPkt, "\r\n"), i += 2;
i = sendstr (sockfd, szSendPkt, i, &nRetCode);
bCmdInProgress--;
return i;
}
int iMultiLine=0;
//***********************************************************************
// read a reply (may be multi line) and display in debug window
//***********************************************************************
int ReadDisplayLine (SOCKET sockfd)
{
int iRetCode;
int iContinue;
char *s;
char c;
// can't do anything if we don't have a socket
if(sockfd==INVALID_SOCKET) return(0);
// let other routine know that we are doing something right now.
// count the lines in the response
bCmdInProgress++;
iMultiLine++;
// initialize some variables, go read the line
do
{
iContinue=0;
iRetCode = ReadLine (sockfd);
//switch (iRetCode)
//{
// case 257: ConvertSourceDir
//}
// if it wasn't a valid value or the 4th char was a hyphen
// then it is a continuation line
if (iRetCode<100 || iRetCode>599 || szMsgBuf[3]=='-') iContinue=1;
// send the line we read to our user/debug window
DoAddLine (szMsgBuf);
// if the timer killed it
if (bAborted) { iCode=iRetCode=421; iContinue=0; break; }
// we only want to set the real return code in certain situations
if ((iMultiLine==1 || iCode==0) && iRetCode>99 && iRetCode<600)
iCode = iRetCode;
// allow for continuation lines
}
while ((iContinue==1) || (iCode>0 && iMultiLine>1 && iRetCode!=iCode));
// ReadDisplayLine (sockfd);
// count back down our multiline reponses
iMultiLine--;
// allow other processes to run
bCmdInProgress--;
if (bAborted) return FTP_ABORT;
//************************************************
// return only the first char of return code
//************************************************
if (iCode>99 && iCode<600) return (iCode/100);
else return 0;
UNREFERENCED_PARAMETER (c);
UNREFERENCED_PARAMETER (s);
}
//***********************************************************************
// read a reply line back in from the sockfd and return the
// value at the beginning of the first line.
//***********************************************************************
int ReadLine (SOCKET sockfd)
{
LPSTR szBuf;
int nI;
int iNumBytes,iN1,iN2,iN3;
int iBytesRead;
int iRetCode;
int i;
char *s, szTrim[5] = " \r\n";
char c;
// can't do anything if we don't have a socket
if (sockfd==INVALID_SOCKET) return(0);
// let other routines know that we are doing something right now.
bCmdInProgress++;
// make sure we don't mistakenly think we timed out
KillTimer (hWndMain, 10);
// bAborted=FALSE;
nTimerID = -1;
// zero our receive buffer
memset (szMsgBuf, 0, 4096);
// initialize some variables
szBuf=szMsgBuf; iBytesRead=0; iRetCode=0;
// set our timeout
nTimerID = SetTimer (hWndMain, 10, uiTimeOut, NULL);
// this routine is a little better as it read 80 characters at a time
// (if it works:-) Here we PEEK at what is available, find the LF etc...
iNumBytes=recv (sockfd, (LPSTR) szBuf, 82, MSG_PEEK);
while (iBytesRead<4000 && (iNumBytes>0))
{
// Trumpet WinSock Alpha 15 always returns the len (82) from a recv
// with MSG_PEEK. I suppose this is an error??? The spec doesn't say
// that MSG_PEEK returns something different than normal.
KillTimer (hWndMain, 10);
nTimerID = -1;
iN1 = iNumBytes;
// must terminate the string so strchr doesn't go wild.
szBuf[iNumBytes]='\0';
// find a LF in the input if it exists
for (nI=0; nI<iNumBytes; nI++)
{
if (szBuf[nI]==0 || szBuf[nI]==0x0a || (bIs5000 && (szBuf[nI]==0x0d)))
{
iNumBytes=nI+1;
break;
}
}
iN2=iNumBytes;
// otherwise read up to the full length of what the first recv saw.
// Wonder what happens here if the second receive actually returns more
// characters than the first receive and there was a LF in the extra data?
iNumBytes = recv (sockfd, (LPSTR) szBuf, iNumBytes, 0);
// again, terminate the string
szBuf[iNumBytes]=0;
DoPrintf ("[%u] readline %u - %u - %u %s", sockfd, iN1, iN2, iNumBytes, szBuf);
// bump the receive buffer pointer
szBuf+=iNumBytes;
// count the bytes that we have read so far
iBytesRead+=iNumBytes;
// if the last character read was a LF, then stop. NOTE: this is not really
// in keeping with RFC 959 as the line MUST end with CRLF but I work with
// a system (UNISYS 5000) that only returns a LF and no CR at the end of lines.
if(*(szBuf-1)==0x0a || (bIs5000 && *(szBuf-1)==0x0d)) break;
// otherwise reset the timer and go read more characters
nTimerID = SetTimer (hWndMain, 10, uiTimeOut, NULL);
iNumBytes=recv (sockfd, (LPSTR) szBuf, 82, MSG_PEEK);
}
// if we are here, we have a line or an error or there was nothing to read
// in any case terminate what we have
KillTimer(hWndMain, 10);
nTimerID = -1;
*szBuf=0;
//*******************************************************
// find the retcode at the beginning of the line
//*******************************************************
if (iNumBytes!=SOCKET_ERROR)
{
c=szMsgBuf[3];
szMsgBuf[3]=0;
iRetCode = atoi (szMsgBuf);
szMsgBuf[3]=c;
}
else
{
int nError = WSAGetLastError();
switch (nError)
{
case WSAEINTR :
case WSAENETRESET:
case WSAESHUTDOWN:
case WSAENETDOWN :
case WSAECONNABORTED:
case WSAECONNRESET:
case WSAEINVAL :
case WSAENOTSOCK : bAborted=TRUE; break;
}
}
//*******************************************************
// if the timer killed it or was somehow aborted
//*******************************************************
if (bAborted) iRetCode=421;
// strip trailing blanks, CR's and LF's
i = lstrlen (szMsgBuf) - 1;
while ((i>1) && (strchr (szTrim, szMsgBuf[i])!=NULL)) szMsgBuf[i--]=0, i;
// unmark our progress
bCmdInProgress--;
return iRetCode;
UNREFERENCED_PARAMETER (iN3);
UNREFERENCED_PARAMETER (s);
}
//***********************************************************************
// based on WINTEL (ftp.c) and BSD (ftp.c)
//***********************************************************************
SOCKET GetFTPListenSocket(SOCKET ctrl_skt)
{
SOCKET listen_skt;
int iLength;
int iRetCode;
char *a,*p;
int iFlag=1;
// create a data socket
if ((listen_skt=socket (AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET)
{
ReportWSError ("socket create", WSAGetLastError());
return (INVALID_SOCKET);
}
// let system pick an unused port. we tell remote end with PORT cmd
DoPrintf("[%u] going to listen %s port %u",listen_skt,
inet_ntoa(saCtrlAddr.sin_addr),ntohs(saCtrlAddr.sin_port));
if(bSendPort)
{
saCtrlAddr.sin_port=htons(0);
saCtrlAddr.sin_family=AF_INET;
saCtrlAddr.sin_addr.s_addr=0;
}
else
{
// otherwise we attempt to reuse our ctrl_skt
if(setsockopt (listen_skt,SOL_SOCKET,SO_REUSEADDR,
(char *)&iFlag, sizeof(iFlag))==SOCKET_ERROR)
{
ReportWSError ("setsockopt",WSAGetLastError());
closesocket (listen_skt);
return (INVALID_SOCKET);
}
}
// Bind name to socket
if ( bind((SOCKET)listen_skt,(LPSOCKADDR)&saCtrlAddr,
(int)sizeof(struct sockaddr))==SOCKET_ERROR)
{
ReportWSError("bind",WSAGetLastError());
closesocket(listen_skt);
return (INVALID_SOCKET);
}
// get the port name that we got for later transmission in PORT cmd
iLength = sizeof (saCtrlAddr);
if (getsockname (listen_skt, (struct sockaddr *) &saCtrlAddr, &iLength)<0)
{
ReportWSError ("getsockname", WSAGetLastError());
closesocket (listen_skt);
return (INVALID_SOCKET);
}
// invoke listener
if (listen (listen_skt,1)!=0)
{
ReportWSError ("listen", WSAGetLastError());
closesocket (listen_skt);
return (INVALID_SOCKET);
}
// inform remote end about our port that we created.
if(bSendPort)
{
struct sockaddr_in saTmpAddr;
int iLength;
iLength = sizeof (saTmpAddr);
if (getsockname(ctrl_skt, (LPSOCKADDR) &saTmpAddr, &iLength)==SOCKET_ERROR)
{
ReportWSError("getsockname", WSAGetLastError());
}
a = (char *) &saTmpAddr.sin_addr;
p = (char *) &saCtrlAddr.sin_port;
#define UC(b) (((int)b)&0xff)
if ((iRetCode=command(ctrl_skt,"PORT %d,%d,%d,%d,%d,%d",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
UC(p[0]), UC(p[1])))!=FTP_COMPLETE)
{
DoPrintf("[%u] remote end didn't understand our port command.",listen_skt);
return(listen_skt);
}
}
DoPrintf("[%u] listener %s port %u",listen_skt,
inet_ntoa (saCtrlAddr.sin_addr), ntohs (saCtrlAddr.sin_port));
return (listen_skt);
}
#ifdef WIN32
#define OPENFIL(x) _lopen (x, OF_READ | OF_SHARE_DENY_NONE)
#else
#define OPENFIL(x) _lopen (x, READ)
#endif
//***********************************************************************
// Return the size of the specified file
//***********************************************************************
LONG GetFileLength (LPSTR lpName, int iFileHandle)
{
#ifdef WIN32
WIN32_FIND_DATA wfDat;
HANDLE hFile;
LONG lSize;
hFile=FindFirstFile (lpName, &wfDat);
if (hFile==INVALID_HANDLE_VALUE) return (LONG) -1;
FindClose (hFile);
lSize = (wfDat.nFileSizeHigh << 32) + wfDat.nFileSizeLow;
return lSize;
#else
return _filelength (iFileHandle);
#endif
}
//***********************************************************************
// send a file through the data socket
//***********************************************************************
int SendMass (SOCKET sockfd, LPSTR szFileName, BOOL binaryflag)
{
int iNumBytes;
int iRetCode;
int iFileHandle;
long lBytesWritten, lBytesToGo;
time_t ttStart;
time_t ttStop;
// if we don't have a socket, return an error
if (sockfd==INVALID_SOCKET || !(bConnected)) return FTP_ERROR;
// turn on a flag so other routines know we have a command in progress
// initialize some vars
bCmdInProgress++;
lBytesWritten=0l; iRetCode=FTP_ERROR;
// Open the local file for transmit.
if ((iFileHandle=OPENFIL (szFileName))== -1)
{
DoPrintf ("Could not open file %s (%u)", szFileName, errno);
if (bBell) MessageBeep (MB_ICONEXCLAMATION);
}
else
{
// get the start time
ttStart=time(NULL);
iRetCode = FTP_COMPLETE;
lBytesToGo=GetFileLength (szFileName, iFileHandle);
SetTotalBytes (lBytesToGo);
DoPrintf ("Transferring %ld bytes", (long) lBytesToGo);
SetXferWindowText (szFileName);
// loop to send output to remote end
while (((iNumBytes=_lread (iFileHandle, szMsgBuf, 512))>0)
&&(iRetCode!=FTP_ERROR)&&(iRetCode!=FTP_ABORT)&&(!bAborted))
{
// count the characters that we have sent out
lBytesWritten += (LONG) sendstr (sockfd, szMsgBuf, iNumBytes, &iRetCode);
wsprintf (szString, "%lu", lBytesWritten);
SendMessage (hTxtLBytes, WM_SETTEXT, 0, (LPARAM)(LPCSTR) szString);
SetXmitBytes (lBytesWritten);
}
// if the output file is open, close it
_lclose (iFileHandle);
switch (iRetCode)
{
case FTP_ERROR: DoPrintf ("Error on Transfer, aborted"); break;
case FTP_ABORT: DoPrintf ("Transfer aborted by User"); break;
default : // show the user how we did
// get the finish time
ttStop=time(NULL);
SendMessage (hTxtLBytes, WM_SETTEXT, 0, (LPARAM) NULL);
PrintTransferStatus ("Transmitt", lBytesWritten, (LONG) ttStop-ttStart);
iRetCode=FTP_COMPLETE;
if (bBell) MessageBeep(MB_OK);
}
}
// turn off our command in progress flag
bCmdInProgress--;
return (iRetCode);
}
//***********************************************************************
// read information from the data socket into a file.
//***********************************************************************
int ReadMass (SOCKET sockfd, LPSTR szFileName,BOOL binaryflag)
{
int iNumBytes;
int iRetCode;
int iFileHandle;
long lBytesRead;
time_t ttStart;
time_t ttStop;
// if we don't have a socket, return an error
// otherwise turn on a flag so other routines know about cmd in progress
if(sockfd==INVALID_SOCKET || !(bConnected)) return 0;
bCmdInProgress++;
//************************************************
// make sure we don't mistakenly think we timed out
// initialize some vars
//************************************************
KillTimer (hWndMain, 10); bAborted=FALSE;
nTimerID = -1;
lBytesRead=0l; iRetCode=0;
//***********************************************************************
// at the moment we are ignoring the fact that the local destination file
// may not open correctly.
//***********************************************************************
if ((iFileHandle=_lcreat (szFileName,0))== -1)
{
DoPrintf ("Failed to create file %s (%u)", szFileName,errno);
bCmdInProgress--;
return FTP_ERROR;
}
//************************************************
// get the start time
//************************************************
SetXferWindowText (szFileName);
ttStart = time (NULL);
// loop to receive input from remote end
iNumBytes = recv (sockfd, (LPSTR)szMsgBuf, 4000, 0);
while (!bAborted && (iNumBytes>0) && (iNumBytes!=SOCKET_ERROR))
{
//************************************************
// write what we received if the file is open
// and count the characters that we received
//************************************************
_lwrite (iFileHandle, szMsgBuf, iNumBytes);
lBytesRead += iNumBytes;
SetXmitBytes (lBytesRead);
wsprintf (szString, "%lu", lBytesRead);
SendMessage (hTxtRBytes, WM_SETTEXT, 0, (LPARAM)(LPCSTR) szString);
if (!bAborted) iNumBytes = recv (sockfd, (LPSTR) szMsgBuf, 4000, 0);
}
//************************************************
// get the finish time
// if the output file is open, close it
//************************************************
ttStop = time (NULL);
if (iFileHandle != -1) _lclose (iFileHandle);
if (bAborted) _unlink (szFileName), DoPrintf ("Delete partially downloaded file");
//************************************************
// if we had a recv error, let us know about it
//************************************************
if (iNumBytes==SOCKET_ERROR)
{
ReportWSError ("Recv", iRetCode=WSAGetLastError());
if (lBytesRead==0l)
{
if(bBell) MessageBeep (MB_ICONEXCLAMATION);
}
}
else
{
//************************************************
// show the user how we did
// turn off our command in progress flag
//************************************************
SendMessage (hTxtRBytes, WM_SETTEXT, 0, (LPARAM) NULL);
PrintTransferStatus ("Receiv", lBytesRead, (LONG) ttStop-ttStart);
if (bBell) MessageBeep (MB_OK);
iRetCode = (bAborted) ? FTP_ABORT : FTP_COMPLETE;
}
bCmdInProgress--;
return iRetCode;
}