home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 15
/
CD_ASCQ_15_070894.iso
/
vrac
/
wsftp2.zip
/
WS_CON.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-03
|
30KB
|
944 lines
/***************************************************************************
Windows Sockets Client Application Support Module
Written by:
John A. Junod Internet: <junodj@gordon-emh2.army.mil>
267 Hillwood Street <zj8549@trotter.usma.edu>
Martinez, GA 30907 Compuserve: 72321,366
This program executable and all source code is released into the public
domain. It would be nice (but is not required) to give me a little
credit for any use of this code.
THE INFORMATION AND CODE PROVIDED IS PROVIDED AS IS WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. IN NO EVENT SHALL JOHN A. JUNOD BE LIABLE FOR ANY DAMAGES
WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS
OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF JOHN A. JUNOD HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*****************************************************************************/
#include "ws_glob.h"
#include "ws_ftp.h"
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <time.h>
#include <stdlib.h> // atoi()
extern int errno;
extern int nHostType;
extern BOOL bAborted; // timer routine may set this
BOOLEAN globalsucceed = FALSE;
int iMultiLine=0;
// lgk timer messages do not work for use because we have mult. threads
// so create a timer proc.
extern BOOLEAN check_busy();
extern void set_busy();
VOID CALLBACK mytimerproc(wind,msg,idevent,systime)
HWND wind;
UINT msg;
UINT idevent;
DWORD systime;
{
DoPrintf("Timer has Expired\n");
if(idevent ==10)
{
KillTimer(wind,10);
if(WSAIsBlocking())
{
// lgk if we are blocking in another thread here we need to kill
// it also
if (check_busy())
{
DoPrintf("Timer cancelled blocking call\n");
bAborted=TRUE;
WSACancelBlockingCall();
TerminateThread(threadhandle,1);
set_busy(FALSE);
}
else
{
DoPrintf("Timer cancelled blocking call\n");
bAborted=TRUE;
WSACancelBlockingCall();
}
}
}
}
/*
// 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)
{
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(SendPacket(ctrl_skt,cmdstring)!=-1)
iRetCode=ReadDisplayLine(ctrl_skt);
}
return(iRetCode); // 0 - 5
}
int command(SOCKET ctrl_skt, char *fmt,...)
{
va_list args;
char szBuf[90];
// int iRetCode;
va_start(args,fmt);
vsprintf(szBuf,fmt,args);
va_end(args);
return(getreply(ctrl_skt,szBuf));
}
int qcommand(SOCKET ctrl_skt, char *fmt,...)
{
va_list args;
char szBuf[90];
// int iRetCode;
va_start(args,fmt);
vsprintf(szBuf,fmt,args);
va_end(args);
command(ctrl_skt,szBuf);
return iCode ;
}
// 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)
{
if(command(ctrl_skt,"CWD %s",path)==FTP_ERROR && iCode==500) {
command(ctrl_skt,"XCWD %s",path);
}
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)
{
if(command(ctrl_skt,"MKD %s",pathname)==FTP_ERROR && iCode==500) {
command(ctrl_skt,"XMKD %s",pathname);
}
return(iCode/100);
}
// process RMD
int DoRMD(SOCKET ctrl_skt,LPSTR pathname)
{
if(command(ctrl_skt,"RMD %s",pathname)==FTP_ERROR && iCode==500)
command(ctrl_skt,"XRMD %s",pathname);
return(iCode/100);
}
// process DELE
int DoDELE(SOCKET ctrl_skt,LPSTR pathname)
{
command(ctrl_skt,"DELE %s",pathname);
return(iCode/100);
}
// 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;
// initial connection
SOCKET DoConnect(LPSTR ftp_host)
{
int iLength,iRetCode;
int iFlag=1;
char host[80] ;
SOCKET ctrl_skt;
if(bConnected) {
DoAddLine("Already connected!");
return(INVALID_SOCKET);
}
// let other routines know that we are busy
bCmdInProgress++;
// DoPrintf("host name in doconnect is %s\n",ftp_host);
bHELP=FALSE;
if(use_gateway)
strcpy(host, szGateHost) ;
else
strcpy(host, ftp_host) ;
// create a connected socket
if((ctrl_skt=connectTCP(host,"ftp"))==INVALID_SOCKET) {
//DoAddLine("connection failed");
DoPrintf("Connection to %s failed",host) ;
bCmdInProgress--;
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);
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
// lgk need to set the global control_socket to ctrl_skt here since
// it will be returned but abort does not work unless it is set here
ctrl_socket = ctrl_skt;
while((iRetCode=ReadDisplayLine(ctrl_skt))==FTP_PRELIM && !bAborted) // 93.12.04
if(nHostType==HOST_TYPE_AUTO) {
if(strstr(szMsgBuf,"(EXOS")!=NULL)
nHostType=HOST_TYPE_U5000;
}
// if it succeeded
if(iRetCode==FTP_COMPLETE) {
if(nHostType==HOST_TYPE_AUTO) {
if(strstr(szMsgBuf,"(EXOS")!=NULL)
nHostType=HOST_TYPE_U5000;
}
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(use_gateway)
{ // send our userid
if((iRetCode=command(ctrl_skt,"USER %s",szGateUserID))==FTP_CONTINUE)
{ // if the remote system requires a password, send it.
iRetCode=command(ctrl_skt,"PASS %s",szGatePassWord);
}
if(iRetCode!=FTP_COMPLETE)
{ // if we failed to successfully log on
DoAddLine("Gateway logon failure, so quitting");
DoClose((SOCKET)ctrl_skt);
return(INVALID_SOCKET);
}
if((iRetCode=qcommand(ctrl_skt,"site %s",ftp_host))==FTP_ERROR)
{
DoAddLine("Connect to final destination failed, so quitting");
DoClose((SOCKET)ctrl_skt);
bConnected=0;
return(INVALID_SOCKET);
}
bConnected=1;
// lgk now that we are connected enable the close button and disable the
// open button
EnableWindow(hBtnClose,TRUE);
EnableWindow(hBtnConnect,FALSE);
} // end of gateway connect
// send our userid to the ftp_host
if((iRetCode=command(ctrl_skt,"USER %s",szUserID))==FTP_CONTINUE) // || 1)
{
while(szPassWord[0]==0) {
StdInputPassword(szPassWord,"Need a password:");
}
// if the remote system requires a password, send it.
if((iRetCode=command(ctrl_skt,"PASS %s",szPassWord))==FTP_CONTINUE)
{
// if the remote system requires an account, send it.
StdInput(NULL,"Need an account:");
iRetCode=command(ctrl_skt,"ACCT %s",szDlgEdit);
}
}
// if we are successfully logged on,.....
if(iRetCode!=FTP_COMPLETE) // || 0)
{
DoAddLine("logon failure, so quitting");
DoClose((SOCKET)ctrl_skt);
bConnected=0;
EnableWindow(hBtnClose,FALSE);
EnableWindow(hBtnConnect,TRUE);
return(INVALID_SOCKET);
}
bConnected=1;
EnableWindow(hBtnClose,TRUE);
EnableWindow(hBtnConnect,FALSE);
} else {
DoPrintf("unk open msg \"%s\" %u",szMsgBuf,iCode);
// allow other processes to work
bCmdInProgress--;
DoClose((SOCKET)ctrl_skt);
bConnected = 0;
EnableWindow(hBtnClose,TRUE);
EnableWindow(hBtnConnect,FALSE);
return(INVALID_SOCKET);
}
wsprintf(szString,"WS_FTP32 %s",szRemoteHost);
SetWindowText(hWndMain,szString);
return (ctrl_skt);
}
int DoDirList(SOCKET ctrl_skt,LPSTR szCMD)
{
int nRC,nBell;
nBell=bBell; bBell=0;
nRC=RetrieveFile(ctrl_skt,szCMD,szTmpFile,szTmpFile,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
iRetCode=command((SOCKET)ctrl_skt,szCMD);
// read the control channel (should return 1xx if it worked)
if(iRetCode==FTP_PRELIM) {
// wait for connection back to us on the listen socket
SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc);
// 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);
// 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=SendMass(data_socket,localfile,stype==TYPE_I);
// close the socket
data_socket=DoClose(data_socket);
// read the close control message (should return 2xx)
iRetCode=ReadDisplayLine(ctrl_skt);
}
} 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);
}
int RetrieveFile(SOCKET ctrl_skt,LPSTR szCMD,LPSTR localfile, LPSTR shortname,char rtype)
{
int iRetCode;
int iLength;
iCode=0;
iMultiLine = 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) {
if(rtype==TYPE_L)
command(ctrl_skt,"TYPE L 8");
else
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
iRetCode=command((SOCKET)ctrl_skt,szCMD);
// read the control channel (should return 1xx if it worked)
if(iRetCode==FTP_PRELIM) {
// wait for connection back to us on the listen socket
SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc);
// get our data connection
iLength=sizeof(saSockAddr1);
data_socket=accept(listen_socket,(struct sockaddr far *)&saSockAddr1,
(int far *)&iLength);
// lgk check for error case here
if (data_socket == INVALID_SOCKET)
{
ReportWSError("accept for retrieve",WSAGetLastError());
data_socket=DoClose(data_socket);
return 0;
}
// turn off the timeout timer
KillTimer(hWndMain,10);
// 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,shortname,rtype==TYPE_I);
// shut the data socket down
if(shutdown(data_socket,2)!=0)
ReportWSError("shutdown",WSAGetLastError());
// close the data socket
data_socket=DoClose(data_socket);
// read the close control message (should return 2xx)
iRetCode=ReadDisplayLine(ctrl_skt);
}
} 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 ntlinger;
if(sockfd!=INVALID_SOCKET) {
if(WSAIsBlocking())
{
DoPrintf("[%u] Cancelled blocking call",sockfd);
WSACancelBlockingCall();
bAborted=TRUE;
}
/* dont report error here since shutdown does not work on non data sockets
if(shutdown(sockfd,2)==SOCKET_ERROR)
ReportWSError("shutdown",WSAGetLastError());
*/
// 93.12.04 - so Lanera Winsock Works
ntlinger.l_onoff = TRUE;
ntlinger.l_linger = 20;
setsockopt(sockfd,SOL_SOCKET,SO_LINGER,
(LPSTR)&ntlinger,sizeof(ntlinger) );
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;
if(sockfd==INVALID_SOCKET) return(-1);
if(bCmdInProgress) {
DoAddLine("command in progress, ignored");
return (-1);
}
bCmdInProgress++;
i=strlen(msg);
strcpy(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);
bCmdInProgress--;
return (i);
}
// 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.
bCmdInProgress++;
// count the lines in the response
iMultiLine++;
// initialize some variables
iContinue=0;
// go read the line
iRetCode=ReadLine(sockfd);
// if it wasn't a valid value or the 4th char was a hyphen
// lgk check for error here and return if so
if (iRetCode == SOCKET_ERROR)
{
return iRetCode;
}
if(iRetCode<100 || iRetCode>599 || szMsgBuf[3]=='-')
// then it is a continuation line
iContinue=1;
// send the line we read to our user/debug window
DoAddLine((LPSTR)&szMsgBuf[0]);
// DoPrintf("iRetCode=%u, =%u",iRetCode,iContinue);
// if the timer killed it
if(bAborted) { iCode=iRetCode=421; iContinue=0; }
// we only want to set the real return code in certain situations
if((iMultiLine==1 || iCode==0) && iRetCode>99 && iRetCode<600)
iCode=iRetCode;
// handle continuation lines
if(iContinue==1 || (iCode>0 && iMultiLine>1 && iRetCode!=iCode))
ReadDisplayLine(sockfd);
// count back down our multiline reponses
iMultiLine--;
// allow other processes to run
bCmdInProgress--;
// return only the first char of return code
if(iCode>99 && iCode<600)
return (iCode/100);
else return 0;
}
// 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 nIndex;
int iNumBytes,iN1,iN2; //.iN3;
int iBytesRead;
int iRetCode;
int i;
// char *s;
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;
// zero our receive buffer
memset(szMsgBuf,0,4096);
// initialize some variables
szBuf=szMsgBuf; iBytesRead=0; iRetCode=0;
// set our timeout
SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc);
// 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...
// lgk here we have a bug and it puts the system in an endless loop
// we don't check for a socket error but one happens fix this
iNumBytes=recv(sockfd,(LPSTR)szBuf,82,MSG_PEEK);
if (iNumBytes == SOCKET_ERROR)
{
ReportWSError("socket recv (peek)",WSAGetLastError());
return (SOCKET_ERROR);
}
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);
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(nIndex=0;nIndex<iNumBytes;nIndex++)
if(szBuf[nIndex]==0 || szBuf[nIndex]==0x0a) {
iNumBytes=nIndex+1;
break;
}
// have to treat the UNISYS 5000 (EXOS driver) special. It sends a
// line with a CR at end and no LF and then follows it up with a
// separate packet that has a CR/LF. Usually this second packet is
// not there when we peek but is when we read (answers my question
// about the second receive containing new data!!... jaj 931024)
if(iNumBytes>80 && nHostType==HOST_TYPE_U5000)
for(nIndex=0;nIndex<iNumBytes;nIndex++)
if(szBuf[nIndex]==0x0d) {
iNumBytes=nIndex+2;
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.
if(*(szBuf-1)==0x0a)
break; // '\n') break;
// otherwise reset the timer and go read more characters
SetTimer(hWndMain,10,uiTimeOut*1000,(TIMERPROC)mytimerproc);
}
// if we are here, we have a line or an error or there was nothing to read
KillTimer(hWndMain,10);
// in any case terminate what we have
*szBuf=0;
// find the retcode at the beginning of the line
c=szMsgBuf[3]; szMsgBuf[3]=0; iRetCode=atoi(szMsgBuf); szMsgBuf[3]=c;
// if the timer killed it
if(bAborted) iRetCode=421;
// strip trailing blanks, CR's and LF's
while((i=strlen(szMsgBuf))>2 &&
(szMsgBuf[i-1]==0x0a || szMsgBuf[i-1]==0x0d || szMsgBuf[i-1]==' '))
szMsgBuf[i-1]=0;
// unmark our progress
bCmdInProgress--;
return(iRetCode);
}
// 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);
}
// send a file through the data socket
int SendMass(SOCKET sockfd,LPSTR filename,BOOL binaryflag)
{
int iNumBytes;
int iRetCode;
int iFileHandle;
long lBytesWritten;
time_t ttStart,ttStop,ttDiff;
iRetCode=0;
// if we don't have a socket, return an error
if(sockfd==INVALID_SOCKET || !(bConnected)) return 0;
// turn on a flag so other routines know we have a command in progress
bCmdInProgress++;
// initialize some vars
lBytesWritten=0l; iRetCode=0;
// at the moment we are ignoring the fact that the local destination file
// may not open correctly.
if((iFileHandle=_lopen(filename,OF_READ))== -1) {
DoPrintf("failed to open file %s (%u)",filename,errno);
if(bBell) MessageBeep(MB_ICONEXCLAMATION);
} else {
// get the start time
ttStart=time(NULL);
// loop to send output to remote end
while((iNumBytes=_lread(iFileHandle,szMsgBuf,512))>0)
{
// this forces binary mode at the moment
iRetCode=sendstr(sockfd,szMsgBuf,iNumBytes);
// count the characters that we received
lBytesWritten+=iNumBytes;
wsprintf(szString,"%lu",lBytesWritten);
SendMessage(hTxtLBytes,WM_SETTEXT,0,(LPARAM)szString);
}
// get the finish time
ttStop=time(NULL);
// if the output file is open, close it
_lclose(iFileHandle);
// show the user how we did
SendMessage(hTxtLBytes,WM_SETTEXT,0,(LPARAM)NULL);
ttDiff=ttStop-ttStart;
if(ttDiff==0l) ttDiff=1l;
// lgk fix to convert bps to k/sec if bps > 1024
if (lBytesWritten > 1024)
DoPrintf("%ld bytes transmitted in %.2f seconds, (%3.2fKbytes/sec), transfer %s",
lBytesWritten,(float)ttDiff,(float)lBytesWritten/1024.000/(float)ttDiff,
(iFileHandle==-1)?"failed":"succeeded");
else
DoPrintf("Transmitted %ld bytes in %ld secs, %ld bps, transfer %s",
lBytesWritten,(long)ttDiff,
lBytesWritten*8l/(long)(ttDiff),
(iFileHandle==-1)?"failed":"succeeded");
iRetCode=TRUE;
if(bBell) MessageBeep(MB_ICONASTERISK);
}
// turn off our command in progress flag
bCmdInProgress--;
return (iRetCode);
}
// read information from the data socket into a file.
int ReadMass(SOCKET sockfd,LPSTR filename, LPSTR shortname, BOOL binaryflag)
{
int iNumBytes;
int iRetCode;
int iFileHandle;
long lBytesRead;
time_t ttStart,ttStop,ttDiff;
// if we don't have a socket, return an error
if(sockfd==INVALID_SOCKET || !(bConnected)) return 0;
// turn on a flag so other routines know we have a command in progress
bCmdInProgress++;
// make sure we don't mistakenly think we timed out
KillTimer(hWndMain,10); bAborted=FALSE;
// initialize some vars
lBytesRead=0l; iRetCode=0;
// at the moment we are ignoring the fact that the local destination file
// may not open correctly.
if((iFileHandle=_lcreat(filename,0))== -1)
{
DoPrintf("failed to open file %s (%u)",filename,errno);
DoPrintf("Trying shorting name %s ",shortname);
if ((iFileHandle=_lcreat(shortname,0)) == -1)
DoPrintf("Still failed to open file %s (%u)",shortname,errno);
}
// here if the name was too long than may be an ntfs partition so try the shorter name
// get the start time
ttStart=time(NULL);
// loop to receive input from remote end
while(!bAborted && (iNumBytes=recv(sockfd,(LPSTR)szMsgBuf,4000,0))>0)
{
// write what we received if the file is open
if(iFileHandle!= -1)
_lwrite(iFileHandle,szMsgBuf,iNumBytes);
// count the characters that we received
lBytesRead+=iNumBytes;
// update screen
wsprintf(szString,"%lu",lBytesRead);
SendMessage(hTxtRBytes,WM_SETTEXT,0,(LPARAM)szString);
}
// get the finish time
ttStop=time(NULL);
// if the output file is open, close it
if(iFileHandle != -1) _lclose(iFileHandle);
// if we had a recv error, let us know about it
if(iNumBytes==SOCKET_ERROR)
{
ReportWSError("recv",WSAGetLastError());
if(lBytesRead==0l)
{
if(bBell) MessageBeep(MB_ICONEXCLAMATION);
bCmdInProgress--;
return(FALSE);
}
}
SendMessage(hTxtRBytes,WM_SETTEXT,0,(LPARAM)NULL);
ttDiff=ttStop-ttStart;
if(ttDiff==0l) ttDiff=1l;
// show the user how we did
if (lBytesRead > 1024)
{
DoPrintf("%ld bytes received in %.2f seconds, (%3.2fKbytes/sec), transfer %s",
lBytesRead,(float)ttDiff,(float)lBytesRead/1024.000/(float)ttDiff,
(iFileHandle==-1 || bAborted)?"failed":"succeeded");
// lgk set global variable so that we know it succeeded so we will
// close window
globalsucceed = TRUE;
if (iFileHandle == -1)
globalsucceed = FALSE;
}
else
DoPrintf("Received %ld bytes in %ld secs, %ld bps, transfer %s",
lBytesRead,(long)ttDiff,
lBytesRead*8l/(long)ttDiff,
(iFileHandle==-1 || bAborted)?"failed":"succeeded");
// lgk set global variable so that we know it succeeded so we will
// close window
globalsucceed = TRUE;
if (iFileHandle == -1)
globalsucceed = FALSE;
// DoPrintf("Bell = %d \n",bBell);
if(bBell > 0) MessageBeep(MB_ICONASTERISK);
// turn off our command in progress flag
bCmdInProgress--;
return (TRUE);
}