/* Copyright (c) 1998 Alexander Yukhimets. All rights reserved. */
#include"utils.h"
#include<string.h>
#include<signal.h>
#include<ctype.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<errno.h>
#include<netdb.h>
#include<sys/types.h>
#include<sys/time.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<arpa/ftp.h>
#include<arpa/telnet.h>
extern int h_errno;
#include"ftp.h"
#define FTP_MIN_BUF 256
static int interrupt;
void handler(int sig){
interrupt=sig;
/*printf("\n\n\n\nGOT SIGNAL!\n\n\n");*/
return;
}
int ftp_size(long* size,char type,char* name,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* cmd;
int ret;
if(name==NULL){
*size=-1;
return 0;
}
cmd=WXmalloc(strlen(name)+9);
sprintf(cmd,"TYPE %c\r\n",type);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
*size=-1;
WXfree(cmd);
return ret;
}
if(cd->lastline[0]!='2'){
*size=-1;
WXfree(cmd);
return 1;
}
sprintf(cmd,"SIZE %s\r\n",name);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
*size=-1;
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2' || strlen(cd->lastline)<5){
*size=-1;
return 2;
}
*size=atol(&cd->lastline[4]);
return 0;
}
int ftp_rename(char* from,char* to,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* cmd;
int ret;
if(from==NULL || to==NULL)return 0;
cmd=WXmalloc(strlen(from)+8);
sprintf(cmd,"RNFR %s\r\n",from);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='3'){
return 2;
}
cmd=WXmalloc(strlen(to)+8);
sprintf(cmd,"RNTO %s\r\n",to);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
int ftp_site(char* name,connect_data* cd,FILE* log,ftp_check_proc proc){
char* cmd;
int ret;
if(name==NULL)return 0;
cmd=WXmalloc(strlen(name)+8);
sprintf(cmd,"SITE %s\r\n",name);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
int ftp_mkdir(char* name,connect_data* cd,FILE* log,ftp_check_proc proc){
char* cmd;
int ret;
if(name==NULL)return 0;
cmd=WXmalloc(strlen(name)+8);
sprintf(cmd,"MKD %s\r\n",name);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
int ftp_syst(connect_data* cd,FILE* log,ftp_check_proc proc){
int ret;
if((ret=ftp_command("SYST\r\n",cd,log,proc))!=0){
return ret;
}
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
int ftp_rmdir(char* name,connect_data* cd,FILE* log,ftp_check_proc proc){
char* cmd;
int ret;
if(name==NULL)return 0;
cmd=WXmalloc(strlen(name)+8);
sprintf(cmd,"RMD %s\r\n",name);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
int ftp_delete(char* name,connect_data* cd,FILE* log,ftp_check_proc proc){
char* cmd;
int ret;
if(name==NULL)return 0;
cmd=WXmalloc(strlen(name)+8);
sprintf(cmd,"DELE %s\r\n",name);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
int ftp_disconnect(connect_data* cd,FILE* log,ftp_check_proc proc){
int ret;
signal(SIGALRM,handler);
alarm(10);
ret=ftp_command("QUIT\r\n",cd,log,proc);
interrupt=0;
alarm(5);
close(cd->ctrl);
shutdown(cd->ctrl,2);
signal(SIGALRM,SIG_IGN);
return ret;
}
int ftp_command(char* cmd,connect_data* cd,FILE* log,ftp_check_proc proc){
signal(SIGPIPE,handler);
if(log)fputs(cmd,log);
if(write(cd->ctrl,cmd,strlen(cmd))<=0 || interrupt){
signal(SIGPIPE,SIG_IGN);
interrupt=0;
return 10;
}
if(proc && (*proc)()){
signal(SIGPIPE,SIG_IGN);
interrupt=0;
return -1;
}
return ftp_read_response(cd,log,proc);
}
int ftp_read_line(char** retbuf,connect_data* cd,ftp_check_proc proc){
static char* buf=NULL;
static int allocated=0;
int total;
char iac[4];
fd_set selset;
struct timeval seltime;
int retval;
int gotI,gotW,gotD;
if(buf==NULL)buf=WXmalloc(allocated=FTP_MIN_BUF);
signal(SIGPIPE,handler);
interrupt=0;
*retbuf=buf;
total=0;
gotI=0;
gotW=0;
gotD=0;
for(;;){
FD_ZERO(&selset);
FD_SET(cd->ctrl,&selset);
seltime.tv_sec=0;
seltime.tv_usec=100000;
retval=select(cd->ctrl+1,&selset,NULL,NULL,&seltime);
if(retval==0){
if((proc && (*proc)()) || interrupt){
INT_EXIT:
buf[total]='\0';
signal(SIGPIPE,SIG_IGN);
if(interrupt){
interrupt=0;
return 10;
} else return -1;
}
} else if(retval<0){
(void)(proc && (*proc)());
buf[total]='\0';
signal(SIGPIPE,SIG_IGN);
interrupt=0;
return 10;
} else {
retval=read(cd->ctrl,&buf[total],1);
if(retval==0){
/* EOF */
(void)(proc && (*proc)());
buf[total]='\0';
signal(SIGPIPE,SIG_IGN);
interrupt=0;
/*printf("\n\n\nEOF EOF EOF!!!!!!!!!!!!\n\n\n");*/
return 10;
}
if(retval<0){
(void)(proc && (*proc)());
buf[total]='\0';
signal(SIGPIPE,SIG_IGN);
interrupt=0;
return 10;
}
if(gotI){
if(buf[total]==(char)WILL || buf[total]==(char)WONT){
gotW=1;
gotI=0;
} else if(buf[total]==(char)DO || buf[total]==(char)DONT){
gotD=1;
gotI=0;
} else {
gotI=0;
goto NORMAL_CHAR;
}
} else if(gotW || gotD){
sprintf(iac,"%c%c%c",IAC,gotW?DONT:WONT,buf[total]);
write(cd->ctrl,iac,3);
if(interrupt)goto INT_EXIT;
gotW=0;gotD=0;
} else {
NORMAL_CHAR:
switch(buf[total]){
case '\0':
break;
case '\n':
(void)(proc && (*proc)());
signal(SIGPIPE,SIG_IGN);
interrupt=0;
buf[++total]='\0';
return 0;
default:
total++;
if(allocated-total<3){
*retbuf=buf=WXrealloc(buf,allocated+=FTP_MIN_BUF);
}
break;
}
}
}
}
}
int ftp_read_response(connect_data* cd,FILE* log,ftp_check_proc proc){
int r,len;
int first;
char code[4];
char* p;
first=1;
for(;;){
r=ftp_read_line(&p,cd,proc);
cd->lastline=p;
if(log)fputs(p,log);
if(r){
if(log)fputc('\n',log);
return r;
}
len=strlen(p);
if(first){
if(len<4)return 2;
if(p[3]=='-'){
strncpy(code,p,3);
code[3]=' ';
first=0;
} else {
return 0;
}
} else {
if(len >=4 && strncmp(code,p,4)==0){
return 0;
}
}
}
}
struct in_addr* ftp_gethosts(char* host,ftp_check_proc proc){
int fd[2];
int child;
if(pipe(fd)<0)return NULL;
signal(SIGPIPE,handler);
interrupt=0;
if((child=fork())==0){
/* child */
char** p;
struct hostent *ht=NULL;
close(fd[0]);
ht=gethostbyname(host);
if(ht==NULL){
child=-1;
write(fd[1],&child,sizeof(int));
close(fd[1]);
_exit(0);
}
p=ht->h_addr_list;
child=0;
while(p[0]){
child++;
p++;
}
p=ht->h_addr_list;
write(fd[1],&child,sizeof(int));
while(child){
write(fd[1],p[0],sizeof(struct sockaddr_in));
p++;child--;
}
close(fd[1]);
_exit(0);
} else if(child<0){
close(fd[0]);
close(fd[1]);
return NULL;
} else {
/* parent */
struct timeval tv;
struct in_addr *buf,*pt;
fd_set fdset;
int num;
close(fd[1]);
for(;;) {
FD_ZERO(&fdset);
FD_SET(fd[0],&fdset);
tv.tv_sec=0;
tv.tv_usec=100000;
if(select(fd[0]+1,&fdset,NULL,NULL,&tv)<=0){
if((proc && (*proc)()) || interrupt){
signal(SIGPIPE,SIG_IGN);
kill(child,SIGKILL);
interrupt=0;
return NULL;
}
} else {
if(read(fd[0],&num,sizeof(int))<=0 || num<=0 || interrupt){
close(fd[0]);
signal(SIGPIPE,SIG_IGN);
kill(child,SIGKILL);
interrupt=0;
return NULL;
}
pt=buf=(struct in_addr*)WXmalloc((num+1)*sizeof(struct in_addr));
while(num){
if(read(fd[0],pt,sizeof(struct in_addr))<=0 || interrupt){
close(fd[0]);
signal(SIGPIPE,SIG_IGN);
kill(child,SIGKILL);
interrupt=0;
return NULL;
}
pt++;num--;
}
memset(pt,0,sizeof(struct in_addr));
close(fd[0]);
signal(SIGPIPE,SIG_IGN);
kill(child,SIGKILL);
interrupt=0;
return buf;
}
}
}
return NULL;
}
/*#define NOFORK*/
static int myconnect(int sock,struct sockaddr *serv_addr,int addrlen,
ftp_check_proc proc){
int p[2];
int child;
#ifdef NOFORK
return connect(sock,serv_addr,addrlen)<0;
#else
signal(SIGPIPE,handler);
interrupt=0;
if(pipe(p)==-1)return 1;
if((child=fork())==-1)return 1;
if(child==0){
/* child */
close(p[0]);
child=connect(sock,serv_addr,addrlen);
write(p[1],&child,sizeof(child));
close(p[1]);
_exit(0);
} else {
/* parent */
struct timeval tv;
fd_set fdset;
int num;
close(p[1]);
for(;;) {
FD_ZERO(&fdset);
FD_SET(p[0],&fdset);
tv.tv_sec=0;
tv.tv_usec=100000;
if(select(p[0]+1,&fdset,NULL,NULL,&tv)<=0){
if((proc && (*proc)()) || interrupt){
signal(SIGPIPE,SIG_IGN);
kill(child,SIGKILL);
close(sock);
interrupt=0;
return 1;
}
} else {
if(read(p[0],&num,sizeof(int))<=0 || num<0 || interrupt){
close(p[0]);
signal(SIGPIPE,SIG_IGN);
kill(child,SIGKILL);
close(sock);
interrupt=0;
return 1;
}
return 0;
}
}
}
return 1;
#endif /* NOFORK */
}
int ftp_connect(char* host,int port,connect_data* cd,
FILE* log,ftp_check_proc proc){
struct in_addr *ht,*pt;
int on;
struct linger lin;
memset(&cd->saddr,(char)0,sizeof(cd->saddr));
cd->saddr.sin_family=AF_INET;
cd->saddr.sin_port=htons(port);
if(proc && (*proc)()){
interrupt=0;
return -1;
}
pt=ht=NULL;
/*if(!inet_aton(host,&cd->saddr.sin_addr)){*/
if((cd->saddr.sin_addr.s_addr=inet_addr(host))==-1){
pt=ht=ftp_gethosts(host,proc);
if(ht==NULL){
return 1;
}
}
if((cd->ctrl=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0 ||
(proc && (*proc)())){
WXfree((char*)ht);
shutdown(cd->ctrl,2);
interrupt=0;
return -1;
}
on=1;
setsockopt(cd->ctrl,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
if(proc && (*proc)()){
shutdown(cd->ctrl,2);
interrupt=0;
return -1;
}
if(ht==NULL){
if(myconnect(cd->ctrl,(struct sockaddr*)&cd->saddr,sizeof(cd->saddr),
proc)<0 || (proc && (*proc)())){
close(cd->ctrl);
interrupt=0;
return -1;
}
} else {
while(((char*)pt)[0]){
memcpy(&cd->saddr.sin_addr,pt,sizeof(struct in_addr));
if(myconnect(cd->ctrl,(struct sockaddr*)&cd->saddr,sizeof(cd->saddr),
proc)>=0){
goto CONNECTED;
}
if(proc && (*proc)()){
WXfree((char*)ht);
interrupt=0;
return -1;
}
pt++;
}
close(cd->ctrl);
WXfree((char*)ht);
interrupt=0;
return 1;
}
CONNECTED:
WXfree((char*)ht);
setsockopt(cd->ctrl,SOL_SOCKET,SO_OOBINLINE,(void*)&on,sizeof(on));
setsockopt(cd->ctrl,SOL_SOCKET,SO_KEEPALIVE,(void*)&on,sizeof(on));
lin.l_onoff=0;
lin.l_linger=0;
setsockopt(cd->ctrl,SOL_SOCKET,SO_LINGER,(void*)&lin,sizeof(lin));
#ifdef IPTOS_LOWDELAY
on=IPTOS_LOWDELAY;
setsockopt(cd->ctrl,IPPROTO_IP,IP_TOS,(void*)&on,sizeof(on));
#endif
on=sizeof(cd->laddr);
if(getsockname(cd->ctrl,(struct sockaddr*)&cd->laddr,&on)<0 ||
(proc && (*proc)())){
close(cd->ctrl);
interrupt=0;
return -1;
}
do {
on=ftp_read_response(cd,log,proc);
if(on!=0 || (proc && (*proc)())){
signal(SIGALRM,SIG_IGN);
interrupt=0;
return -1; /*EOF*/
}
} while(cd->lastline[0]=='1');
(void)(proc &&(*proc)());
interrupt=0;
if(!cd->lastline[0]=='2')return 1;
return 0;
}
int ftp_login(char* user,char* pass,char* account,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* buf;
int ret;
if(proc && (*proc)())return -1;
if(user==NULL)user="";
buf=WXmalloc(strlen(user)+8);
sprintf(buf,"USER %s\r\n",user);
if((ret=ftp_command(buf,cd,log,proc))!=0 || (proc && (*proc)())){
WXfree(buf);
return ret;
}
WXfree(buf);
if(cd->lastline[0]=='2')return 0;
if(cd->lastline[0]!='3') return 1;
if(pass==NULL)pass="";
buf=WXmalloc(strlen(pass)+8);
sprintf(buf,"PASS %s\r\n",pass);
if((ret=ftp_command(buf,cd,log,proc))!=0 || (proc && (*proc)())){
WXfree(buf);
return ret;
}
WXfree(buf);
if(cd->lastline[0]=='2')return 0;
if(cd->lastline[0]!='3') return 1;
if(account==NULL)account="";
buf=WXmalloc(strlen(account)+8);
sprintf(buf,"ACCT %s\r\n",account);
if((ret=ftp_command(buf,cd,log,proc))!=0 || (proc && (*proc)())){
WXfree(buf);
return ret;
}
WXfree(buf);
if(cd->lastline[0]=='2')return 0;
return 1;
}
int ftp_pwd(char** retval,connect_data *cd,FILE* log,ftp_check_proc proc){
static char* cmd="PWD\r\n";
char *start,*end;
int len;
if((len=ftp_command(cmd,cd,log,proc))!=0){
return len;
}
if(cd->lastline[0]!='2'){
return 1;
}
if((start=strchr(cd->lastline,'\"'))==NULL){
return 1;
}
if((end=strrchr(cd->lastline,'\"'))==NULL || start>=end){
return 1;
}
len=(int)(end-start);
*retval=WXmalloc(len);
strncpy(*retval,++start,len-1);
(*retval)[len-1]='\0';
return 0;
}
int ftp_sendport_init(connect_data* cd,FILE* log,ftp_check_proc proc){
int on;
struct linger lin;
char cmd[35];
cd->daddr=cd->laddr;
cd->daddr.sin_port=0;
if((cd->data=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0){
return 1;
}
on=1;
(void)setsockopt(cd->data,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
on=1;
(void)setsockopt(cd->data,SOL_SOCKET,SO_KEEPALIVE,(void*)&on,sizeof(on));
lin.l_onoff=1;
lin.l_linger=600;
(void)setsockopt(cd->data,SOL_SOCKET,SO_LINGER,(void*)&lin,sizeof(lin));
#ifdef IPTOS_THROUGHPUT
on=IPTOS_THROUGHPUT;
(void)setsockopt(cd->data,IPPROTO_IP,IP_TOS,(void*)&on,sizeof(on));
#endif
if(bind(cd->data,(struct sockaddr*)&cd->daddr,sizeof(cd->daddr))<0){
fprintf(log,"%s\n",strerror(errno));
return 1;
}
on=sizeof(cd->daddr);
if(getsockname(cd->data, (struct sockaddr *)&cd->daddr,&on)<0){
fprintf(log,"%s\n",strerror(errno));
return 1;
}
if(listen(cd->data,1)<0){
fprintf(log,"%s\n",strerror(errno));
return 1;
}
sprintf(cmd,"PORT %d,%d,%d,%d,%d,%d\r\n",
(int)((char*)&cd->daddr.sin_addr)[0] & 0xFF,
(int)((char*)&cd->daddr.sin_addr)[1] & 0xFF,
(int)((char*)&cd->daddr.sin_addr)[2] & 0xFF,
(int)((char*)&cd->daddr.sin_addr)[3] & 0xFF,
(int)((char*)&cd->daddr.sin_port)[0] & 0xFF,
(int)((char*)&cd->daddr.sin_port)[1] & 0xFF);
if((on=ftp_command(cmd,cd,log,proc))!=0){
return on;
}
if(cd->lastline[0]!='2'){
return 1;
}
return 0;
}
int ftp_passive_init(connect_data* cd,FILE* log,ftp_check_proc proc){
int pd[6];
unsigned char ad[6];
int i,on;
struct linger lin;
char* s;
if((on=ftp_command("PASV\r\n",cd,log,proc))!=0){
return on;
}
if(cd->lastline[0]!='2'){
if(cd->lastline[0]=='5'){
cd->passive=0;
return ftp_sendport_init(cd,log,proc);
} else return 1;
}
s=&cd->lastline[3];
while(!isdigit((int)(*s))){
if(*s=='\0'){
return 1;
}
s++;
}
if(sscanf(s,"%d,%d,%d,%d,%d,%d",
&pd[0],&pd[1],&pd[2],&pd[3],&pd[4],&pd[5])!=6){
cd->passive=0;
return ftp_sendport_init(cd,log,proc);
}
for(i=0;i<6;i++){
ad[i]=(unsigned char)(pd[i] & 0xFF);
}
memset(&cd->daddr,(char)0,sizeof(cd->daddr));
memcpy(&cd->daddr.sin_addr,&ad[0],4);
memcpy(&cd->daddr.sin_port,&ad[4],2);
cd->daddr.sin_family=AF_INET;
if((cd->data=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0){
return 1;
}
on=1;
setsockopt(cd->data,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
if(connect(cd->data,(struct sockaddr*)&cd->daddr,sizeof(cd->daddr))<0){
cd->passive=0;
close(cd->data);
shutdown(cd->data,2);
return ftp_sendport_init(cd,log,proc);
}
setsockopt(cd->data,SOL_SOCKET,SO_KEEPALIVE,(void*)&on,sizeof(on));
lin.l_onoff=1;
lin.l_linger=600;
setsockopt(cd->data,SOL_SOCKET,SO_LINGER,(void*)&lin,sizeof(lin));
#ifdef IPTOS_THROUGHPUT
on=IPTOS_THROUGHPUT;
setsockopt(cd->data,IPPROTO_IP,IP_TOS,(void*)&on,sizeof(on));
#endif
return 0;
}
int ftp_data_init(connect_data* cd,FILE* log,ftp_check_proc proc){
if(cd->passive) return ftp_passive_init(cd,log,proc);
else return ftp_sendport_init(cd,log,proc);
}
int ftp_passive_connect(connect_data* cd,FILE* log,ftp_check_proc proc){
return 0;
}
int ftp_sendport_connect(connect_data* cd,FILE* log,ftp_check_proc proc){
int on,fd;
on=sizeof(struct sockaddr);
if((fd=accept(cd->data,(struct sockaddr*)&cd->daddr,&on))<0){
fprintf(log,"%s\n",strerror(errno));
return 1;
}
close(cd->data);
cd->data=fd;
return 0;
}
int ftp_data_connect(connect_data* cd,FILE* log,ftp_check_proc proc){
if(cd->passive) return ftp_passive_connect(cd,log,proc);
else return ftp_sendport_connect(cd,log,proc);
}
int ftp_list(char* opt,char* mask,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* cmd;
int ret;
if((ret=ftp_command("TYPE A\r\n",cd,log,proc))!=0){
return ret;
}
if(cd->lastline[0]!='2'){
return 1;
}
if((ret=ftp_data_init(cd,log,proc))!=0){
return ret;
}
if(opt==NULL)opt="";
if(mask==NULL)mask="";
cmd=WXmalloc(strlen(opt)+strlen(mask)+9);
if(strlen(opt)==0){
if(strlen(mask)==0){
sprintf(cmd,"LIST\r\n");
} else {
sprintf(cmd,"LIST %s\r\n",mask);
}
} else {
if(strlen(mask)==0){
sprintf(cmd,"LIST %s\r\n",opt);
} else {
sprintf(cmd,"LIST %s %s\r\n",opt,mask);
}
}
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='1'){
return 1;
}
return ftp_data_connect(cd,log,proc);
}
int ftp_put(char type,char* local,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* cmd;
int ret;
if(local==NULL){
return 0;
}
if((ret=ftp_data_init(cd,log,proc))!=0){
return ret;
}
ret=4;
cmd=WXmalloc(strlen(local)+9);
sprintf(cmd,"TYPE %c\r\n",type);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
if(cd->lastline[0]!='2'){
WXfree(cmd);
return 1;
}
sprintf(cmd,"STOR %s\r\n",local);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='1'){
return 1;
}
return ftp_data_connect(cd,log,proc);
}
int ftp_get(char type,char* remote,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* cmd;
int ret;
if(remote==NULL){
return 0;
}
if((ret=ftp_data_init(cd,log,proc))!=0){
return ret;
}
cmd=WXmalloc(strlen(remote)+9);
sprintf(cmd,"TYPE %c\r\n",type);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
if(cd->lastline[0]!='2'){
WXfree(cmd);
return 1;
}
sprintf(cmd,"RETR %s\r\n",remote);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='1'){
return 1;
}
return ftp_data_connect(cd,log,proc);
}
int ftp_resume(char type,long size,char* remote,connect_data* cd,FILE* log,
ftp_check_proc proc){
char* cmd;
int ret;
if(remote==NULL){
return 0;
}
if((ret=ftp_data_init(cd,log,proc))!=0){
return ret;
}
cmd=WXmalloc(strlen(remote)+40);
sprintf(cmd,"TYPE %c\r\n",type);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
if(cd->lastline[0]!='2'){
WXfree(cmd);
return 1;
}
sprintf(cmd,"REST %ld\r\n",size);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
if(cd->lastline[0]!='3'){
return 1;
}
sprintf(cmd,"RETR %s\r\n",remote);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='1'){
return 1;
}
return ftp_data_connect(cd,log,proc);
}
int ftp_abort_data(connect_data* cd,FILE* log,ftp_check_proc proc){
char buf[3];
int ret;
signal(SIGPIPE,handler);
signal(SIGALRM,handler);
sprintf(buf,"%c%c",IAC,IP);
if(write(cd->ctrl,buf,2)<=0 || interrupt){
shutdown(cd->data,2);
signal(SIGPIPE,SIG_IGN);
signal(SIGALRM,SIG_IGN);
interrupt=0;
return 10;
}
sprintf(buf,"%c%c",IAC,DM);
if(send(cd->ctrl,buf,2,MSG_OOB)<=0 || interrupt){
shutdown(cd->data,2);
signal(SIGPIPE,SIG_IGN);
signal(SIGALRM,SIG_IGN);
interrupt=0;
return 10;
}
ret=ftp_command("ABOR\r\n",cd,log,proc);
shutdown(cd->data,2);
close(cd->data);
signal(SIGPIPE,SIG_IGN);
signal(SIGALRM,SIG_IGN);
interrupt=0;
return ftp_read_response(cd,log,proc);
}
int ftp_close_data(connect_data* cd,FILE* log,ftp_check_proc proc){
shutdown(cd->data,2);
close(cd->data);
return ftp_read_response(cd,log,proc);
}
int ftp_chdir(char* dir,connect_data* cd,FILE* log,ftp_check_proc proc){
char* cmd;
int ret;
if(dir==NULL)return 0;
cmd=WXmalloc(strlen(dir)+7);
sprintf(cmd,"CWD %s\r\n",dir);
if((ret=ftp_command(cmd,cd,log,proc))!=0){
WXfree(cmd);
return ret;
}
WXfree(cmd);
if(cd->lastline[0]!='2'){
return 2;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1