A programmatic interface to ftp. I need this for several other
components of the system. The license is poorly worded, though I have an (email only) release from the author for unlimited FreeBSD use. I will try to get something more concrete, though the author's remote location makes this difficult. Submitted by: Oleg Orel <orel@oea.ihep.su>
This commit is contained in:
parent
6ec8ee4578
commit
6f52f41fb2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/libftp/; revision=8064
47
lib/libftp/FtpAbort.c
Normal file
47
lib/libftp/FtpAbort.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
|
||||
FtpAbort(FTP *ftp)
|
||||
{
|
||||
fd_set fds;
|
||||
char msgc=IAC;
|
||||
String msg;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fileno(FTPCMD(ftp)),&fds);
|
||||
|
||||
FtpPutc(ftp, FTPCMD(ftp), IAC);
|
||||
FtpPutc(ftp, FTPCMD(ftp), IP);
|
||||
|
||||
if ( send ( fileno(FTPCMD(ftp)), &msgc , 1 ,MSG_OOB) != 1 )
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
FtpPutc(ftp, FTPCMD(ftp), DM);
|
||||
|
||||
FtpSendMessage(ftp,"ABOR");
|
||||
|
||||
while (select ( getdtablesize(), &fds, 0,0, &(ftp->timeout) )>0)
|
||||
{
|
||||
register int i;
|
||||
|
||||
FtpGetMessage(ftp,msg);
|
||||
if (FtpGood(FtpNumber(msg),225,226,EOF)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
63
lib/libftp/FtpArchie.c
Normal file
63
lib/libftp/FtpArchie.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
#define C2I(n) ((int)((n)-'0'))
|
||||
|
||||
int FtpArchie ( char *what, ARCHIE *result, int len)
|
||||
{
|
||||
FILE *archie;
|
||||
String cmd,tmp;
|
||||
int i;
|
||||
|
||||
bzero(result,sizeof(result[0])*len);
|
||||
|
||||
sprintf(cmd,"archie -l -m %d %s",len,what);
|
||||
|
||||
if ((archie = popen(cmd,"r"))==NULL)
|
||||
return 0;
|
||||
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
char *p, *pp;
|
||||
|
||||
if (fgets(tmp,sizeof (tmp), archie)==NULL)
|
||||
break;
|
||||
|
||||
|
||||
result[i].createtime.tm_year = C2I (tmp[2 ])*10 - 70 + C2I(tmp[3]);
|
||||
result[i].createtime.tm_mday = C2I (tmp[4 ])*10 + C2I(tmp[5]);
|
||||
result[i].createtime.tm_hour = C2I (tmp[6 ])*10 + C2I(tmp[7]);
|
||||
result[i].createtime.tm_min = C2I (tmp[8 ])*10 + C2I(tmp[9]);
|
||||
result[i].createtime.tm_sec = C2I (tmp[10])*10 + C2I(tmp[11]);
|
||||
|
||||
for(p=tmp; *p!=' '; p++);
|
||||
for(; *p==' '; p++);
|
||||
|
||||
result[i].size = atoi(p);
|
||||
|
||||
for(; *p!=' '; p++);
|
||||
for(; *p==' '; p++);
|
||||
|
||||
for (pp=result[i].host;*p!=' ';p++,pp++) *pp=*p;
|
||||
*pp=0;
|
||||
for(; *p==' '; p++);
|
||||
for (pp=result[i].file;*p!='\n';p++,pp++) *pp=*p;
|
||||
*pp=0;
|
||||
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
50
lib/libftp/FtpBye.c
Normal file
50
lib/libftp/FtpBye.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
#include <signal.h>
|
||||
|
||||
STATUS FtpBye(FTP *ftp)
|
||||
{
|
||||
String S1;
|
||||
int i;
|
||||
|
||||
FtpAssert(ftp,FtpCommand(ftp,"QUIT",221,EOF));
|
||||
|
||||
fclose(FTPCMD(ftp));
|
||||
free(ftp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATUS FtpQuickBye(FTP *ftp)
|
||||
{
|
||||
|
||||
|
||||
if (ftp == NULL) return;
|
||||
|
||||
if (FTPDATA(ftp)!=NULL)
|
||||
{
|
||||
shutdown(fileno(FTPDATA(ftp)),2);
|
||||
fclose(FTPDATA(ftp));
|
||||
}
|
||||
|
||||
if (FTPCMD(ftp)!=NULL)
|
||||
{
|
||||
shutdown(fileno(FTPCMD(ftp)),2);
|
||||
fclose(FTPCMD(ftp));
|
||||
}
|
||||
|
||||
free(ftp);
|
||||
}
|
||||
|
26
lib/libftp/FtpClose.c
Normal file
26
lib/libftp/FtpClose.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpClose(FTP *ftp)
|
||||
{
|
||||
int i;
|
||||
String S1;
|
||||
|
||||
fflush(FTPDATA(ftp));
|
||||
shutdown(fileno(FTPDATA(ftp)),2);
|
||||
fclose(FTPDATA(ftp));
|
||||
|
||||
FtpAssert(ftp,i=FtpGetMessage(ftp,S1));
|
||||
if ( i != 226 )
|
||||
return EXIT(ftp,-i);
|
||||
return EXIT(ftp,i);
|
||||
}
|
60
lib/libftp/FtpCommand.c
Normal file
60
lib/libftp/FtpCommand.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpCommand(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
FTP *con;
|
||||
char *command, *param;
|
||||
int Answer[MAX_ANSWERS];
|
||||
va_list args;
|
||||
String S1;
|
||||
int i,counter=0;
|
||||
|
||||
va_start(args);
|
||||
|
||||
con = va_arg(args,FTP *);
|
||||
command = va_arg(args,char *);
|
||||
param = va_arg(args, char *);
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if (counter == MAX_ANSWERS)
|
||||
return EXIT(con,QUIT);
|
||||
Answer[counter] = va_arg(args,int);
|
||||
if (Answer[counter] == EOF ) break;
|
||||
counter++;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
|
||||
sprintf(S1,command,param);
|
||||
|
||||
if ( FtpSendMessage(con,S1) == QUIT )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ( (i=FtpGetMessage(con,S1)) == QUIT )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ( ! FtpGood1 ( i , Answer ))
|
||||
return EXIT(con,-i);
|
||||
|
||||
return EXIT(con,i);
|
||||
}
|
||||
|
||||
|
||||
|
71
lib/libftp/FtpConnect.c
Normal file
71
lib/libftp/FtpConnect.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpConnect(FTP **con,char * hostname)
|
||||
{
|
||||
struct sockaddr_in unit;
|
||||
register struct hostent *host;
|
||||
register int new_socket;
|
||||
String S1;
|
||||
STATUS x;
|
||||
|
||||
*con = FtpCreateObject();
|
||||
|
||||
if ((host=FtpGetHost(hostname))==NULL)
|
||||
return EXIT((*con),QUIT);
|
||||
|
||||
strcpy((*con) -> title,host -> h_name); /* Default title for FtpLog */
|
||||
|
||||
unit.sin_family = host -> h_addrtype; /* AF_INET */
|
||||
|
||||
bcopy(host-> h_addr_list[0],(char *)&unit.sin_addr,host->h_length);
|
||||
if ( ( new_socket = socket ( unit.sin_family , SOCK_STREAM , 0)) < 0)
|
||||
return EXIT((*con),QUIT);
|
||||
|
||||
unit.sin_port = htons((*con)->port);
|
||||
|
||||
while ( connect ( new_socket , (struct sockaddr *)&unit , sizeof unit ) < 0 )
|
||||
{
|
||||
host -> h_addr_list ++;
|
||||
if (host -> h_addr_list[0]==NULL) {
|
||||
close(new_socket);
|
||||
return EXIT((*con),QUIT);
|
||||
}
|
||||
bcopy(host -> h_addr_list[0],(char *)&unit,host->h_length);
|
||||
close(new_socket);
|
||||
if ( ( new_socket = socket ( unit.sin_family , SOCK_STREAM , 0)) < 0)
|
||||
{
|
||||
close(new_socket);
|
||||
return EXIT((*con),QUIT);
|
||||
}
|
||||
}
|
||||
|
||||
FTPCMD(*con) = fdopen(new_socket,"r+");
|
||||
|
||||
if ( (x=FtpGetMessage(*con,S1)) == QUIT )
|
||||
return EXIT((*con),QUIT);
|
||||
if ( ! FtpGood(x,120,220,EOF))
|
||||
{
|
||||
close(new_socket);
|
||||
return EXIT((*con),-x);
|
||||
}
|
||||
if ( (*con)->mode != 'A' ) FtpType(*con,(*con)->mode);
|
||||
|
||||
return EXIT((*con),x);
|
||||
}
|
||||
|
||||
|
||||
|
50
lib/libftp/FtpCopy.c
Normal file
50
lib/libftp/FtpCopy.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpCopy (FTP * ftp1 , FTP * ftp2 ,char *in , char * out)
|
||||
{
|
||||
int size;
|
||||
char buffer[FTPBUFSIZ];
|
||||
|
||||
if (!*out) out=in;
|
||||
|
||||
if ( FtpTestFlag(ftp1,FTP_REST) && FtpTestFlag(ftp2,FTP_REST)
|
||||
&& (size=FtpSize(ftp1,in))>0
|
||||
&& FtpCommand(ftp1,"REST 0",0,0,EOF)==350 && FtpCommand(ftp2,"REST 0",0,0,EOF)==350 )
|
||||
ftp1->seek=ftp2->seek=size;
|
||||
else
|
||||
ftp1->seek=ftp2->seek=0;
|
||||
|
||||
FtpAssert(ftp1,FtpData(ftp1,"RETR %s",in,"r"));
|
||||
FtpAssert(ftp2,FtpData(ftp2,"STOR %s",out,"w"));
|
||||
|
||||
while ((size=FtpReadBlock(ftp1,buffer,FTPBUFSIZ))>0)
|
||||
{
|
||||
if (FtpWriteBlock(ftp2,buffer,size)!=size)
|
||||
return EXIT(ftp2,QUIT);
|
||||
}
|
||||
|
||||
FtpAssert(ftp1,FtpClose(ftp1));
|
||||
FtpAssert(ftp2,FtpClose(ftp2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
90
lib/libftp/FtpData.c
Normal file
90
lib/libftp/FtpData.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpData(FTP * con,char * command , char * file ,char * mode)
|
||||
{
|
||||
struct sockaddr_in data,from;
|
||||
register struct hostent *host;
|
||||
String hostname,cmd;
|
||||
int NewSocket,Accepted_Socket,len=sizeof(data),one=1,fromlen=sizeof(from),i;
|
||||
char *a,*b;
|
||||
|
||||
FREE(data);
|
||||
FREE(from);
|
||||
|
||||
if ( gethostname( hostname , sizeof hostname ) == -1 )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ((host=(struct hostent *)gethostbyname(hostname))==0)
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
data.sin_family = host -> h_addrtype;
|
||||
|
||||
bcopy(host-> h_addr_list[0],(char *)&data.sin_addr,host->h_length);
|
||||
|
||||
if ((NewSocket = socket ( AF_INET , SOCK_STREAM , 0 ))<0)
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ( setsockopt ( NewSocket , SOL_SOCKET , SO_REUSEADDR ,
|
||||
(char *)&one , sizeof(one) ) < 0 )
|
||||
{
|
||||
close(NewSocket);
|
||||
return EXIT ( con,QUIT );
|
||||
}
|
||||
|
||||
data.sin_port = 0 ;
|
||||
|
||||
if ( bind ( NewSocket , (struct sockaddr *)&data , sizeof data ) < 0 )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ( getsockname ( NewSocket , &data , &len ) < 0 )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ( listen ( NewSocket , 1 ) < 0 )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
a = ( char * ) & data.sin_addr;
|
||||
b = ( char * ) & data.sin_port;
|
||||
|
||||
FtpAssert(con,FtpPort(con,CUT(a[0]),CUT(a[1]),CUT(a[2]),
|
||||
CUT(a[3]),CUT(b[0]),CUT(b[1])));
|
||||
|
||||
if ( con -> seek != 0)
|
||||
{
|
||||
if ((i = FtpCommand ( con, "REST %d" , con -> seek , 0, EOF)) != 350 )
|
||||
return -i;
|
||||
}
|
||||
|
||||
FtpAssert(con, FtpCommand ( con , command , file ,
|
||||
200, 120 , 150 , 125 , 250 , EOF ));
|
||||
|
||||
if (( Accepted_Socket = accept (NewSocket , &from , &fromlen )) < 0)
|
||||
{
|
||||
close(NewSocket);
|
||||
return EXIT(con,QUIT);
|
||||
}
|
||||
|
||||
close(NewSocket);
|
||||
|
||||
FTPDATA(con) = fdopen(Accepted_Socket, "r+");
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
90
lib/libftp/FtpDebug.c
Normal file
90
lib/libftp/FtpDebug.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
void FtpDebug(FTP *ftp)
|
||||
{
|
||||
STATUS FtpDebugDebug(),
|
||||
FtpDebugError(),
|
||||
FtpDebugIO();
|
||||
|
||||
FtpSetDebugHandler(ftp,FtpDebugDebug);
|
||||
FtpSetErrorHandler(ftp,FtpDebugError);
|
||||
FtpSetIOHandler(ftp,FtpDebugIO);
|
||||
}
|
||||
|
||||
STATUS FtpDebugDebug(FTP *ftp,int n, char * Message)
|
||||
{
|
||||
String tmp;
|
||||
|
||||
|
||||
strcpy(tmp,Message);
|
||||
|
||||
if (strncmp(tmp,"PASS ",5)==0)
|
||||
{
|
||||
char *p=tmp+5;
|
||||
while ( *p != '\0') *p++='*';
|
||||
};
|
||||
|
||||
FtpLog(ftp->title,tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
STATUS FtpDebugError(FTP *ftp,int n, char * Message)
|
||||
{
|
||||
|
||||
FtpLog("FtpDebugError","");
|
||||
FtpLog(ftp->title,Message);
|
||||
if ( ! FtpTestFlag(ftp,FTP_NOEXIT))
|
||||
exit(1);
|
||||
}
|
||||
|
||||
STATUS FtpDebugIO(FTP *ftp,int n, char * Message)
|
||||
{
|
||||
FtpLog("FtpDebugIO","");
|
||||
FtpLog(ftp->title,Message);
|
||||
if ( ! FtpTestFlag(ftp,FTP_NOEXIT))
|
||||
exit(1);
|
||||
}
|
||||
|
||||
STATUS FtpLog(char *name,char *str)
|
||||
{
|
||||
time_t t=time((time_t *)0);
|
||||
struct tm *lt=localtime(&t);
|
||||
fprintf(stderr,"%02d:%02d:%02d %s %s\n",lt->tm_hour,
|
||||
lt->tm_min,lt->tm_sec,name,str);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
FtpHash(FTP *ftp, unsigned long chars)
|
||||
{
|
||||
|
||||
if (chars==0) return ftp->counter=0;
|
||||
ftp->counter+=chars;
|
||||
fprintf(stdout,"%10u bytes transfered\r",ftp->counter);
|
||||
fflush(stdout);
|
||||
return ftp->counter;
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpBadReply550(char *s)
|
||||
{
|
||||
if(
|
||||
(strstr(s,"unreachable")!=NULL) ||
|
||||
(strstr(s,"Broken pipe")!=NULL)
|
||||
)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
43
lib/libftp/FtpFilenameChecker.c
Normal file
43
lib/libftp/FtpFilenameChecker.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
static char * simplename(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ( (p=(char *)strrchr(s,'/')) == NULL )
|
||||
return s;
|
||||
return p+1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
STATUS FtpFilenameChecker(char ** in, char ** out)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ( (stat(*out,&st) == 0) && S_ISDIR(st.st_mode))
|
||||
{
|
||||
char * sfn = simplename(*in);
|
||||
char * new = (char *) malloc ( strlen(*out)+ strlen(sfn) + 2 );
|
||||
|
||||
strcpy(new,*out);
|
||||
strcat(new,"/");
|
||||
strcat(new,sfn);
|
||||
*out=new;
|
||||
return;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
142
lib/libftp/FtpFull.c
Normal file
142
lib/libftp/FtpFull.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
#include <pwd.h>
|
||||
|
||||
static FTP *ftp_table[256];
|
||||
static STATUS syntax();
|
||||
|
||||
FILE * FtpFullOpen(char * file , char * mode )
|
||||
{
|
||||
FTP *ftp;
|
||||
FILE *tmp;
|
||||
String Host,User,Passwd,RemoteFile;
|
||||
STATUS i;
|
||||
|
||||
if ( ! FtpFullSyntax (file,Host,User,Passwd,RemoteFile))
|
||||
{
|
||||
tmp=fopen(file,mode);
|
||||
if (tmp==NULL) return tmp;
|
||||
ftp_table[(int)fileno(tmp)] = NULL;
|
||||
return tmp;
|
||||
}
|
||||
if ( FtpError(i=FtpLogin(&ftp,Host,User,Passwd,NULL)))
|
||||
return NULL;
|
||||
|
||||
if (mode[1]=='b') FtpBinary(ftp);
|
||||
|
||||
switch(mode[0])
|
||||
{
|
||||
case 'r':
|
||||
if (FtpError(FtpOpenRead(ftp,RemoteFile)))
|
||||
return NULL;
|
||||
ftp_table[fileno(FTPDATA(ftp))] = ftp;
|
||||
return FTPDATA(ftp);
|
||||
case 'w':
|
||||
if (FtpError(FtpOpenWrite(ftp,RemoteFile)))
|
||||
return NULL;
|
||||
ftp_table[fileno(FTPDATA(ftp))] = ftp;
|
||||
return FTPDATA(ftp);
|
||||
case 'a':
|
||||
if (FtpError(FtpOpenAppend(ftp,RemoteFile)))
|
||||
return NULL;
|
||||
ftp_table[fileno(FTPDATA(ftp))] = ftp;
|
||||
return FTPDATA(ftp);
|
||||
}
|
||||
/* Error Mode */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATUS FtpFullClose(FILE *f)
|
||||
{
|
||||
FTP *ftp=ftp_table[(int)fileno(f)];
|
||||
if (ftp == NULL)
|
||||
return fclose(f);
|
||||
FtpClose(ftp);
|
||||
return FtpQuickBye(ftp);
|
||||
}
|
||||
|
||||
|
||||
/* Format of ftp's file [user[/passord]@]hostname:filename_with_path */
|
||||
|
||||
STATUS FtpFullSyntax ( String source ,
|
||||
String host ,
|
||||
String user ,
|
||||
String passwd ,
|
||||
String file)
|
||||
|
||||
{
|
||||
char *in,*out;
|
||||
String tmp;
|
||||
|
||||
host[0] = user[0] = passwd[0] = file[0] = '\0';
|
||||
|
||||
for ( in=source, out = user;
|
||||
*in !='\0' && *in != '/' && *in!='@' && *in!=':' ;
|
||||
*out++ = *in++);
|
||||
*out = '\0';
|
||||
|
||||
if ( *in == '\0' ) return 0;
|
||||
|
||||
if ( *in == ':' )
|
||||
{
|
||||
strcpy(host,user);
|
||||
strcpy(user,"anonymous");
|
||||
gethostname(tmp, sizeof tmp);
|
||||
sprintf(passwd,"%s@%s",
|
||||
getpwuid(getuid())->pw_name,gethostbyname(tmp)->h_name);
|
||||
goto file;
|
||||
}
|
||||
|
||||
if ( *in == '/' )
|
||||
{
|
||||
for ( in++, out = passwd;
|
||||
*in !='\0' && *in!='@' ;
|
||||
*out++ = *in++);
|
||||
*out = '\0';
|
||||
if ( *in == '\0' ) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gethostname(tmp, sizeof tmp);
|
||||
sprintf(passwd,"%s@%s",
|
||||
getpwuid(getuid())->pw_name,gethostbyname(tmp)->h_name);
|
||||
}
|
||||
|
||||
|
||||
for ( in++, out = host;
|
||||
*in !='\0' && *in!=':' ;
|
||||
*out++ = *in++);
|
||||
*out = '\0';
|
||||
|
||||
if ( *in == '\0' ) return 0;
|
||||
|
||||
file:
|
||||
|
||||
for ( in++, out = file;
|
||||
*in !='\0';
|
||||
*out++ = *in++);
|
||||
*out = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
44
lib/libftp/FtpGetHost.c
Normal file
44
lib/libftp/FtpGetHost.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
|
||||
|
||||
struct hostent *FtpGetHost(char *host)
|
||||
{
|
||||
|
||||
static struct in_addr addr;
|
||||
static struct hostent _host;
|
||||
static char *point[2];
|
||||
static char *alias[1];
|
||||
|
||||
bzero(&_host,sizeof _host);
|
||||
if ( (addr.s_addr=inet_addr(host)) != -1 )
|
||||
{
|
||||
_host.h_addr_list = point;
|
||||
_host.h_addr_list[0] = (char *) &addr;
|
||||
_host.h_addr_list[1] = (char *) 0;
|
||||
alias[0]=NULL;
|
||||
_host.h_aliases=alias;
|
||||
_host.h_name=host;
|
||||
_host.h_length=sizeof(unsigned long);
|
||||
_host.h_addrtype=AF_INET;
|
||||
return &_host;
|
||||
}
|
||||
|
||||
return gethostbyname(host);
|
||||
}
|
||||
|
||||
|
54
lib/libftp/FtpGood.c
Normal file
54
lib/libftp/FtpGood.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpGood(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
int Number;
|
||||
int Answer[MAX_ANSWERS];
|
||||
int counter=0;
|
||||
|
||||
va_start(args);
|
||||
|
||||
Number = va_arg(args,int);
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if (counter == MAX_ANSWERS)
|
||||
return 0;
|
||||
Answer[counter] = va_arg(args,int);
|
||||
if (Answer[counter] == EOF ) break;
|
||||
counter++;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return FtpGood1(Number,Answer);
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpGood1(int Number , int *Answer)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if ( *Answer == Number) return 1;
|
||||
if ( *Answer == 0) return 1;
|
||||
if ( *Answer == EOF ) return 0;
|
||||
Answer++;
|
||||
}
|
||||
}
|
||||
|
172
lib/libftp/FtpIO.c
Normal file
172
lib/libftp/FtpIO.c
Normal file
@ -0,0 +1,172 @@
|
||||
/* Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the exist
|
||||
ing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
int FtpRead(FTP *con)
|
||||
{
|
||||
int c;
|
||||
|
||||
if ( con -> mode == 'I' )
|
||||
return FtpGetc(con,FTPDATA(con));
|
||||
|
||||
if ( con->ch != EOF )
|
||||
{
|
||||
c=con->ch;
|
||||
con->ch=EOF;
|
||||
return c;
|
||||
}
|
||||
|
||||
c=FtpGetc(con,FTPDATA(con));
|
||||
|
||||
if ( c == Ctrl('M') )
|
||||
{
|
||||
c = FtpGetc(con,FTPDATA(con));
|
||||
|
||||
if ( c == Ctrl('J') )
|
||||
return '\n';
|
||||
con->ch = c;
|
||||
return Ctrl('M');
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int FtpWrite(FTP *ftp,char c)
|
||||
{
|
||||
|
||||
if ( ftp -> mode == 'I' || c != '\n' )
|
||||
return FtpPutc(ftp,FTPDATA(ftp),c);
|
||||
|
||||
FtpPutc(ftp,FTPDATA(ftp),Ctrl('M'));
|
||||
return FtpPutc(ftp,FTPDATA(ftp),Ctrl('J'));
|
||||
}
|
||||
|
||||
|
||||
int FtpGetc(FTP *ftp,FILE *fp)
|
||||
{
|
||||
fd_set fds;
|
||||
char c;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fileno(fp),&fds);
|
||||
|
||||
if (select(getdtablesize(), &fds, 0, 0, &(ftp->timeout))<1)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
if (read(fileno(fp),&c,1)<1)
|
||||
return EOF;
|
||||
|
||||
if (ftp->hash!=NULL) (*ftp->hash)(ftp,1);
|
||||
|
||||
return (int)c;
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpPutc(FTP *ftp,FILE *fp,char c)
|
||||
{
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fileno(fp),&fds);
|
||||
|
||||
if (select(getdtablesize(), 0, &fds, 0, &(ftp->timeout))<1)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
if (write(fileno(fp),&c,1)!=1)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
if (ftp->hash!=NULL) (*ftp->hash)(ftp,1);
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpReadBlock(FTP *ftp, char *buffer, int size)
|
||||
{
|
||||
fd_set fds;
|
||||
register int rsize,status;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fileno(FTPDATA(ftp)),&fds);
|
||||
|
||||
if (select(getdtablesize(), &fds,0, 0, &(ftp->timeout))<1)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
|
||||
if ((rsize=read(fileno(FTPDATA(ftp)),buffer,size))<0)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
if (ftp->hash!=NULL && rsize!=0) (*ftp->hash)(ftp,rsize);
|
||||
|
||||
if (ftp->mode == 'A')
|
||||
{
|
||||
char buffer2[size];
|
||||
register int i,ii;
|
||||
|
||||
for (i=0,ii=0;i<rsize;i++,ii++)
|
||||
if (buffer[i]==Ctrl('M')&&buffer[i+1]==Ctrl('J'))
|
||||
buffer2[ii]='\n',i++;
|
||||
else
|
||||
buffer2[ii]=buffer[i];
|
||||
|
||||
rsize=ii;
|
||||
bcopy(buffer2,buffer,rsize);
|
||||
}
|
||||
return rsize;
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpWriteBlock(FTP *ftp, char *buffer, int size)
|
||||
{
|
||||
fd_set fds;
|
||||
register int wsize;
|
||||
char buffer2[size*2];
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fileno(FTPDATA(ftp)),&fds);
|
||||
|
||||
if (select(getdtablesize(), 0, &fds, 0, &(ftp->timeout))<1)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
|
||||
if (ftp->mode=='A')
|
||||
{
|
||||
register int i,ii;
|
||||
|
||||
for(i=0,ii=0;i<size;i++,ii++)
|
||||
if (buffer[i]=='\n')
|
||||
buffer2[ii++]=Ctrl('M'),buffer2[ii]=Ctrl('J');
|
||||
else
|
||||
buffer2[ii]=buffer[i];
|
||||
buffer=buffer2;
|
||||
size=ii;
|
||||
}
|
||||
|
||||
if ((wsize=write(fileno(FTPDATA(ftp)),buffer,size))!=size)
|
||||
return EXIT(ftp,QUIT);
|
||||
|
||||
if ( ftp->hash!=NULL && wsize!=0 ) (*ftp->hash)(ftp,wsize);
|
||||
|
||||
return wsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
40
lib/libftp/FtpInit.c
Normal file
40
lib/libftp/FtpInit.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
FTP FtpInit = {
|
||||
NULL, /*sock*/
|
||||
NULL, /*data*/
|
||||
'A', /*mode*/
|
||||
0, /*errno*/
|
||||
0, /*ch*/
|
||||
NULL,NULL,NULL, NULL, /*funcs*/
|
||||
0, /*seek*/
|
||||
0, /*flags*/
|
||||
{120,0}, /*timeout 2 min*/
|
||||
21, /*Port*/
|
||||
0, /*Counter*/
|
||||
};
|
||||
|
||||
FTP *FtpCreateObject()
|
||||
{
|
||||
FTP *new = (FTP *) malloc (sizeof(FTP));
|
||||
|
||||
bcopy(&FtpInit,new,sizeof(FTP));
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
264
lib/libftp/FtpLibrary.h
Normal file
264
lib/libftp/FtpLibrary.h
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FTPLIBRARY_H
|
||||
#define __FTPLIBRARY_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/ftp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <varargs.h>
|
||||
#include <arpa/telnet.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Standard Macros & Definitions */
|
||||
|
||||
|
||||
|
||||
#define EXIT(con,e) \
|
||||
( con -> errno = e, \
|
||||
((e==QUIT||e==LQUIT)&&(con->IO != NULL))?(*(con->IO))(con,e,sys_errlist[errno]):0,\
|
||||
((con->error != NULL) && (e < 0) )?(*(con->error))(con,e,FtpMessage(e)):0,\
|
||||
e)
|
||||
|
||||
|
||||
#define MAX_ANSWERS 10 /* Number of known goodest answers for reqest */
|
||||
#define NFDS 64
|
||||
#define FTPBUFSIZ BUFSIZ
|
||||
#define LQUIT (-6)
|
||||
#define QUIT (-5) /* Few time ago QUIT character been
|
||||
equivalence to zero, changed for clear
|
||||
conflicts with reading functions */
|
||||
#define Ctrl(x) ((x) - '@')
|
||||
#define FREE(x) memset ( &(x) , '\0' , sizeof (x) )
|
||||
#define CUT(x) ((x)&0xff)
|
||||
#define FtpError(x) ((x)<0)
|
||||
#define FtpAssert(ftp,x) if (FtpError(x)) return EXIT((ftp),(ftp)->errno);
|
||||
|
||||
typedef int STATUS;
|
||||
typedef char String[256];
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Common Information Structure */
|
||||
|
||||
typedef struct/* All structure initialize from edited struct FtpInit */
|
||||
{
|
||||
FILE *sock; /* Command stream to server */
|
||||
|
||||
#define FTPDATA(x) ((x)->data)
|
||||
#define FTPCMD(x) ((x)->sock)
|
||||
|
||||
|
||||
FILE *data; /* Data stream to server */
|
||||
char mode; /* Binary, Ascii, ......... */
|
||||
int errno; /* Last error code */
|
||||
int ch; /* Help character for ascii streams */
|
||||
|
||||
STATUS (*error)();
|
||||
STATUS (*debug)();
|
||||
STATUS (*IO)();
|
||||
STATUS (*hash)(); /* Call with reading/writing next "int" characters
|
||||
from stream */
|
||||
int seek; /*
|
||||
Warning! If server not supported REST-command,
|
||||
then seek variable automaticaly turn to zero
|
||||
*/
|
||||
int flags; /* FTP_REST,
|
||||
FTP_NOEXIT */
|
||||
struct timeval timeout;
|
||||
/* How long must be waiting next character
|
||||
from server */
|
||||
int port;
|
||||
String title; /* Using for FtpLog, FtpConnect lets hostname */
|
||||
unsigned long counter;
|
||||
/* Using by FtpHash */
|
||||
} FTP;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct tm createtime;
|
||||
unsigned long size;
|
||||
String host;
|
||||
String file;
|
||||
} ARCHIE;
|
||||
|
||||
|
||||
enum {FTP_REST=1,FTP_NOEXIT=2};
|
||||
enum {no,yes};
|
||||
enum {off,on};
|
||||
enum {false,true};
|
||||
|
||||
extern FTP FtpInit;
|
||||
|
||||
/* Options defines */
|
||||
|
||||
#define FtpSetFlag(ftp,flag) ((ftp)->flags|=(flag))
|
||||
#define FtpClearFlag(ftp,flag) ((ftp)->flags &= (~(flag)) )
|
||||
#define FtpTestFlag(ftp,flag) ((ftp)->flags&(flag)==flag)
|
||||
#define FtpSetTimeout(ftp,tim) \
|
||||
((ftp)->timeout.tv_sec=tim,(ftp)->timeout.tv_usec=0)
|
||||
#define FtpSetPort(ftp,prt) ((ftp)->port=(prt))
|
||||
|
||||
/* Connect & disconnect */
|
||||
|
||||
STATUS FtpConnect(FTP **con,char *hostname);
|
||||
#define FtpUser(ftp,user) FtpCommand(ftp,"USER %s",user,230,331,332,EOF)
|
||||
#define FtpPassword(ftp,pas) FtpCommand(ftp,"PASS %s",pas,230,332,EOF)
|
||||
#define FtpAccount(ftp,acc) FtpCommand(ftp,"ACCT %s",acc,230,EOF)
|
||||
STATUS FtpLogin(FTP **con,char *host ,char *user,char *pass,char *acct);
|
||||
STATUS FtpBye (FTP * con);
|
||||
STATUS FtpQuickBye (FTP * con);
|
||||
STATUS FtpAbort(FTP *ftp);
|
||||
|
||||
/* Set type of transfer */
|
||||
|
||||
STATUS FtpType(FTP *ftp,char type);
|
||||
#define FtpAscii(ftp) FtpType(ftp,'A')
|
||||
#define FtpBinary(ftp) FtpType(ftp,'I')
|
||||
|
||||
|
||||
/* Send/Receive and handling Procedure(s) */
|
||||
|
||||
STATUS FtpCopy(FTP *ftp1, FTP *ftp2, char *in, char *out);
|
||||
STATUS FtpPassiveTransfer(FTP *ftp1, FTP *ftp2, char *in, char *out);
|
||||
|
||||
STATUS FtpRetr(FTP *con, char *command,char *inp,char *out);
|
||||
#define FtpGet(ftp,in,out) FtpRetr(ftp,"RETR %s",in,out)
|
||||
#define FtpDirectory(ftp,pat,out) FtpRetr(ftp,"LIST %s",pat,out)
|
||||
#define FtpDir(ftp,out) FtpRetr(ftp,"LIST","",out)
|
||||
|
||||
STATUS FtpStor(FTP *con ,char*command ,char *inp,char *out);
|
||||
#define FtpPut(ftp,in,out) FtpStor(ftp,"STOR %s",in,out)
|
||||
|
||||
STATUS FtpData( FTP * con , char * command , char * param , char *mode);
|
||||
STATUS FtpPort ( FTP *con ,int ,int ,int ,int ,int ,int );
|
||||
#define FtpOpenRead(ftp,file) FtpData(ftp,"RETR %s",file,"r")
|
||||
#define FtpOpenWrite(ftp,file) FtpData(ftp,"STOR %s",file,"w")
|
||||
#define FtpOpenAppend(ftp,file) FtpData(ftp,"APPE %s",file,"r")
|
||||
STATUS FtpOpenDir( FTP * con , char * files );
|
||||
STATUS FtpClose ( FTP *);
|
||||
|
||||
/* Command for hand transfer */
|
||||
|
||||
STATUS FtpRead ( FTP * con);
|
||||
STATUS FtpWrite ( FTP * con , char c);
|
||||
int FtpGetc ( FTP * ftp, FILE *fp );
|
||||
STATUS FtpPutc (FTP *ftp, FILE *fp, char c);
|
||||
|
||||
/* Manipulation commands for remote server */
|
||||
|
||||
STATUS FtpCommand ();
|
||||
#define FtpChdir(ftp,dir) FtpCommand(ftp,"CWD %s",dir,200,250,EOF)
|
||||
#define FtpMkdir(ftp,dir) FtpCommand(ftp,"MKD %s",dir,200,257,EOF)
|
||||
#define FtpRm(ftp,dir) FtpCommand(ftp,"DELE %s",dir,200,250,EOF)
|
||||
char *FtpPwd(FTP *con);
|
||||
int FtpSize(FTP *con,char *filename);
|
||||
STATUS FtpMove ( FTP *con,char * old,char *new);
|
||||
|
||||
/* Procedures for dialog with remote server */
|
||||
|
||||
STATUS FtpInitMessageList();
|
||||
STATUS FtpSendMessage( FTP * con , char * Message );
|
||||
int FtpGetMessage( FTP * con , char * Message);
|
||||
char *FtpMessage(int Number);
|
||||
int FtpNumber ( char * Message );
|
||||
|
||||
|
||||
/* Debug */
|
||||
|
||||
#define FtpSetErrorHandler(con,f) (con)->error = f
|
||||
#define FtpSetDebugHandler(con,f) (con)->debug = f
|
||||
#define FtpSetIOHandler(con,f) (con)->IO =f
|
||||
#define FtpSetHashHandler(con,f) (con)->hash =f
|
||||
#define FtplibDebug(t) FtpDebug(&FtpInit)
|
||||
|
||||
STATUS FtpDebugDebug ( FTP *con, int errno, char * Message);
|
||||
STATUS FtpDebugError ( FTP *con, int errno, char * Message);
|
||||
STATUS FtpDebugIO ( FTP *con, int errno, char * Message);
|
||||
STATUS FtpLog(char *progtitle, char *msg);
|
||||
STATUS FtpHash ( FTP *con, unsigned long number_of_bytes );
|
||||
void FtpDebug ( FTP * con );
|
||||
STATUS FtpBadReply550 (char *message);
|
||||
|
||||
|
||||
/* Other Procedures */
|
||||
|
||||
FTP *FtpCreateObject();
|
||||
FILE *FtpFullOpen(char * file,char * mode );
|
||||
STATUS FtpFullSyntax(String,String,String,String,String);
|
||||
FILE *Ftpfopen(char *filename,char *mode);
|
||||
STATUS Ftpfclose(FILE *);
|
||||
STATUS FtpFullClose(FILE *);
|
||||
STATUS FtpGood ();
|
||||
STATUS FtpGood1 (int, int *);
|
||||
struct hostent *FtpGetHost(char *host);
|
||||
STATUS FtpFilenameChecher(char *input, char *output);
|
||||
STATUS FtpLink(FTP *,FTP *);
|
||||
int FtpArchie(char *what, ARCHIE *, int number);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Additional definitions */
|
||||
|
||||
#ifdef _AIX
|
||||
int accept (int, struct sockaddr_in*, int*);
|
||||
char *bcopy (char*, char*, size_t);
|
||||
int bind (int, const void*, int);
|
||||
int connect (int, struct sockaddr_in*, int);
|
||||
int gethostname (char*, size_t);
|
||||
int getsockname (int, struct sockaddr_in*, int*);
|
||||
int getpeername (int, struct sockaddr_in*, int*);
|
||||
int getsockopt (int, int, int, void*, int*);
|
||||
int listen(int, int);
|
||||
int setsockopt (int, int, int, void*, int);
|
||||
int socket (int, int, int);
|
||||
void free (void*);
|
||||
void *malloc (size_t);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __FTPLIBRARYH_ */
|
||||
|
||||
|
||||
|
34
lib/libftp/FtpLogin.c
Normal file
34
lib/libftp/FtpLogin.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpLogin ( FTP ** con, char * host , char * user ,
|
||||
char * password , char * account)
|
||||
{
|
||||
|
||||
FtpAssert((*con),FtpConnect(con,host));
|
||||
FtpAssert((*con),FtpUser((*con),user));
|
||||
if (((*con)->errno)==230 )
|
||||
return ((*con)->errno);
|
||||
if (((*con)->errno)==332)
|
||||
{
|
||||
if ( account == NULL )
|
||||
return EXIT(((*con)),(*con)->errno);
|
||||
FtpAssert((*con),FtpAccount( (*con) , account ));
|
||||
if ( ((*con)->errno)==230 )
|
||||
return (*con)->errno;
|
||||
}
|
||||
return FtpPassword((*con),password);
|
||||
}
|
130
lib/libftp/FtpMessage.c
Normal file
130
lib/libftp/FtpMessage.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
|
||||
static char * FtpMessageList[1000];
|
||||
|
||||
INLINE static char *___gets(char *s, int maxchars, FTP *ftp)
|
||||
{
|
||||
char *p=s;
|
||||
int c;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((c = FtpGetc(ftp,FTPCMD(ftp))) == EOF)
|
||||
return NULL;
|
||||
|
||||
if ( c == '\n' && *(p-1) == '\r' )
|
||||
{
|
||||
p--;
|
||||
*p='\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
if ( (p-s) > maxchars ) return NULL;
|
||||
|
||||
*p++=(char)c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int FtpGetMessage(FTP *con , char * Message )
|
||||
{
|
||||
int i=0,n;
|
||||
char tmp[1024];
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (___gets(tmp,sizeof tmp,con)==NULL)
|
||||
return EXIT(con,QUIT);
|
||||
if (isdigit(tmp[0]) &&
|
||||
isdigit(tmp[1]) &&
|
||||
isdigit(tmp[2]) &&
|
||||
tmp[3]!='-') break;
|
||||
if ( con -> debug != NULL )
|
||||
(*con->debug)(con,0,tmp);
|
||||
}
|
||||
|
||||
strcpy(Message,tmp);
|
||||
FtpInitMessageList();
|
||||
FtpMessageList[n=FtpNumber(Message)] =
|
||||
( char * ) malloc ( strlen(Message) + 1);
|
||||
strcpy(FtpMessageList[n] , Message );
|
||||
if ( con -> debug != NULL )
|
||||
(*con->debug)(con,n,Message);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
STATUS FtpSendMessage(FTP *ftp,char * Message )
|
||||
{
|
||||
char *msg=Message;
|
||||
|
||||
while (*Message)
|
||||
FtpAssert(ftp,FtpPutc(ftp,FTPCMD(ftp),*Message++));
|
||||
|
||||
FtpAssert(ftp,FtpPutc(ftp,FTPCMD(ftp),'\015'));
|
||||
FtpAssert(ftp,FtpPutc(ftp,FTPCMD(ftp),'\012'));
|
||||
|
||||
if ( ftp -> debug != NULL )
|
||||
(*ftp->debug)(ftp,0,msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *FtpMessage(int number)
|
||||
{
|
||||
extern int sys_nerr,errno;
|
||||
#ifndef __FreeBSD__
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
|
||||
FtpInitMessageList();
|
||||
if ( number == 0 )
|
||||
return sys_errlist[errno];
|
||||
return (FtpMessageList[abs(number)]==NULL)?
|
||||
"":FtpMessageList[abs(number)];
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpInitMessageList()
|
||||
{
|
||||
int i;
|
||||
static u = 0;
|
||||
|
||||
if ( u )
|
||||
return 1;
|
||||
|
||||
u = 1;
|
||||
|
||||
for (i=0;i<1000;i++)
|
||||
FtpMessageList[i]=NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FtpNumber(char *Message)
|
||||
{
|
||||
return (Message[0] - '0') * 100 +
|
||||
(Message[1] - '0') * 10 +
|
||||
(Message[2] - '0') ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
25
lib/libftp/FtpMove.c
Normal file
25
lib/libftp/FtpMove.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpMove(FTP *con,char * oldname , char * newname )
|
||||
{
|
||||
STATUS i;
|
||||
|
||||
if ((i=FtpCommand(con,"RNFR %s",oldname,200,350,EOF)) > 1 )
|
||||
return FtpCommand(con,"RNTO %s",newname,200,250,EOF);
|
||||
else
|
||||
return i;
|
||||
}
|
22
lib/libftp/FtpNumber.c
Normal file
22
lib/libftp/FtpNumber.c
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
int FtpNumber(char *Message)
|
||||
{
|
||||
return (Message[0] - '0') * 100 +
|
||||
(Message[1] - '0') * 10 +
|
||||
(Message[2] - '0') ;
|
||||
}
|
27
lib/libftp/FtpOpenDir.c
Normal file
27
lib/libftp/FtpOpenDir.c
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpOpenDir(FTP * con,char * file)
|
||||
{
|
||||
String command;
|
||||
|
||||
if ( file == NULL || *file == '\0' )
|
||||
strcpy(command,"NLST");
|
||||
else
|
||||
sprintf(command,"NLST %s",file);
|
||||
|
||||
return FtpCommand(con,command,"",120,150,200,EOF);
|
||||
}
|
97
lib/libftp/FtpPasv.c
Normal file
97
lib/libftp/FtpPasv.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the exist
|
||||
ing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
|
||||
char * FtpPasv (FTP *ftp)
|
||||
{
|
||||
char *msg;
|
||||
String PORT;
|
||||
char *p=PORT;
|
||||
|
||||
if FtpError(FtpCommand(ftp,"PASV","",227,EOF))
|
||||
return "";
|
||||
|
||||
msg = FtpMessage (227);
|
||||
|
||||
msg+=3;
|
||||
|
||||
while (!isdigit(*msg++));
|
||||
msg--;
|
||||
|
||||
while (isdigit(*msg)||*msg==',') *p++=*msg++;
|
||||
*p=0;
|
||||
|
||||
return PORT;
|
||||
}
|
||||
|
||||
|
||||
STATUS FtpLink(FTP *ftp1, FTP *ftp2)
|
||||
{
|
||||
|
||||
String PORT;
|
||||
|
||||
strcpy(PORT,FtpPasv(ftp1));
|
||||
|
||||
FtpCommand(ftp2,"PORT %s",PORT,200,EOF);
|
||||
}
|
||||
|
||||
STATUS FtpPassiveTransfer(FTP *ftp1, FTP *ftp2, char *f1, char *f2)
|
||||
{
|
||||
String tmp;
|
||||
fd_set fds;
|
||||
|
||||
FtpAssert(ftp1,FtpLink(ftp1,ftp2));
|
||||
|
||||
|
||||
if (!*f2) f2=f1;
|
||||
|
||||
FtpAssert(ftp2,FtpCommand(ftp2,"STOR %s",f2, 200, 120 , 150 , 125 , 250 , EOF ));
|
||||
FtpAssert(ftp1,FtpCommand(ftp1,"RETR %s",f1, 200, 120 , 150 , 125 , 250 , EOF ));
|
||||
|
||||
FD_ZERO(&fds);
|
||||
|
||||
FD_SET(fileno(FTPCMD(ftp1)),&fds);
|
||||
FD_SET(fileno(FTPCMD(ftp2)),&fds);
|
||||
|
||||
if (select(getdtablesize(),&fds,0,0,0)<0)
|
||||
{
|
||||
if (ftp1->error!=NULL)
|
||||
return (*(ftp1->error))(ftp1,QUIT,sys_errlist[errno]);
|
||||
if (ftp2->error!=NULL)
|
||||
return (*(ftp2->error))(ftp1,QUIT,sys_errlist[errno]);
|
||||
return QUIT;
|
||||
}
|
||||
|
||||
if (FD_ISSET(fileno(FTPCMD(ftp1)),&fds))
|
||||
{
|
||||
FtpGetMessage(ftp1,tmp);
|
||||
FtpLog(ftp1->title,tmp);
|
||||
FtpGetMessage(ftp2,tmp);
|
||||
FtpLog(ftp2->title,tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
FtpGetMessage(ftp2,tmp);
|
||||
FtpLog(ftp2->title,tmp);
|
||||
FtpGetMessage(ftp1,tmp);
|
||||
FtpLog(ftp1->title,tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
32
lib/libftp/FtpPort.c
Normal file
32
lib/libftp/FtpPort.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpPort(FTP *con,int a,int b,int c,int d,int e,int f)
|
||||
{
|
||||
String cmd;
|
||||
int i;
|
||||
|
||||
sprintf(cmd,"PORT %d,%d,%d,%d,%d,%d",a,b,c,d,e,f);
|
||||
if ( FtpSendMessage(con,cmd) == QUIT)
|
||||
return QUIT;
|
||||
if ( (i=FtpGetMessage(con,cmd)) == QUIT)
|
||||
return QUIT;
|
||||
|
||||
if ( ! FtpGood ( i , 200 , EOF ))
|
||||
return EXIT(con,-i);
|
||||
|
||||
return EXIT(con,i);
|
||||
}
|
33
lib/libftp/FtpPwd.c
Normal file
33
lib/libftp/FtpPwd.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
char * FtpPwd(FTP * con)
|
||||
{
|
||||
String tmp,tmp1;
|
||||
int i;
|
||||
|
||||
if ( FtpSendMessage(con,"PWD") == QUIT )
|
||||
return (char *) EXIT(con,QUIT);
|
||||
if ( (i=FtpGetMessage(con,tmp)) == QUIT )
|
||||
return (char *) EXIT(con,QUIT);
|
||||
|
||||
if ( i != 257 )
|
||||
return (char *) EXIT(con,-i);
|
||||
|
||||
sscanf(tmp,"%*[^\"]%*c%[^\"]%*s",tmp1);
|
||||
con -> errno = i;
|
||||
return tmp1;
|
||||
}
|
82
lib/libftp/FtpRetr.c
Normal file
82
lib/libftp/FtpRetr.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpRetr (FTP * con , char * command ,
|
||||
char *in , char * out)
|
||||
{
|
||||
FILE *o;
|
||||
int c;
|
||||
struct stat st;
|
||||
char buffer[FTPBUFSIZ],buffer2[FTPBUFSIZ];
|
||||
register int size;
|
||||
|
||||
FtpFilenameChecker(&in,&out);
|
||||
|
||||
if ( FtpTestFlag(con,FTP_REST) && stat(out,&st)==0)
|
||||
{
|
||||
con -> seek = st.st_size;
|
||||
if ((o=Ftpfopen(out,"a+"))==NULL)
|
||||
return EXIT(con,LQUIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
con -> seek = 0;
|
||||
if ((o=Ftpfopen(out,"w+"))==NULL)
|
||||
return EXIT(con,LQUIT);
|
||||
}
|
||||
|
||||
|
||||
if ( FtpError(FtpData(con,command,in,"r")))
|
||||
{
|
||||
|
||||
if (con->seek==0) return EXIT(con,con->errno);
|
||||
|
||||
con -> seek = 0;
|
||||
fclose(o);
|
||||
|
||||
if ( FtpError(FtpData(con,command,in,"r")) )
|
||||
{
|
||||
return EXIT(con,con->errno);
|
||||
}
|
||||
|
||||
if ((o=Ftpfopen(out,"w+"))==NULL)
|
||||
return EXIT(con,LQUIT);
|
||||
}
|
||||
|
||||
|
||||
fseek(o,con->seek,0);
|
||||
|
||||
while((size=FtpReadBlock(con,buffer,FTPBUFSIZ))>0)
|
||||
{
|
||||
if (write(fileno(o),buffer,size)!=size)
|
||||
return EXIT(con,LQUIT);
|
||||
}
|
||||
|
||||
Ftpfclose(o);
|
||||
return FtpClose(con);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
35
lib/libftp/FtpSize.c
Normal file
35
lib/libftp/FtpSize.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
int FtpSize(FTP * con, char *filename)
|
||||
{
|
||||
String tmp;
|
||||
int i,size;
|
||||
|
||||
strcpy(tmp,"SIZE ");
|
||||
strcat(tmp,filename);
|
||||
|
||||
if ( FtpSendMessage(con,tmp) == QUIT )
|
||||
return EXIT(con,QUIT);
|
||||
if ( (i=FtpGetMessage(con,tmp)) == QUIT )
|
||||
return EXIT(con,QUIT);
|
||||
|
||||
if ( i != 213 )
|
||||
return con -> errno = (-i);
|
||||
|
||||
sscanf(tmp,"%*d %d",&size);
|
||||
return size;
|
||||
}
|
57
lib/libftp/FtpStor.c
Normal file
57
lib/libftp/FtpStor.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpStor (FTP * con , char * command ,
|
||||
char *in , char * out)
|
||||
{
|
||||
FILE *i;
|
||||
char buffer[FTPBUFSIZ];
|
||||
int size;
|
||||
|
||||
con->seek=0;
|
||||
|
||||
if ( (i=Ftpfopen(in,"rb")) == NULL )
|
||||
return EXIT(con,LQUIT);
|
||||
|
||||
if ( FtpTestFlag(con,FTP_REST) &&
|
||||
(con->seek=FtpSize(con,out))<0 )
|
||||
con->seek=0;
|
||||
|
||||
|
||||
if ( FtpError(FtpData(con,command,out,"w")))
|
||||
{
|
||||
if (con->seek==0) return EXIT(con,con->errno);
|
||||
|
||||
con -> seek =0;
|
||||
if ( FtpError(FtpData(con,command,out,"w")) )
|
||||
return EXIT(con,con->errno);
|
||||
}
|
||||
|
||||
if (con->seek) fseek(i,con->seek,0);
|
||||
|
||||
while ( (size=read ( fileno(i) , buffer, FTPBUFSIZ ))>0)
|
||||
FtpWriteBlock(con,buffer,size);
|
||||
|
||||
Ftpfclose(i);
|
||||
return FtpClose(con);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
34
lib/libftp/FtpSyscalls.c
Normal file
34
lib/libftp/FtpSyscalls.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
#include <errno.h>
|
||||
|
||||
#define DEF(syscal,name) name(a,b,c,d,e,f,g,h) \
|
||||
{\
|
||||
register int status;\
|
||||
while (((status=syscal(a,b,c,d,e,f,g,h))==-1) && (errno==EINTR));\
|
||||
return status;\
|
||||
}
|
||||
|
||||
DEF(open,nointr_open)
|
||||
DEF(close,nointr_close)
|
||||
DEF(select,nointr_select)
|
||||
DEF(read,nointr_read)
|
||||
DEF(write,nointr_write)
|
||||
DEF(dup,nointr_dup)
|
||||
DEF(wait,nointr_wait)
|
||||
DEF(connect,nointr_connect)
|
||||
DEF(listen,nointr_listen)
|
||||
DEF(accept,nointr_accept)
|
26
lib/libftp/FtpType.c
Normal file
26
lib/libftp/FtpType.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "FtpLibrary.h"
|
||||
|
||||
STATUS FtpType(FTP *ftp, char type)
|
||||
{
|
||||
STATUS p;
|
||||
|
||||
if ((p=FtpCommand(ftp,"TYPE %c",type,200,EOF))>0)
|
||||
ftp->mode=(int)type;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
98
lib/libftp/Ftpfopen.c
Normal file
98
lib/libftp/Ftpfopen.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <FtpLibrary.h>
|
||||
|
||||
#define NFSD 256
|
||||
|
||||
static int fds_types[NFDS];
|
||||
static int init=0;
|
||||
|
||||
enum {T_EMPTY=0,T_FILE,T_STREAM,T_PIPE,T_FULL};
|
||||
|
||||
FILE *Ftpfopen(char *filename,char *mode)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (!init)
|
||||
{
|
||||
bzero(fds_types,NFDS*sizeof(fds_types[0]));
|
||||
init=1;
|
||||
}
|
||||
|
||||
if (!strcmp(filename,"*STDIN*") || (!strcmp(filename,"-") && (mode[0]=='r')) )
|
||||
{
|
||||
fds_types[fileno(stdin)]=T_STREAM;
|
||||
return stdin;
|
||||
}
|
||||
|
||||
if (!strcmp(filename,"*STDOUT*") || (!strcmp(filename,"-") && (mode[0]=='w')))
|
||||
{
|
||||
fds_types[fileno(stdout)]=T_STREAM;
|
||||
return stdout;
|
||||
}
|
||||
|
||||
if (strcmp(filename,"*STDERR*")==0)
|
||||
{
|
||||
fds_types[fileno(stderr)]=T_STREAM;
|
||||
return stderr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (*filename=='|')
|
||||
{
|
||||
fp=popen(filename+1,mode);
|
||||
if (fp==NULL) return fp;
|
||||
fds_types[fileno(fp)]=T_PIPE;
|
||||
return fp;
|
||||
}
|
||||
|
||||
fp=FtpFullOpen(filename,mode);
|
||||
if (fp==NULL) return fp;
|
||||
fds_types[fileno(fp)]=T_FILE;
|
||||
return fp;
|
||||
|
||||
}
|
||||
|
||||
int Ftpfclose(FILE *fp)
|
||||
{
|
||||
|
||||
if (!init)
|
||||
{
|
||||
bzero(fds_types,NFDS*sizeof(fds_types[0]));
|
||||
init=1;
|
||||
}
|
||||
|
||||
switch (fds_types[fileno(fp)])
|
||||
{
|
||||
|
||||
case T_FILE:
|
||||
|
||||
return FtpFullClose(fp);
|
||||
|
||||
case T_STREAM:
|
||||
|
||||
return fflush(fp);
|
||||
|
||||
case T_PIPE:
|
||||
|
||||
return pclose(fp);
|
||||
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
9
lib/libftp/Makefile
Normal file
9
lib/libftp/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
LIB= ftp
|
||||
CFLAGS+= -I${.CURDIR}
|
||||
|
||||
SRCS= FtpAbort.c FtpArchie.c FtpBye.c FtpClose.c FtpCommand.c FtpConnect.c \
|
||||
FtpCopy.c FtpData.c FtpDebug.c FtpFilenameChecker.c FtpFull.c \
|
||||
FtpMove.c FtpOpenDir.c FtpPasv.c FtpPort.c FtpPwd.c FtpRetr.c \
|
||||
FtpSize.c FtpStor.c FtpType.c Ftpfopen.c
|
||||
|
||||
.include <bsd.lib.mk>
|
2
lib/libftp/doc/Makefile
Normal file
2
lib/libftp/doc/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
all clean cleandist install:
|
||||
@echo -n
|
51
lib/libftp/doc/example.c
Normal file
51
lib/libftp/doc/example.c
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
/* Include standard libftp's header */
|
||||
|
||||
#include <FtpLibrary.h>
|
||||
|
||||
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
FILE *input,*output;
|
||||
int c;
|
||||
|
||||
|
||||
if (argc<3)
|
||||
exit(fprintf(stderr,"Usage: %s input-file output-file\n",argv[0]));
|
||||
|
||||
FtplibDebug(yes);
|
||||
|
||||
if ((input=Ftpfopen(argv[1],"r"))==NULL)
|
||||
{
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((output=Ftpfopen(argv[2],"w"))==NULL)
|
||||
{
|
||||
perror(argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while ( (c=getc(input)) != EOF && (putc(c,output)!=EOF) );
|
||||
|
||||
if (ferror(input))
|
||||
{
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ferror(output))
|
||||
{
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Ftpfclose(input);
|
||||
Ftpfclose(output);
|
||||
|
||||
exit(0);
|
||||
|
||||
}
|
59
lib/libftp/doc/example.tex
Normal file
59
lib/libftp/doc/example.tex
Normal file
@ -0,0 +1,59 @@
|
||||
%%
|
||||
%% Creator: ansic2latex (from <stdin>)
|
||||
%% Date: Tue Dec 27 16:14:26 1994
|
||||
%%
|
||||
\expandafter\ifx\csname indentation\endcsname\relax
|
||||
\newlength{\indentation}\fi
|
||||
\setlength{\indentation}{0.5em}
|
||||
\begin{flushleft}
|
||||
\mbox{}\\
|
||||
{\em /$\ast$\hspace*{1\indentation}Include\hspace*{1\indentation}standard\hspace*{1\indentation}libftp's\hspace*{1\indentation}header\hspace*{1\indentation}$\ast$/}\mbox{}\\
|
||||
\mbox{}\\
|
||||
{\tt\#include} $<${\tt FtpLibrary.h}$>$ \mbox{}\\
|
||||
\mbox{}\\
|
||||
\mbox{}\\
|
||||
main({\bf int\/} argc, {\bf char\/} $\ast$argv[])\mbox{}\\
|
||||
\{\mbox{}\\
|
||||
\mbox{}\\
|
||||
\hspace*{2\indentation}FILE $\ast$input,$\ast$output;\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf int\/} c;\mbox{}\\
|
||||
\hspace*{2\indentation}\mbox{}\\
|
||||
\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf if\/} (argc$<$3)\mbox{}\\
|
||||
\hspace*{4\indentation}exit(fprintf(stderr,{\tt "Usage: \%s input-file output-file$\backslash$n"},argv[0]));\mbox{}\\
|
||||
\mbox{}\\
|
||||
\hspace*{2\indentation}FtplibDebug(yes);\mbox{}\\
|
||||
\hspace*{2\indentation}\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf if\/} ((input=Ftpfopen(argv[1],{\tt "r"}))==NULL)\mbox{}\\
|
||||
\hspace*{4\indentation}\{\mbox{}\\
|
||||
\hspace*{6\indentation}perror(argv[1]);\mbox{}\\
|
||||
\hspace*{6\indentation}exit(1);\mbox{}\\
|
||||
\hspace*{4\indentation}\}\mbox{}\\
|
||||
\hspace*{2\indentation}\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf if\/} ((output=Ftpfopen(argv[2],{\tt "w"}))==NULL)\mbox{}\\
|
||||
\hspace*{4\indentation}\{\mbox{}\\
|
||||
\hspace*{6\indentation}perror(argv[2]);\mbox{}\\
|
||||
\hspace*{6\indentation}exit(1);\mbox{}\\
|
||||
\hspace*{4\indentation}\}\mbox{}\\
|
||||
\hspace*{2\indentation}\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf while\/} ( (c=getc(input)) $\neq$ EOF \&\& (putc(c,output)$\neq$EOF) );\mbox{}\\
|
||||
\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf if\/} (ferror(input))\mbox{}\\
|
||||
\hspace*{4\indentation}\{\mbox{}\\
|
||||
\hspace*{6\indentation}perror(argv[1]);\mbox{}\\
|
||||
\hspace*{6\indentation}exit(1);\mbox{}\\
|
||||
\hspace*{4\indentation}\}\mbox{}\\
|
||||
\hspace*{2\indentation}\mbox{}\\
|
||||
\hspace*{2\indentation}{\bf if\/} (ferror(output))\mbox{}\\
|
||||
\hspace*{4\indentation}\{\mbox{}\\
|
||||
\hspace*{6\indentation}perror(argv[1]);\mbox{}\\
|
||||
\hspace*{6\indentation}exit(1);\mbox{}\\
|
||||
\hspace*{4\indentation}\}\mbox{}\\
|
||||
\mbox{}\\
|
||||
\hspace*{2\indentation}Ftpfclose(input);\mbox{}\\
|
||||
\hspace*{2\indentation}Ftpfclose(output);\mbox{}\\
|
||||
\mbox{}\\
|
||||
\hspace*{2\indentation}exit(0);\mbox{}\\
|
||||
\hspace*{2\indentation}\mbox{}\\
|
||||
\}\mbox{}\\
|
||||
\end{flushleft}
|
571
lib/libftp/doc/libftp.tex
Normal file
571
lib/libftp/doc/libftp.tex
Normal file
@ -0,0 +1,571 @@
|
||||
\documentstyle[cxx,fancyheadings,twoside,epsf,indentfirst]{article}
|
||||
% Vertical sizes
|
||||
%\vsize=20cm
|
||||
%\voffset=-2.3cm
|
||||
%\topmargin=0cm
|
||||
%\headheight=0.9cm
|
||||
%\footskip=1cm
|
||||
%\footheight=0.9cm
|
||||
%\textheight=16cm
|
||||
%\headrulewidth 0.01cm
|
||||
%\footrulewidth 0.0cm
|
||||
% 0 sizes
|
||||
%\hsize=30cm
|
||||
%\hoffset=-4.3cm
|
||||
%\hoffset=-2.3cm
|
||||
%\textwidth=13cm
|
||||
% Modes
|
||||
% \special{landscape}
|
||||
\pagestyle{empty}
|
||||
\pagestyle{fancyplain}
|
||||
\newcommand{\tit}[1]{#1}
|
||||
\rhead[\fancyplain{}{\tit{\leftmark}}]{\fancyplain{}{\tit{\rightmark}}}
|
||||
\lhead[\fancyplain{}{\tit{\rightmark}}]{\fancyplain{}{\tit{\leftmark}}}
|
||||
\chead{\hfill}
|
||||
\lfoot[\fancyplain{}{\tit{\thepage}}]{\fancyplain{}{\hfill}}
|
||||
\rfoot[\fancyplain{}{\hfill}]{\fancyplain{}{\tit{\thepage}}}
|
||||
\cfoot{\hfill}
|
||||
\renewcommand{\sectionmark}[1]{\markboth{#1}{\ }}
|
||||
\renewcommand{\subsectionmark}[1]{\markright{\ }}
|
||||
\newcommand{\look}[1]{(Chapter~\ref{#1}, page~\pageref{#1})}
|
||||
\newcommand{\toindex}[1]{\underline{\bf#1}\index{#1}}
|
||||
\newcommand{\add}[1]{\symbol{64}}
|
||||
\newcommand{\ps}[1]{\symbol{37}s}
|
||||
\newcommand{\twcol}[4]{
|
||||
\noindent\parbox[t]{#1\textwidth}{#3} \hfill \parbox[t]{#2\textwidth}{#4\hfill}\\
|
||||
}
|
||||
\newcommand{\tc}[2]{\twcol{0.49}{0.49}{#1}{#2}}
|
||||
\newcommand{\tcc}[2]{\twcol{0.49}{0.49}{\toindex{#1}}{#2}}
|
||||
\newcommand{\ttt}[2]{\bigskip
|
||||
|
||||
{\bf#1}
|
||||
|
||||
#2}
|
||||
\newcommand{\ts}[1]{{\underline{\bf#1}}}
|
||||
\newcommand{\dl}[2]{\parbox[t]{0.4\textwidth}{#1\hfill}\hfill
|
||||
\parbox[t]{0.4\textwidth}{#2\hfill}}
|
||||
\makeindex
|
||||
\begin{document}
|
||||
\title{\bf\it{LIBFTP User's guide}}
|
||||
\author{Oleg Orel}
|
||||
\date{\today}
|
||||
\newpage
|
||||
\maketitle
|
||||
|
||||
\section*{License}
|
||||
|
||||
This library is designed for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
\section*{Introduction}
|
||||
|
||||
The basic orientation of this library is making user's programs which transport
|
||||
files via TCP/IP network. It contains set of functions,
|
||||
starting from primitive, such as opening FTP connection to the server,
|
||||
and finishing by high-level functions, such as functions which retrieve files
|
||||
via network, making and closing channels to the server. All functions have
|
||||
prototypes in common header file named \toindex{FtpLibrary.h},
|
||||
which must be
|
||||
available in standard headers directory
|
||||
\footnote{for example ``/usr/include''}.
|
||||
Those prototypes almost fully
|
||||
describe orientation and arguments of all functions,
|
||||
but common ideology and library components should be mentioned.
|
||||
|
||||
This library is a client and uses standard FTPD from the other side.
|
||||
|
||||
There are problems of errors processing in many operating systems including input/output errors.
|
||||
The mutual mechanism of value returning of all functions is used in this library.
|
||||
(EXIT macros, defined in file FtpLibrary.h). This mechanism allows,
|
||||
after the definition of the error processing functions, write programs,
|
||||
considering the conditions to be ideal.
|
||||
Data transfer functions have possibility to preset data stream
|
||||
expectation timeout.
|
||||
When the set time expires, previously set function will be called.
|
||||
|
||||
\section{Variables and definitions}
|
||||
|
||||
\subsection{Some definitions in libftp's header file (FtpLibrary.h)}
|
||||
|
||||
\ttt{\toindex{EXIT}}{Main macro for return value from library's functions with
|
||||
calling handlers if it's need}
|
||||
|
||||
\ttt{\toindex{MAX\_ANSWERS}}{Number of possible answers from FTPD for one request}
|
||||
|
||||
\ttt{\toindex{NFDS}}{Maximum numbers of one-time opened files in your system, if this
|
||||
value higher than need isn't important. }
|
||||
|
||||
\ttt{\toindex{FTPBUFSIZE}}{Size of block for transmit data via network. By default equivalence \toindex{BUSIZ}}
|
||||
|
||||
\ttt{\toindex{LQUIT}}{Error status of local functions. If you give this status from libftp's function you must use perror for expand diagnostic.}
|
||||
|
||||
\ttt{\toindex{QUIT}}{Error status of network operation. Use perror.}
|
||||
|
||||
\ttt{\toindex{Ctrl}(char)}{Return control character code}
|
||||
|
||||
\ttt{\toindex{FREE}(data)}{Full data by zero}
|
||||
|
||||
\ttt{\toindex{FtpError}(libftp's call)}{Special macro for diagnostic bad conditions}
|
||||
|
||||
\ttt{\toindex{FtpAssert}(libftp's call}{Special macro for automatically return from
|
||||
this function if status is bad}
|
||||
|
||||
\subsection{Libftp's file specification}
|
||||
|
||||
All files wich must be interprets as local interprets as libftp's files.
|
||||
Libftp responds to three types of files such
|
||||
as local file, ftp files and program
|
||||
pipes. All files can be described as next syntax:
|
||||
|
||||
\ttt{$\mid$string}{interprets string as shell command, which must be
|
||||
executed with appropriate input/output for file. It depends where
|
||||
this file is specified.}
|
||||
|
||||
\ttt{hostname:filename}{interprets as file, which must be taken
|
||||
using ftp protocol with anonymous access}
|
||||
|
||||
\ttt{user@hostname:filename\\
|
||||
user/pass@hostname:filename
|
||||
}{interprets as file accesses via ftp
|
||||
with password yourname@your\_host.your\_domain}
|
||||
|
||||
|
||||
\ttt{*STDIN*, *STDOUT*, *STDERR* or char '-'}{opened standard streams}
|
||||
|
||||
\ttt{anything else}{local file}
|
||||
|
||||
|
||||
|
||||
|
||||
\subsection{The FTP data structure}
|
||||
|
||||
\subsubsection{The members of FTP structure}
|
||||
|
||||
\tc{FILE *\toindex{sock}\footnote{You can use macro FTPCMD(ftp) for extract
|
||||
this members, using this macro for making your program more compatibility
|
||||
with next versions of this library}}
|
||||
{--- command channel to the server;}
|
||||
|
||||
\tc{FILE *\toindex{data}\footnote{You can use macro FTPDATA(ftp) for extract
|
||||
this members, using this macro for making your program more compatibility
|
||||
with next versions of this library}}
|
||||
{--- pointer to data structure, which describes data channel to the server;}
|
||||
|
||||
\tc{int \toindex{errno}}{ --- last returned value. When value is lower than 1, an error occurred;}
|
||||
|
||||
\tc{char \toindex{mode}}{--- type of transfer (valid values: 'A' 'I' ....);}
|
||||
|
||||
\tc{int \toindex{ch}}{--- help variable. Is used to convert ASCII files, user of library for cleaning your problems must forget about this member;}
|
||||
|
||||
\tc{STATUS (*\toindex{error})()}{--- pointer to an error handler. It is called
|
||||
when status from the server is bad;}
|
||||
\tc{STATUS (*\toindex{debug})()}{--- pointer to a debug handler. Is called from
|
||||
functions of sending/receiving messages to/from server;}
|
||||
|
||||
\tc{STATUS (*\toindex{IO})()}{--- pointer to Input/Output error handler. Is called when channel to server is broken.}
|
||||
|
||||
\tc{STATUS (*\toindex{hash})()}{--- pointer to function, which must compute
|
||||
summary traffic. This function can take one argument which describe
|
||||
how many bytes
|
||||
now received of sended to/from server. If the argument is equivalence
|
||||
to zero, then counter must be reset to zero. But of course user can use
|
||||
this handler for another properties of herself program, for example for
|
||||
perriodicaly called anything else for checking other conditions, because
|
||||
the transfer procedure can take large time from user's program.}
|
||||
|
||||
\tc{int \toindex{seek}}{--- the first byte in file for transfer. This option
|
||||
can use for retransfer file again after connection is broken}
|
||||
|
||||
\tc{int \toindex{flags}}{--- the option list for transfer procedures such as:
|
||||
\\
|
||||
\begin{itemize}
|
||||
\item[FTP\_REST] Turn on retransfer file using method of compare size of files
|
||||
in both sides.
|
||||
\item[FTP\_NOEXIT] Don't exit from standard error and IO handlers
|
||||
\end{itemize}}
|
||||
|
||||
\tc{struct timeval \toindex{timeout}}{--- Timeout for send/receive procedures}
|
||||
|
||||
\tc{int \toindex{port}}{--- Port for making command connection}
|
||||
|
||||
\tc{String \toindex{title}}{--- Connection identification}
|
||||
|
||||
\tc{unsigned long \toindex{counter}}{--- counter of already transferred bytes}
|
||||
|
||||
\subsubsection{Initialization of FTP structure}
|
||||
|
||||
This library have two special objects: procedure FtpCreateObject and external
|
||||
static structure FtpInit. The procedure FtpCreateObject called from
|
||||
FtpConnect. The structure FtpInit can be modified by hand or by using special
|
||||
macros such as \toindex{FtpSetFlag}, \toindex{FtpClearFlag}, \toindex{FtpSetPort}, \toindex{FtpSetTimeout}, \toindex{FtpSetErrorHandler}, \toindex{FtpSetDebugHandler}, \toindex{FtpSetIOHandler}, \\
|
||||
\toindex{FtpSetHashHandler}.
|
||||
|
||||
\subsection{The \toindex{ARCHIE} data structure}
|
||||
|
||||
The \ts{ARCHIE} data structure using only with function FtpArchie for extract
|
||||
result of works one. This structure have four members such as:
|
||||
|
||||
\tc{struct tm \toindex{createtime}}{Time of file creation.}
|
||||
|
||||
\tc{unsigned long \toindex{size}}{size of file.}
|
||||
|
||||
\tc{String \toindex{host}}{Host which file is located}
|
||||
|
||||
\tc{String \toindex{file}}{Full path in pointed host of this file}
|
||||
|
||||
|
||||
\section{Library's routines}
|
||||
|
||||
\subsection{Connection/Disconnection with server}
|
||||
|
||||
\ttt{STATUS \toindex{FtpConnect}(FTP~**, char~*hostname
|
||||
\footnote{The name of the host may be symbolic (for example \ts{dxcern.cern.ch}) or numeric (for example \ts{128.141.201.96})}
|
||||
)}
|
||||
{
|
||||
Makes channel to the server, at the ``hostname'' machine.
|
||||
Creates FTP data structure and returns pointer to it. If the procedure \toindex{FtplibDebug}(1)
|
||||
was previously called, \ts{FtpConnect} calls automatically \ts{FtpDebug} for the \ts{debug mode} to be turned on.
|
||||
\look{debug}.
|
||||
}
|
||||
\ttt{STATUS \toindex{FtpUser}(FTP~*, char~*user)}
|
||||
{
|
||||
Sends the name of the user to the server. The connection must be done before it.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpPassword}(FTP~*, char~*password)}
|
||||
{
|
||||
Sends \ts{password} to the server. The function \ts{FtpUser} must be called before it.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpAccount}(FTP~*, char~*account)}
|
||||
{
|
||||
Sends a name of the account to the server. The name of the account is not standard
|
||||
attribute for many systems, so this function is used very seldom.
|
||||
The function \ts{FtpPassword} must be called before it.
|
||||
}
|
||||
|
||||
\ttt{
|
||||
STATUS \toindex{FtpLogin}(FTP~**, char~*hostname, char~*user, char~*password, char~*account)}
|
||||
{
|
||||
Executes functions \ts{FtpConnect}, \ts{FtpUser}, \ts{FtpPassword},
|
||||
\ts{FtpAccount} (if necessary) consistently. If the name of the account is absent,
|
||||
replaces it with the \ts{NULL} value.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpBye}(FTP~*)}
|
||||
{ Finishes work with the server and closes all channels.
|
||||
\footnote{You can see from the description of connect/disconnect functions, that you can create
|
||||
more than one connection to servers simultaneously.}
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpQuickBye}(FTP~*)}
|
||||
{ Fast close data and command connection to server without delays for waiting
|
||||
server's confirmation and destroying the FTP object.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpAbort}(FTP~*)}
|
||||
{ Abort last command passed to server}
|
||||
|
||||
|
||||
\subsection{The debugging} \label{debug}
|
||||
|
||||
There is a possibility to predefine few functions,
|
||||
such as:~\footnote{If the \ts{NULL} value is transferred as a parameter \ts{``function''} to the functions, described below,
|
||||
the handling will be turned off.}
|
||||
|
||||
\ttt{\toindex{FtpSetDebugHandler}(FTP *,function)}
|
||||
{ Predefines function of protocol debugging.
|
||||
After the function is predefined, it is called with every
|
||||
sending/receiving messages from the server.
|
||||
The function, defined as a debug handler must do returns to the calling
|
||||
functions (\ts{FtpSendMessage}/\ts{FtpGetMessage}), but can also abort the program.
|
||||
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpSetErrorHandler}(FTP *,function)}
|
||||
{
|
||||
Predefines error handler. If the server's answer means, that the operation is not finished
|
||||
correctly, this function will be called.
|
||||
The result code is negative, if an error is occurs.
|
||||
}
|
||||
\ttt{\toindex{FtpSetIOHandler}(FTP *,function)}
|
||||
{
|
||||
Predefines handler of Input/Output processing. This function is called, when a connection to the
|
||||
server is broken. For example, when the network or the remote host is down. This handler also is
|
||||
called after the \toindex{timeout} of one character waiting expires.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpDebug}(FTP *)}
|
||||
{
|
||||
Turns on all standard debugging functions.
|
||||
|
||||
\tc{\toindex{FtpDebugError}}{--- prints a string, taken from the server, and aborts the program;}
|
||||
\tc{\toindex{FtpDebugDebug}}{--- prints a string, taken from the server;}
|
||||
\tc{\toindex{FtpDebugIO}}{--- prints string \ts{strerror(errno)} and aborts the program.}
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpSetHashHandler}(FTP *,function)}
|
||||
{
|
||||
Predefines handler of function which must compute traffic size. This
|
||||
function have only one argument which describe number of transferred bytes.
|
||||
If this argument is zero counter must be reset to zero.
|
||||
}
|
||||
|
||||
|
||||
All function for debugging have three arguments:\\
|
||||
1. Pointer to FTP data structure;\\
|
||||
2. Last returned value from the server. When errors occur, the value is less than 1;\\
|
||||
3. Diagnostic string.(char *)
|
||||
|
||||
\ttt{\toindex{FtplibDebug}(yes|no)}
|
||||
{ Turns on/off autostart debug mode, when connection is established.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpLog}(char *name\_of\_log, char *message)}
|
||||
{ Print message to user's screen in libftp's standard format,
|
||||
name\_of\_log must be your program name (if this function called
|
||||
from standard handlers then this string is title from FTP structure) and
|
||||
message with diagnostic string from anywhere.}
|
||||
|
||||
|
||||
\subsection{Data transfer procedures}
|
||||
|
||||
\ttt{STATUS \toindex{FtpRetr}(FTP~*, char~*command, char~*inp, char~*out)}
|
||||
{
|
||||
This is basically and single procedure in the library with transfer
|
||||
file from the server. One check many option with customizing its style
|
||||
of working. This options basically is members of FTP structure such
|
||||
as timeout, all handlers, mode, seek. If in continue of working this
|
||||
function happen timeout or network broked then this function
|
||||
automatically called I/O handler which can restart this function
|
||||
again or broken procedure. If handler is not set then FtpRetr return
|
||||
status QUIT or LQUIT as signal of type of error (LQUIT is specify
|
||||
error happen with local filesystem). \\
|
||||
{\bf Warring!} All receive function described bellow working by
|
||||
called this procedure and described rules is right for them.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpGet}(FTP~*, char~*in, char~*out)}
|
||||
{
|
||||
Calls \ts{FtpRetr} with adaptation arguments to transfer file
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpDirectory}(FTP~*, char~*pat\footnote{This is the first argument for \ts{``ls''} command}, char~*out)}
|
||||
{
|
||||
Transfers files listing from the server, described by \ts{pat}, to the local file \ts{out}.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpDir}(FTP~*, char~*out)}
|
||||
{
|
||||
Transfers files listing of the current directory from the server to the local file \ts{out}.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpStor}(FTP~*, char~*command, char~*inp, char*~out)}
|
||||
{
|
||||
Store file to the server. Works like FtpRetr.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpPut}(FTP~*, char~*in, char~*out)}
|
||||
{
|
||||
Calls \ts{FtpStor} adaptation arguments to transfer file
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpCopy}(FTP~*ftp\_from, FTP~*ftp\_to, char~*in, char~*out)}
|
||||
{
|
||||
Transfer file between two server without connection to client's host
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpPassiveTransfer}(FTP~*ftp\_from, FTP~*ftp\_to, char~*in, char~*out)}
|
||||
{
|
||||
Transfer file between two server via client's cache.
|
||||
}
|
||||
|
||||
\subsection{Server's files read/write procedures}
|
||||
|
||||
This library contains special functions for remote files reading and
|
||||
writing, without precopying them to local files. The functions,
|
||||
which are described below, do it. After the data channel
|
||||
to a remote file is created, it becomes possible to read and write
|
||||
characters using standard Input/Output functions
|
||||
or using special functions \ts{FtpRead}/\ts{FtpWrite} and/or
|
||||
\ts{FtpGetc}/\ts{FtpPutc}, which reorganize stream for standard text file,
|
||||
under condition that the \ts{ASCII} mode is set.
|
||||
\footnote{Of course, such functions as \ts{seek}, \ts{ioctl}, ....
|
||||
can not be used.}
|
||||
|
||||
\ttt{\toindex{FtpData}(FTP~*, char~*command, char~*param, char~*mode)}
|
||||
{ Makes data transfer channel, with presending command composed from \ts{command} and \ts{param}.
|
||||
The mode must be \ts{``r''} or \ts{``w''}}
|
||||
|
||||
\ttt{\toindex{FtpOpenRead}(FTP~*,char~*filename)}
|
||||
{ Opens file named \ts{filename} for reading on server}
|
||||
|
||||
\ttt{\toindex{FtpOpenWrite}(FTP~*,char~*filename)}
|
||||
{ Creats and opens file named \ts{filename} for writing on server}
|
||||
|
||||
\ttt{\toindex{FtpOpenAppend}(FTP~*,char~*filename)}
|
||||
{ Creats and opens file named \ts{filename} for appending on server}
|
||||
|
||||
\ttt{\toindex{FtpOpenDir}(FTP~*, char~*files)}
|
||||
{
|
||||
Creats channel for directory list reading, described by argument \ts{files}.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpRead}(FTP~*)}{
|
||||
Reads character from data stream. If \ts{ASCII} mode is set\footnote{By default} converts new line markers.
|
||||
When the end of file is detected or channel is broken, returns \toindex{EOF}}
|
||||
|
||||
\ttt{\toindex{FtpWrite}(FTP~*, char~c)}{
|
||||
Writes single character to stream, if \ts{ASCII} mode is set converts new line markers.
|
||||
When channel is broken, returns \toindex{EOF}}
|
||||
|
||||
\ttt{int \toindex{FtpGetc}(FTP~*,FILE~*fp)}{
|
||||
Reads character from data stream specified by fp. Using macros FTPDATA and FTPCMD you can specify stream need for reading. \footnote{Functions FtpGetc and FtpPutc ignories data stream mode, works as binary always}
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpPutc}(FTP~*,FILE~*fp, char c)}{
|
||||
Writes character to data stream specified by fp. Using macros FTPDATA and
|
||||
FTPCMD you can specify stream need for reading. \footnote{Functions
|
||||
FtpGetc and FtpPutc ignores data stream mode, works as binary always}
|
||||
}
|
||||
|
||||
|
||||
\ttt{\toindex{FtpClose}(FTP~*)}
|
||||
{Closes opened channel to server}
|
||||
|
||||
\subsection{Other commands for server}
|
||||
|
||||
\ttt{\toindex{FtpCommand}(FTP~*, char~*command, char~*param, int~ok1, ok2, ok3, ..., okN, EOF)}
|
||||
{ Sends a command, composed from \ts{command} and \ts{param} using \ts{sprintf} function.
|
||||
Reads an answer from the server.
|
||||
When return code from the server is not included to \ts{ok-list}(\ts{ok1},\ts{ok2}...) the sign of code
|
||||
will be inverted.}
|
||||
|
||||
|
||||
\ttt{\toindex{FtpType}(FTP~*,char~mode)}
|
||||
{Sets transfer mode, such as \ts{'A'},\ts{'I'},\ts{'S'},etc...}
|
||||
|
||||
\ttt{\toindex{FtpBinary}(FTP~*)}
|
||||
{Sets binary mode}
|
||||
|
||||
\ttt{\toindex{FtpAscii}(FTP~*)}
|
||||
{Sets \ts{ASCII} mode}
|
||||
|
||||
|
||||
\ttt{\toindex{FtpMkdir}(FTP~*,char *dirname)}
|
||||
{Makes directory on server}
|
||||
|
||||
\ttt{\toindex{FtpChdir}(FTP~*,char *dirname)}
|
||||
{Changes working directory on server}
|
||||
|
||||
\ttt{\toindex{FtpRm}(FTP~*,char *filename)}
|
||||
{Removes file on server}
|
||||
|
||||
\ttt{char~*\toindex{FtpPwd}(FTP~*)}
|
||||
{Returns the name of working directory on server}
|
||||
|
||||
\ttt{int \toindex{FtpSize}(FTP~*,char *filename)}
|
||||
{Returned size (in bytes) of description's file.}
|
||||
|
||||
\ttt{\toindex{FtpMove}(FTP~*,char *oldfilename, char *newfilename)}
|
||||
{Renames file from \ts{oldfilename} to \ts{newfilename}}
|
||||
|
||||
\ttt{\toindex{FtpPort}(FTP~*, int~a, int~b, int~c, int~d, int~e, int~f)
|
||||
\footnote{Recommended in non-trivial situations}
|
||||
}
|
||||
{ A command for the server for making a new data channel. \ts{a.b.c.d} is an IP address of a client(i.e. your IP address),
|
||||
\ts{e*256+f} is a port number}
|
||||
|
||||
|
||||
\ttt{struct hostent *\toindex{FtpGetHost}(char *hostname)
|
||||
\footnote{Extension of standard function ``gethostbyname''}
|
||||
}
|
||||
{Returned pointer to structure \ts{hostent} creating using string
|
||||
\ts{hostname}, which contains name of the computer or its IP
|
||||
address~\footnote{For example''dxunk8.oea.ihep.su'' or ``192.102.229.71''}
|
||||
}
|
||||
|
||||
|
||||
\subsection{Functions for sending/receiving control messages to/from server}
|
||||
|
||||
\ttt{\toindex{FtpSendMessage}(FTP~*, char~*message)}
|
||||
{Sends a message to the server}
|
||||
|
||||
\ttt{int \toindex{FtpGetMessage}(FTP~*)}
|
||||
{Receives a message from the server.}
|
||||
|
||||
\ttt{\toindex{FtpMessage}(int Number)}
|
||||
{Gets a message by code.}
|
||||
|
||||
\ttt{\toindex{FtpNumber}(char *Message)}
|
||||
{Extract message's number from string.}
|
||||
|
||||
\subsection{High-level functions}
|
||||
|
||||
\ttt{FILE *\toindex{FtpFullOpen}(char *filename,char *mode)}
|
||||
{
|
||||
Parses string \ts{filename}, which must contain a string in format or \\
|
||||
\ts{host/user/password:filename} or \ts{filename},
|
||||
what corresponds to remote or local file. The second argument is the type of opening, divided into two characters:
|
||||
first --- the mode of opening \ts{``r''}, \ts{``w''} or \ts{``a''}, second is the transfer type , if contains character \ts{``b''},
|
||||
then the mode is binary.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpFullSyntax}(String source,String host,String user,String password,String file)}
|
||||
{Make out string ``source'' for next four parameters.}
|
||||
|
||||
\ttt{FILE *\toindex{Ftpfopen}(char *file, char *mode)}
|
||||
{
|
||||
Open file specified in libftp's file specification. Works like
|
||||
\ts{fopen}. See description of libftp's file specification in the
|
||||
top of paper.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{Ftpfclose}(FILE *fp)}
|
||||
{
|
||||
Close file which opened using Ftpfopen. Works like fclose.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpArchie}(char *what, ARCHIE *result, int number)}{
|
||||
Find \ts{number} entrys in archie's database enrolls described by \ts{what}
|
||||
argument. \ts{result} must be pointer to array of ARCHIE's structures number
|
||||
of which must be equivalence or higher than \ts{number}. This call return
|
||||
number of entrys which found in database. If FtpArchie return value lower
|
||||
than zero then pointed target not found or archie isn't works}
|
||||
|
||||
|
||||
\section{Example of using libftp}
|
||||
|
||||
Next example demonstrate very simple using library calls only Ftpfopen
|
||||
and Ftpfclose functions which discriminate libftp's file specification:
|
||||
|
||||
\input example
|
||||
|
||||
For tests works this program you can try run one as:
|
||||
|
||||
\bigskip
|
||||
|
||||
\% example username/password@hostname:filename myfile.out
|
||||
|
||||
\% example myfile.input username/password@hostname:filename.out
|
||||
|
||||
|
||||
\newpage
|
||||
\input libftp.ind
|
||||
\newpage
|
||||
\tableofcontents
|
||||
\end{document}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
521
lib/libftp/doc/rus.tex
Normal file
521
lib/libftp/doc/rus.tex
Normal file
@ -0,0 +1,521 @@
|
||||
\documentstyle[russian,fancyheadings,twoside,epsf,indentfirst]{article}
|
||||
% Vertical sizes
|
||||
%\vsize=20cm
|
||||
%\voffset=-2.3cm
|
||||
%\topmargin=0cm
|
||||
%\headheight=0.9cm
|
||||
%\footskip=1cm
|
||||
%\footheight=0.9cm
|
||||
%\textheight=16cm
|
||||
%\headrulewidth 0.01cm
|
||||
%\footrulewidth 0.0cm
|
||||
% horisontal sizes
|
||||
%\hsize=30cm
|
||||
%\hoffset=-4.3cm
|
||||
%\hoffset=-2.3cm
|
||||
%\textwidth=13cm
|
||||
% Modes
|
||||
% \special{landscape}
|
||||
\pagestyle{empty}
|
||||
\pagestyle{fancyplain}
|
||||
\newcommand{\tit}[1]{#1}
|
||||
\rhead[\fancyplain{}{\tit{\leftmark}}]{\fancyplain{}{\tit{\rightmark}}}
|
||||
\lhead[\fancyplain{}{\tit{\rightmark}}]{\fancyplain{}{\tit{\leftmark}}}
|
||||
\chead{\hfill}
|
||||
\lfoot[\fancyplain{}{\tit{\thepage}}]{\fancyplain{}{\hfill}}
|
||||
\rfoot[\fancyplain{}{\hfill}]{\fancyplain{}{\tit{\thepage}}}
|
||||
\cfoot{\hfill}
|
||||
\renewcommand{\sectionmark}[1]{\markboth{#1}{\ }}
|
||||
\renewcommand{\subsectionmark}[1]{\markright{\ }}
|
||||
\newcommand{\look}[1]{(Глава~\ref{#1}, стр.~\pageref{#1})}
|
||||
\newcommand{\toindex}[1]{\underline{\bf#1}\index{#1}}
|
||||
\newcommand{\add}[1]{\symbol{64}}
|
||||
\newcommand{\ps}[1]{\symbol{37}s}
|
||||
\newcommand{\twcol}[4]{
|
||||
\noindent\parbox[t]{#1\textwidth}{#3} \hfill \parbox[t]{#2\textwidth}{#4\hfill}\\
|
||||
}
|
||||
\newcommand{\tc}[2]{\twcol{0.49}{0.49}{#1}{#2}}
|
||||
\newcommand{\tcc}[2]{\twcol{0.49}{0.49}{\toindex{#1}}{#2}}
|
||||
\newcommand{\ttt}[2]{\bigskip
|
||||
|
||||
{\bf#1}
|
||||
|
||||
#2}
|
||||
\newcommand{\ts}[1]{{\bf#1}}
|
||||
\newcommand{\dl}[2]{\parbox[t]{0.4\textwidth}{#1\hfill}\hfill
|
||||
\parbox[t]{0.4\textwidth}{#2\hfill}}
|
||||
\makeindex
|
||||
\begin{document}
|
||||
\title{\bf\it РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ БИБЛИОТЕКИ "LIBFTP"}
|
||||
\author{Олег Орел}
|
||||
\date{\today}
|
||||
\newpage
|
||||
\maketitle
|
||||
|
||||
\section*{Лицензия}
|
||||
|
||||
Продукт предназначен для написания свободного некоммерческого программного
|
||||
обеспечения. Он может исправляться и дописываться.
|
||||
Автор будет благодарен за получение советов, новых компонент и правок
|
||||
существующих подпрограмм.
|
||||
|
||||
Коммерческое использование этой библиотеки возможно с привлечением
|
||||
е\"е автора.
|
||||
|
||||
\section*{Причины создания и история развития}
|
||||
|
||||
Для людей, которые хотя бы один раз писали программу с использованием
|
||||
системных вызовов типа socket, connect, bind.... не секрет, что почти всегда
|
||||
последовательность вызовов функций для создания соединения по протоколу TCP одна и та же. Отсюда возникает резонный
|
||||
вопрос ``А почему собственно не иметь библиотеки более высокого
|
||||
уровня, для упрощения процесса программирования?''.
|
||||
Это послужило причиной создания \ts{libftp}.
|
||||
|
||||
После реализации ``нижней'' части библиотеки, были созданы
|
||||
функции более высокого уровня, такие как
|
||||
передача целого файла или чтение списка файлов. При написании
|
||||
этих процедур возникла необходимость удобной отладки сбойных случаев,
|
||||
для освобождения программы от бесконечного числа условий
|
||||
(обработка возвращаемого
|
||||
библиотечными функциями статуса).
|
||||
Для этого был создан макрос \ts{EXIT}, который при возврате функциями статуса,
|
||||
проверяет его, и в случае необходимости вызывает заранее установленные
|
||||
функции.
|
||||
|
||||
При передачи файлов по сети, которая в основном состоит из dialup-slip'ов
|
||||
(типичная ситуация для exUSSR)
|
||||
часто возникают ситуации ``поломки сети'' и файл большого размера передать
|
||||
становится практически невозможно\footnote{Конечно можно периодически
|
||||
запускать ftp, и говорить в нем ``reget filename''}, это послужило причиной
|
||||
написания программы \toindex{ftptry}\footnote{Программа \ts{ftptry} будет описана ниже} с использованием библиотеки libftp.
|
||||
Для е\"е реализации в библиотеку были добавлены функции
|
||||
\toindex{FtpRestorTimeout} и \toindex{FtpReretrTimeout},
|
||||
которые в отличии от функций \ts{FtpStorTimeout} и \ts{FtpRetrTimeout}
|
||||
не передают а докачивают файлы.
|
||||
|
||||
\section*{Недостатки - для исправления в следующих версиях}
|
||||
|
||||
\begin{itemize}
|
||||
|
||||
\item В процедурах чтения потока из socket'ов используется механизмы
|
||||
setjmp-longjmp, alarm+SIGALRM, SIGIO, которые будут заменены на select.
|
||||
Этот недостаток (использование SIGALRM) проявляется при работе с X11
|
||||
\footnote{там тоже используется alarm}
|
||||
|
||||
\item Переменная FtpDataStart\footnote{С какого байта передавать файлы} не принадлежит структуре FTP, а является обшей для всех.
|
||||
|
||||
\item Отсутствие работы с \toindex{site-specific} ftpd командами
|
||||
\end{itemize}
|
||||
|
||||
\section*{Идеи для дальнейших реализации}
|
||||
|
||||
\begin{itemize}
|
||||
|
||||
\item Разработка программы дублирования дерева
|
||||
директорий одной машины на другую. \footnote{Разработка идет в данный момент}
|
||||
|
||||
\item Разработка интерфейса в окружении X-window's для манипуляции
|
||||
файлами находящихся на разных машинах с возможностью неинтерактивной передачи
|
||||
(для медленных сетей)
|
||||
|
||||
\item Создание мультиплексирующего аппарата для одновременной
|
||||
обработки нескольких потоков данных.
|
||||
|
||||
\item Создание объекта FTP для C++
|
||||
|
||||
\end{itemize}
|
||||
|
||||
\section*{Введение}
|
||||
|
||||
Библиотека ``libftp'' предназначена для написания прикладных программ в которых
|
||||
существует необходимость передавать файлы по сети TCP/IP. Oна
|
||||
является набором функций начиная от примитивных функций, таких как открытие соединения по протоколу FTP на удаленную машину, до функций высокого уровня, которые передают
|
||||
файлы сами производя соединение/разъединение с сервером.
|
||||
Все функции имеют прототипы в файле \toindex{FtpLibrary.h},
|
||||
который должен быть помещен
|
||||
в каталог стандартных заголовков\footnote{Например /usr/include}.
|
||||
Эти прототипы практически полностью описывают
|
||||
назначение функций и их аргументы, но тем не менее необходимо сказать об общей идеологии
|
||||
построения библиотеки и ее компонент.
|
||||
|
||||
Вся библиотека, являясь клиентом, использует
|
||||
с противоположной стороны соединения стандартный \toindex{FTPD}
|
||||
\footnote{Для работы функций FtpRertrTimeout, FtpRestorTimeout необходимо
|
||||
чтобы сервер отрабатывал команду REST}.
|
||||
|
||||
Во многих операционных системах существует проблема обработки
|
||||
разного рода ошибок, в том числе ошибок
|
||||
ввода/вывода, в данном инструментарии использован единый механизм возврата
|
||||
результата работы любой функции (макрокоманда \ts{EXIT}, определенная в \ts{FtpLibrary.h})
|
||||
который позволяет
|
||||
предварительно установив свои или стандартные функции обработки
|
||||
ошибок и функции
|
||||
отладки, писать смысловую часть программы, думая только о ее методе работы
|
||||
в идеальных условиях. В функциях передачи данных в обе стороны существует
|
||||
возможность установить максимальное время ожидания потока данных, по истечении которого, возможно вызвать определенную процедуру.
|
||||
|
||||
|
||||
При работе с библиотекой, первой всегда вызывается процедура
|
||||
соединения с сервером\footnote{За исключением FtplibDebug} (\ts{FtpLogin} или \ts{FtpConnect})
|
||||
которая возвращает указатель на вновь созданную структуру данных (типа \ts{FTP})
|
||||
о соединении с сервером.
|
||||
|
||||
|
||||
|
||||
|
||||
\section{Структура данных FTP}
|
||||
|
||||
|
||||
\tc{int \toindex{sock}}{--- дескриптор канала передачи команд на сервер;}
|
||||
\tc{FILE *\toindex{data}}{--- описание канала для передачи данных на сервер;}
|
||||
\tc{int \toindex{errno}}{ --- значение последнего возвращенного библиотекой значения.
|
||||
В случае если оно отрицательно или равно нулю,
|
||||
то произошла ошибка;}
|
||||
\tc{char \toindex{mode}}{--- тип передачи данных;}
|
||||
\tc{int ch}{--- вспомогательная переменная используемая для преобразования
|
||||
потока в режиме передачи текстовых файлов;}
|
||||
\tc{STATUS (*func)()}{--- адрес функции, которая вызывается в случае когда от сервера
|
||||
получен ответ об ошибке;}
|
||||
\tc{STATUS (*debug)()}{--- адрес функции, которая вызывается для отладки протокола;}
|
||||
\tc{STATUS (*IO)()}{--- функция вызываемая в случае потери связи с сервером, или
|
||||
по истечению максимального времени на прием/передачу одного
|
||||
символа.}
|
||||
|
||||
|
||||
\section{ Процедуры соединения/разъединения с сервером}
|
||||
|
||||
\ttt{STATUS \toindex{FtpConnect}(FTP~**, char~*hostname
|
||||
\footnote{Имя машины может быть как символьное так и цифровое, например
|
||||
\ts{dxcern.cern.ch} или \ts{128.141.201.96}}
|
||||
)}
|
||||
{
|
||||
Создает канал соединения с сервером, находящимся на машине hostname,
|
||||
и создает структуру FTP, возвращая на нее указатель. Если предварительно
|
||||
была выполнена процедура \toindex{FtplibDebug}(1),
|
||||
то до соединения с сервером включает стандартные
|
||||
подпрограммы обработки ошибок \toindex{FtpDebugDebug}, \toindex{FtpDebugError},
|
||||
\toindex{FtpDebugIO} \look{debug}.
|
||||
}
|
||||
\ttt{STATUS \toindex{FtpUser}(FTP~*, char~*user)}
|
||||
{
|
||||
Посылает серверу имя пользователя. Ранее должно было быть произведено соединение
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpPassword}(FTP~*, char~*password)}
|
||||
{
|
||||
Посылает серверу пароль. Ранее должна была быть выполнена процедура \ts{FtpUser}
|
||||
}\ttt{STATUS \toindex{FtpAccount}(FTP~*, char~*acct)}
|
||||
{
|
||||
Посылает серверу имя account'a Эта функция сделана для полного соответствия
|
||||
библиотеки протоколу \ts{FTP}, но т.к. мало таких операционных систем в которых необходим этот
|
||||
атрибут пользователя то функция \ts{FtpAccount} в общем то не нужна.
|
||||
Предварительно должна была быть выполнена процедура
|
||||
\ts{FtpUser}.
|
||||
}
|
||||
|
||||
\ttt{
|
||||
STATUS \toindex{FtpLogin}(FTP~**, char~*hostname, char~*user, char~*password, char~*account)}
|
||||
{
|
||||
Последовательно выполняет процедуры \ts{FtpConnect}, \ts{FtpUser}, \ts{FtpPassword}, \ts{FtpAccount}
|
||||
(если параметр account равен NULL, то процедура FtpAccount не вызывается)}
|
||||
|
||||
\ttt{STATUS \toindex{FtpBye}(FTP~*)}
|
||||
{ Завершает сеанс работы с сервером \footnote{Как видно из описания процедур соединения/разъединения из одной программы можно одновременно соединятся с несколькими серверами} }
|
||||
|
||||
|
||||
|
||||
|
||||
\section{Процедуры отладки программы} \label{debug}
|
||||
|
||||
Существует возможность предварительно определить три
|
||||
процедуры:~\footnote{Если в любую из функций, описанных ниже, вместо параметра function передать значение \ts{NULL}, то это будет означать
|
||||
отключение отладки. При отключенной отладке результат работы можно
|
||||
определить или же по возвращаемому функцией значению (Если она типа \toindex{STATUS}) или
|
||||
по переменной errno в структуре \ts{FTP}}
|
||||
|
||||
\ttt{\toindex{FtpSetDebugHandler}(FTP *,function)}
|
||||
{ Устанавливает процедуру отладки протокола с удаленным сервером.
|
||||
Если ее определить, то она всегда будет вызывается из стандартной функции
|
||||
приема/передачи сообщения с/на сервера. Должна делать возврат, но в принципе
|
||||
имеет полное право прерывать выполнение программы в случае необходимости.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpSetErrorHandler}(FTP *,function)}
|
||||
{
|
||||
Определяет функцию обработки ошибок.
|
||||
После ее определения, в случае возвращения сервером
|
||||
неудовлетворительного ответа, будет вызываться указанная функция.
|
||||
При этом знак у кода ошибки меняется на '-', и т.о. результат
|
||||
становится меньше нуля.
|
||||
}
|
||||
\ttt{\toindex{FtpSetIOHandler}(FTP *,function)}
|
||||
{
|
||||
Определение функции обработки ошибок ввода/вывода.
|
||||
При передаче данных или команд на сервер, может возникнуть ситуация когда
|
||||
связь с сервером будет потеряна (сюда входят практически все сбои сети
|
||||
и сбои при работе сервера на удаленной машине) при этом будет вызвана
|
||||
указанная функция. Она вызывается так же по истечению
|
||||
максимального времени при ожидании очередного символа с сервера во время
|
||||
передачи данных. (\toindex{timeout})
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpDebug}(FTP *)}
|
||||
{
|
||||
Подключение стандартных функций отладки протокола таких как
|
||||
\tc{\toindex{FtpDebugError}}{--- печатает строку возвращенную сервером и прерывает программу;}
|
||||
\tc{\toindex{FtpDebugDebug}}{--- печатает строку возвращенную сервером;}
|
||||
\tc{\toindex{FtpDebugIO}}{--- печатает строку \ts{strerror(errno)} и прерывает программу.}
|
||||
}
|
||||
|
||||
Во все процедуры передаются три аргумента:\\
|
||||
1. Структура \ts{FTP};\\
|
||||
2. Значение возвращенное функцией, если оно меньше единицы то произошла ошибка;\\
|
||||
3. Символьное сообщение об ошибке (char *).
|
||||
|
||||
\ttt{\toindex{FtplibDebug}(\ts{on} or \ts{off})}
|
||||
{ Включает/выключает автоматическое включение всех видов отладки при
|
||||
выполнении функции \ts{FtpConnect(FtpLogin)}}
|
||||
\section{Процедуры передачи данных с сервера}
|
||||
|
||||
\ttt{STATUS \toindex{FtpRetrTimeout}(FTP~*, char~*command, char~*inp, char~*out
|
||||
\footnote{Если имя локального файла \ts{out} совпадет со строками \ts{*STDIN*}, \ts{*STDOUT*}, \ts{*STDERR*} то
|
||||
вместо открытия нового файла произойдет дублирование потока соответственно с каналами
|
||||
\ts{stdin}, \ts{stdout}, \ts{stderr} (Обработку данной спецификации файлов
|
||||
производит функция \toindex{Ftpfopen}, которая при необходимости может быть вызвана самостоятельно, с такими же аргументами, как системная функция fopen)},
|
||||
long~time)}
|
||||
{
|
||||
Посылает команду \ts{command} на сервер, причем если в команде
|
||||
встретится подстрока \ps, то на ее место будет подставлена строка \ts{inp}.
|
||||
Создает канал для передачи данных, и то что будет передано
|
||||
сервером в этот канал будет скопировано в локальный файл \ts{out}.
|
||||
Если в течении времени \ts{time}(в секундах)
|
||||
с сервера не придет не одного символа, то
|
||||
функция возвратит статус который будет означать ошибку ввода/вывода.
|
||||
В случае когда \toindex{timeout}=0,
|
||||
максимальное время ожидания на уровне библиотеки равно
|
||||
бесконечности, в этом случае ошибка ввода/вывода может возникнуть
|
||||
по истечению timeout'a в ядре TCP/IP (или системы). Таким образом, если \ts{timeout} в
|
||||
параметре time больше чем timeout в ядре TCP/IP, он никогда
|
||||
не прервет передачу данных. \footnote{\ts{Timeout} в ядрах разных TCP/IP(системах) разный}
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpReretrTimeout}(FTP~*, char~*command, char~*inp, char~*out, long~time)}
|
||||
{
|
||||
Производит тo же сaмое действие что и функция \ts{FtpRetrTimeout}, за
|
||||
исключение того, что перед передачей проверяется файл \ts{out}, и в случае
|
||||
его существования передача с сервера начинается с байта с номером \ts{<размер файла out>}+1.}
|
||||
\ttt{\toindex{FtpRetr}(FTP~*, char~*command, char~*inp, char~*out)}
|
||||
{
|
||||
Вызывает то же действие что и FtpRetrTimeout, но с выключенным timeout'ом.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpGetTimeout}(FTP~*, char~*inp, char~*out, long~time)}
|
||||
{
|
||||
Передает с сервера файл \ts{inp} в локальный файл \ts{out}, при этом устанавливается
|
||||
\ts{timeout=time}.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpGet}(FTP~*, char~*in, char~*out)}
|
||||
{
|
||||
Вызывает функцию \ts{FtpGetTimeout} с выключенным максимальным временем
|
||||
ожидания данных}
|
||||
|
||||
\ttt{\toindex{FtpDirectory}(FTP~*, char~*pat\footnote{Это первый аргумент для команды ls(dir)}, char~*out)}
|
||||
{
|
||||
Передает содержимое директории, описанного параметром \ts{pat}, с сервера в файл \ts{out}.
|
||||
}
|
||||
\ttt{\toindex{FtpDir}(FTP~*, char~*out)}
|
||||
{
|
||||
Передает содержимое текущей директории с сервера в файл \ts{out}.
|
||||
}
|
||||
|
||||
\section{Процедуры передачи данных на сервер}
|
||||
|
||||
\ttt{\toindex{FtpStorTimeout}(FTP~*, char~*command, char~*inp, char~*out, long~time)}
|
||||
{
|
||||
Передает содержимое локального файла \ts{inp} на сервер, предварительно послав
|
||||
ему команду, составленную из \ts{command} и \ts{out}. Параметр \ts{time}, задает максимальное
|
||||
время на отправку одного символа.
|
||||
}
|
||||
|
||||
\ttt{STATUS \toindex{FtpRestorTimeout}(FTP~*, char~*command, char~*inp, char~*out, long~time)}
|
||||
{
|
||||
Производит тo же сaмое действие что и функция \ts{FtpStorTimeout}, за
|
||||
исключение того, что перед передачей проверяется файл \ts{out} на сервере,
|
||||
и, в случае его существования, передача на сервер начинается с байта с номером \ts{<размер файла out>}+1.}
|
||||
|
||||
\ttt{\toindex{FtpStor}(FTP~*, char~*command, char~*inp, char*~out)}
|
||||
{
|
||||
Вызывает запуск процедуры \ts{FtpStorTimeout} с параметром \ts{time=0}.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpPutTimeout}(FTP~*, char~*in, char~*out, long~time)}
|
||||
{ Передает локальный файл \ts{in} на сервер в файл с именем \ts{out}, при этом \ts{timeout=time}}
|
||||
|
||||
\ttt{\toindex{FtpPut}(FTP~*, char~*in, char~*out)}
|
||||
{
|
||||
Вызывает процедуру \ts{FtpPutTimeout} с параметром \ts{time=0}}
|
||||
|
||||
|
||||
\section{Процедуры чтения/записи в файл на сервере}
|
||||
|
||||
Для того, чтобы производить ввод/вывод из/в файлы которые находятся на сервере,
|
||||
причем не копируя их предварительно в локальный файл, а работая непосредственно с оригиналом,
|
||||
существует возможность открыть файл на сервере на чтение/запись/дозапись и
|
||||
затем с помощью обычных процедур ввода/вывода или же при помощи процедур
|
||||
\ts{FtpRead} и \ts{FtpWrite}, которые в отличии от первых преобразуют текстовые файлы,
|
||||
производить необходимые операции.
|
||||
\footnote{Естественно, такие функции как \ts{seek}, \ts{ioctl}, ...
|
||||
для этих файлов недопустимы.}
|
||||
|
||||
|
||||
\ttt{\toindex{FtpData}(FTP~*, char~*command, char~*param, char~*mode)}
|
||||
{ Создает канал для передачи данных предварительно послав серверу команду которая
|
||||
составляется из параметров \ts{command} и \ts{param}. Параметр \ts{mode} указывает может быть
|
||||
или ``r'' или ``w''}
|
||||
|
||||
\ttt{\toindex{FtpOpenRead}(FTP~*,char~*filename)}
|
||||
{ Открывает для чтения файл с именем \ts{filename} на сервере }
|
||||
|
||||
\ttt{\toindex{FtpOpenWrite}(FTP~*,char~*filename)}
|
||||
{ Открывает для записи файл с именем \ts{filename} на сервере }
|
||||
|
||||
\ttt{\toindex{FtpOpenAppend}(FTP~*,char~*filename)}
|
||||
{ Открывает для дозаписи файл с именем \ts{filename} на сервере }
|
||||
|
||||
\ttt{\toindex{FtpOpenDir}(FTP~*, char~*files)}
|
||||
{
|
||||
Создает канал для чтения удаленного листинга директории, параметр files передается
|
||||
команде \ts{ls} на сервере в качестве 1-го параметра
|
||||
}
|
||||
|
||||
\ttt{int \toindex{FtpRead}(FTP~*)}{Читает символ из потока данных, если была установлена
|
||||
текстовая мода передачи \footnote{Установлена по умолчанию.}, преобразует переходы на новую строку. При обнаружении
|
||||
конца потока возвращает \toindex{EOF}}
|
||||
|
||||
\ttt{\toindex{FtpGetString}(FTP~*, char~*str)}
|
||||
{ Чтение одной строки из потока данных при помощи функции \ts{FtpRead}.}
|
||||
|
||||
\ttt{\toindex{FtpWrite}(FTP~*, char~c)}{Пишет символ в поток данных, если была установлена
|
||||
текстовая мода передачи, преобразует переходы на новую строку. При обнаружении
|
||||
ошибки ввода/вывода возвращает \toindex{EOF}}
|
||||
|
||||
\ttt{\toindex{FtpClose}(FTP~*)}
|
||||
{Закрывает ранее открытый поток данных.}
|
||||
|
||||
\section{Команды для сервера и вспомогательные функции}
|
||||
|
||||
\ttt{\toindex{FtpCommand}(FTP~*, char~*command, char~*param, int~ok1, ok2, ok3, ..., okN, EOF)}
|
||||
{ Посылает команду, составленную из параметров \ts{command} и \ts{param}, и считывает
|
||||
ответ сервера, если код ответа не совпадает не с одним значением \ts{ok}, то
|
||||
знак кода ответа меняется на '-'. В случае если установлен handler обработки
|
||||
ошибок вызывает его.
|
||||
}
|
||||
|
||||
\ttt{\toindex{FtpType}(FTP~*,char~*mode)}
|
||||
{Устанавливает моду передачи файлов, mode может быть ``A'', ``I'', ``S'',....}
|
||||
|
||||
\ttt{\toindex{FtpBinary}(FTP~*)}
|
||||
{Устанавливает двоичную моду передачи файлов}
|
||||
|
||||
\ttt{\toindex{FtpAscii}(FTP~*)}
|
||||
{Устанавливает текстовую моду передачи файлов}
|
||||
|
||||
|
||||
\ttt{\toindex{FtpMkdir}(FTP~*,char *dirname)}
|
||||
{Создает директорию на сервере}
|
||||
|
||||
\ttt{\toindex{FtpChdir}(FTP~*,char *dirname)}
|
||||
{Меняет активную директорию на сервере}
|
||||
|
||||
\ttt{\toindex{FtpRm}(FTP~*,char *filename)}
|
||||
{Удаляет файл на сервере}
|
||||
|
||||
\ttt{char~*\toindex{FtpPwd}(FTP~*)}
|
||||
{Возвращает активную директорию на сервере}
|
||||
|
||||
\ttt{int \toindex{FtpSize}(FTP~*,char *filename)}
|
||||
{Возвращает размер файла в байтах, если файл с указанным именем отсутствует,
|
||||
то возвращается статус ошибки, т.е. значение меньше нуля}
|
||||
|
||||
\ttt{\toindex{FtpMove}(FTP~*,char *oldfilename, char *newfilename)}
|
||||
{Переименовывает на сервере файл \ts{oldfilename} в файл \ts{newfilename}}
|
||||
|
||||
\ttt{\toindex{FtpPort}(FTP~*, int~a, int~b, int~c, int~d, int~e, int~f)}
|
||||
{Команда серверу создать канал для передачи данных. Причем \ts{a.b.c.d} это IP адрес
|
||||
клиента а \ts{e*256+f} номер порта.}
|
||||
|
||||
\ttt{struct hostent *\toindex{FtpGetHost}(char *hostname)}
|
||||
{Возвращает указатель на структуру типа hostent.
|
||||
Аргумент -- это строка содержащая или имя машины,
|
||||
или ее IP адрес в строчном виде\footnote{Например: ``dxunk8.oea.ihep.su'' или
|
||||
``192.102.229.71''}.}
|
||||
|
||||
\section{Подпрограммы передачи сообщений в/из сервера}
|
||||
|
||||
\ttt{\toindex{FtpSendMessage}(FTP~*, char~*message)}
|
||||
{Посылает сообщение серверу}
|
||||
|
||||
\ttt{int \toindex{FtpGetMessage}(FTP~*)}
|
||||
{Принимает сообщение от сервера и возвращает его код}
|
||||
|
||||
\ttt{\toindex{FtpMessage}(int Number)}
|
||||
{Возвращает по коду сообщения его содержимое}
|
||||
|
||||
\section{Функции полного сеанса работы}
|
||||
|
||||
\ttt{FILE *\toindex{FtpFullOpen}(char *filename,char *mode)}
|
||||
{ Разбирает строку filename, которая должна быть типа
|
||||
\\ \ts{host/user/password:filename} или же типа \ts{filename}, в зависимости от этого
|
||||
открывается файл или на сервере \ts{host} или локальный файл. Параметр mode должен
|
||||
содержать один или два символа. Первый задает тип открытия файла ``r'',``w'' или
|
||||
``a''. Второй символ может содержать символ ``b'' что будет задавать двоичную моду передачи}
|
||||
\ttt{\toindex{FtpFullClose}(FILE *f)}
|
||||
{Закрытие файла}
|
||||
|
||||
|
||||
\section{Описание примеров и прикладных программ}
|
||||
|
||||
\subsection{Программа get}\index{get}
|
||||
|
||||
Копирование файла с сервера в локальный файл с таким же именем с использованием функций полного сеанса.
|
||||
|
||||
|
||||
\subsection{Программа fcp}\index{fcp}
|
||||
|
||||
Программа fcp демонстрирует простое использование функций полного сеанса работы
|
||||
(FtpFullOpen и FtpFullClose). Имя файла передаваемого в качестве
|
||||
параметра, может описывать и локальный и удаленный файл. Это позволяет
|
||||
производить передачу как с сервера в локальный файл, так и наоборот,
|
||||
а также с сервера на сервер.
|
||||
|
||||
\subsection{Программа ftptry}\index{ftptry}
|
||||
|
||||
Предназначена для передачи файлов большого размера по сетям которые
|
||||
очень часто ``ломаются''. Это прежде всего относится к сетям построенных
|
||||
на dialup-линиях.
|
||||
|
||||
\ts{ftptry} в основном предназначен для неитерактивной
|
||||
передачи данных, поэтому необходимая информация для выполнения передачи задаeтся в виде опций при запуске программы.
|
||||
|
||||
При запуске \ts{ftptry} без ключей, на экран выводится список всех допустимых
|
||||
опций и один пример запуска, поэтому в данном руководстве ключи
|
||||
и их назначения описывать не имеет смысла.
|
||||
Необходимо только сказать о том, что
|
||||
так как некоторые опции необходимо ставить практически всегда,
|
||||
то можно предварительно
|
||||
установить переменную окружения ``FTPTRY''\index{FTPTRY enviroment}
|
||||
по аналогии с тем как это делается
|
||||
в программе ``less''
|
||||
\footnote{Например: \% setenv FTPTRY ``-DBb -u anonymous -s 60 -t 15''},
|
||||
и писать в командной строке только те опции которые редко
|
||||
используются или не писать их вообще.
|
||||
|
||||
|
||||
\newpage
|
||||
\input rus.ind
|
||||
\newpage
|
||||
\tableofcontents
|
||||
\end{document}
|
||||
|
||||
|
34
lib/libftp/utils/Makefile
Normal file
34
lib/libftp/utils/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
#
|
||||
# A rather bogus Makefile, but one intended to be used by hand anyway..
|
||||
#
|
||||
|
||||
CFLAGS = -I${.CURDIR} -I${.CURDIR}/.. -DREADLINE
|
||||
LDADD+= -L${.CURDIR}
|
||||
DPADD+= libetc.a
|
||||
|
||||
.if exists(${.CURDIR}/../obj)
|
||||
LDADD+= -L${.CURDIR}/../obj
|
||||
DPADD+= ${.CURDIR}/../obj/libftp.a
|
||||
.else
|
||||
LDADD+= -L${.CURDIR}/..
|
||||
DPADD+= ${.CURDIR}/../libftp.a
|
||||
.endif
|
||||
|
||||
all: ftptry mirror uftp
|
||||
|
||||
ftptry: ftptry.o
|
||||
$(CC) $(CFLAGS) -o ftptry ftptry.o -lftp
|
||||
|
||||
uftp: uftp.o uftpcmd.o libetc.a
|
||||
$(CC) $(CFLAGS) -o uftp uftp.o uftpcmd.o -lftp -letc
|
||||
|
||||
mirror: mirror.o
|
||||
$(CC) $(CFLAGS) -o mirror mirror.o -lftp
|
||||
|
||||
clean:
|
||||
rm -f ftptry mirror uftp *~ *.o *.a
|
||||
|
||||
LIBOBJS= readline.o glob.o
|
||||
libetc.a: $(LIBOBJS)
|
||||
ar qc libetc.a $(LIBOBJS)
|
||||
ranlib libetc.a
|
122
lib/libftp/utils/cdefs.h
Normal file
122
lib/libftp/utils/cdefs.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Berkeley Software Design, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)cdefs.h 8.7 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
#ifndef _CDEFS_H_
|
||||
#define _CDEFS_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#define __BEGIN_DECLS extern "C" {
|
||||
#define __END_DECLS };
|
||||
#else
|
||||
#define __BEGIN_DECLS
|
||||
#define __END_DECLS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
|
||||
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
|
||||
* The __CONCAT macro is a bit tricky -- make sure you don't put spaces
|
||||
* in between its arguments. __CONCAT can also concatenate double-quoted
|
||||
* strings produced by the __STRING macro, but this only works with ANSI C.
|
||||
*/
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
#define __P(protos) protos /* full-blown ANSI C */
|
||||
#define __CONCAT(x,y) x ## y
|
||||
#define __STRING(x) #x
|
||||
|
||||
#define __const const /* define reserved names to standard */
|
||||
#define __signed signed
|
||||
#define __volatile volatile
|
||||
#if defined(__cplusplus)
|
||||
#define __inline inline /* convert to C++ keyword */
|
||||
#else
|
||||
#ifndef __GNUC__
|
||||
#define __inline /* delete GCC keyword */
|
||||
#endif /* !__GNUC__ */
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#else /* !(__STDC__ || __cplusplus) */
|
||||
#define __P(protos) () /* traditional C preprocessor */
|
||||
#define __CONCAT(x,y) x/**/y
|
||||
#define __STRING(x) "x"
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __const /* delete pseudo-ANSI C keywords */
|
||||
#define __inline
|
||||
#define __signed
|
||||
#define __volatile
|
||||
/*
|
||||
* In non-ANSI C environments, new programs will want ANSI-only C keywords
|
||||
* deleted from the program and old programs will want them left alone.
|
||||
* When using a compiler other than gcc, programs using the ANSI C keywords
|
||||
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
|
||||
* When using "gcc -traditional", we assume that this is the intent; if
|
||||
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
|
||||
*/
|
||||
#ifndef NO_ANSI_KEYWORDS
|
||||
#define const /* delete ANSI C keywords */
|
||||
#define inline
|
||||
#define signed
|
||||
#define volatile
|
||||
#endif
|
||||
#endif /* !__GNUC__ */
|
||||
#endif /* !(__STDC__ || __cplusplus) */
|
||||
|
||||
/*
|
||||
* GCC1 and some versions of GCC2 declare dead (non-returning) and
|
||||
* pure (no side effects) functions using "volatile" and "const";
|
||||
* unfortunately, these then cause warnings under "-ansi -pedantic".
|
||||
* GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
|
||||
* these work for GNU C++ (modulo a slight glitch in the C++ grammar
|
||||
* in the distribution version of 2.5.5).
|
||||
*/
|
||||
#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
|
||||
#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define __dead __volatile
|
||||
#define __pure __const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Delete pseudo-keywords wherever they are not available or needed. */
|
||||
#ifndef __dead
|
||||
#define __dead
|
||||
#define __pure
|
||||
#endif
|
||||
|
||||
#endif /* !_CDEFS_H_ */
|
633
lib/libftp/utils/ftptry.c
Normal file
633
lib/libftp/utils/ftptry.c
Normal file
@ -0,0 +1,633 @@
|
||||
/*
|
||||
Library for ftpd clients.(libftp)
|
||||
Copyright by Oleg Orel
|
||||
All rights reserved.
|
||||
|
||||
This library is desined for free, non-commercial software creation.
|
||||
It is changeable and can be improved. The author would greatly appreciate
|
||||
any advises, new components and patches of the existing programs.
|
||||
Commercial usage is also possible with participation of it's author.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
char intro[]="\
|
||||
Ftptry - try transfer via FTP.\n\
|
||||
Copyright by Oleg Orel is Reserved.\n\
|
||||
\n\
|
||||
This program is writen using \"libftp\".The main orientation for this\n\
|
||||
program is FTPing via bad-working network. Many network links are\n\
|
||||
down-up switched and networks are broaken, so the problem of\n\
|
||||
transfering large files exists. The main method, used by this\n\
|
||||
software is repetition until successfull transfer. There are some\n\
|
||||
keys for setting repetition and timeout intervals, modes of transfer\n\
|
||||
(binary and ascii), types of transfer (get,put,directory). All options\n\
|
||||
will be described in usage, if the program is started without them.\n\
|
||||
\n\
|
||||
The libftp you may transfer from host lpuds.oea.ihep.su via ftp-anonymous.\n\
|
||||
All question are sent to author via e-mail (orel@oea.ihep.su)\n\
|
||||
";
|
||||
|
||||
#include <FtpLibrary.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
#define FTPTRY "FTPTRY" /* The name of enviroment
|
||||
variable with default options*/
|
||||
#define log(x) FtpLog("ftptry",x)
|
||||
#define DEBUG(x) (debug?log(x):0)
|
||||
#define USERNAME (getenv("USER")==NULL?getenv("LOGNAME"):getenv("USER"))
|
||||
#define DEFAULT_TIMEOUT 600
|
||||
|
||||
|
||||
enum __type__ {ascii=1,binary};
|
||||
enum __mode__ {get=1,put,dir,multiget};
|
||||
enum __logmode__ {lm_tty,lm_file,lm_mail};
|
||||
enum __rcode__ {OK_, BREAK_, CANCEL_};
|
||||
|
||||
char *gethost();
|
||||
char *date();
|
||||
int my_abort();
|
||||
int my_IO();
|
||||
int my_debug();
|
||||
void done(),leave(),sighup();
|
||||
|
||||
char
|
||||
*machine ="localhost",
|
||||
*user="anonymous",
|
||||
*password,
|
||||
*localfile=NULL,
|
||||
*progname="ftptry";
|
||||
|
||||
jmp_buf stack,trap;
|
||||
int counter=0;
|
||||
String tmp;
|
||||
FTP *ftp;
|
||||
int type=ascii;
|
||||
int sleeptime=600;
|
||||
int debug=false;
|
||||
int mode=get;
|
||||
int logmode=lm_tty;
|
||||
char *logfile=NULL;
|
||||
FILE *LIST=NULL;
|
||||
extern int errno;
|
||||
extern char *optarg;
|
||||
extern int optind, opterr;
|
||||
String PASSWORD;
|
||||
|
||||
|
||||
/* Setup enviroment */
|
||||
|
||||
main(int argc,char **argv)
|
||||
{
|
||||
FILE *out,*in;
|
||||
int i;
|
||||
|
||||
if (setjmp(trap)!=0)
|
||||
exit(1);
|
||||
|
||||
signal(SIGHUP,sighup);
|
||||
signal(SIGTRAP,done);
|
||||
signal(SIGINT,done);
|
||||
signal(SIGQUIT,done);
|
||||
|
||||
sprintf(password=PASSWORD,"%s@%s",
|
||||
USERNAME,
|
||||
gethost());
|
||||
|
||||
progname=argv[0];
|
||||
|
||||
FtpDebug(&FtpInit);
|
||||
FtpSetErrorHandler(&FtpInit,my_abort);
|
||||
FtpSetIOHandler(&FtpInit,my_IO);
|
||||
FtpSetFlag(&FtpInit,FTP_REST);
|
||||
FtpSetTimeout(&FtpInit,DEFAULT_TIMEOUT);
|
||||
|
||||
setoptions();
|
||||
optind=1;
|
||||
options(argc,argv);
|
||||
if ( argc<2 ) usage();
|
||||
|
||||
switch(logmode)
|
||||
{
|
||||
|
||||
case lm_file:
|
||||
|
||||
if (fork()) quit("Deattaching.....");
|
||||
close(0);close(1);close(2);
|
||||
|
||||
if (logfile==NULL)
|
||||
{
|
||||
sprintf(tmp,"/tmp/ftptry-%s.XXXXXX",USERNAME);
|
||||
mktemp(tmp);
|
||||
}
|
||||
else
|
||||
strcpy(tmp,logfile);
|
||||
|
||||
open(tmp,O_TRUNC|O_CREAT|O_WRONLY,0600);
|
||||
dup(0);
|
||||
dup(0);
|
||||
break;
|
||||
|
||||
case lm_mail:
|
||||
|
||||
|
||||
|
||||
if (fork()) quit("Deattaching.....");
|
||||
|
||||
close(0);close(1);close(2);
|
||||
if (popen("/usr/lib/sendmail -t","w")==NULL)
|
||||
perror("sendmail"),
|
||||
quit("");
|
||||
|
||||
dup(0);
|
||||
dup(0);
|
||||
|
||||
printf("From: %s@%s\n",USERNAME,gethost());
|
||||
printf("To: %s@%s\n",USERNAME,gethost());
|
||||
printf("Subject: ftptry session log\n\n");
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
signal(SIGHUP,sighup);
|
||||
if (isatty(fileno(stdout))) FtpSetHashHandler(&FtpInit,FtpHash);
|
||||
loop(argc,argv,optind);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
INLINE noargs(int argc, char **argv, int optind)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=optind;i<argc;i++)
|
||||
if (argv[i]!=NULL) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Main loop */
|
||||
|
||||
loop(int argc, char **argv, int optind /* First args as filename */ )
|
||||
{
|
||||
int i,rcode;
|
||||
String tmp;
|
||||
String machine;
|
||||
String filename;
|
||||
String localfilename;
|
||||
char *p1;
|
||||
|
||||
for(i=optind;;(i==argc-1)?i=optind,
|
||||
sprintf(tmp,"Sleeping %d secs",sleeptime),log(tmp),sleep(sleeptime):
|
||||
i++)
|
||||
{
|
||||
if (noargs(argc,argv,optind))
|
||||
quit("Nothing doing");
|
||||
|
||||
if (strchr(argv[i],':')==NULL)
|
||||
{
|
||||
if (find_archie(argv[i],machine,filename,localfilename)==0)
|
||||
argv[i]=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sscanf(argv[i],"%[^:]:%s",machine,filename);
|
||||
if ((p1=strrchr(filename,'/'))!=NULL)
|
||||
strcpy(localfilename,p1+1);
|
||||
else
|
||||
strcpy(localfilename,filename);
|
||||
}
|
||||
if (localfile == NULL ) localfile=localfilename;
|
||||
if ((rcode=transfer(machine, filename, localfile))==OK_)
|
||||
DEBUG("Transfer complete"),
|
||||
exit(0);
|
||||
if (rcode==CANCEL_ && strchr(argv[i],':')!=NULL)
|
||||
argv[i]=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
transfer(char *machine, char *file, char *localfile)
|
||||
{
|
||||
int r;
|
||||
String tmp;
|
||||
|
||||
if ((r=setjmp(stack))!=0)
|
||||
return r;
|
||||
|
||||
sprintf(tmp,"Start transfer, machine is %s, remote file is %s, local file is %s",
|
||||
machine, file, localfile);
|
||||
DEBUG(tmp);
|
||||
|
||||
FtpLogin(&ftp,machine,user,password,NULL);
|
||||
|
||||
if (type==binary)
|
||||
FtpBinary(ftp);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
|
||||
case get:
|
||||
|
||||
FtpRetr(ftp,"RETR %s",file,localfile);
|
||||
break;
|
||||
|
||||
case put:
|
||||
|
||||
FtpStor(ftp,"STOR %s",localfile,file);
|
||||
break;
|
||||
|
||||
case dir:
|
||||
|
||||
FtpRetr(ftp,"LIST %s",file,localfile);
|
||||
break;
|
||||
|
||||
case multiget:
|
||||
domultiget(file);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
FtpBye(ftp);
|
||||
|
||||
DEBUG("Transfer complete");
|
||||
return OK_;
|
||||
}
|
||||
|
||||
|
||||
void leave(int code)
|
||||
{
|
||||
FtpQuickBye(ftp);
|
||||
DEBUG("Leaving transfering");
|
||||
longjmp(stack,code);
|
||||
}
|
||||
|
||||
void sighup()
|
||||
{
|
||||
leave(BREAK_);
|
||||
}
|
||||
|
||||
|
||||
quit(char *s)
|
||||
{
|
||||
log(s);
|
||||
longjmp(trap,1);
|
||||
}
|
||||
|
||||
|
||||
my_IO(FTP *ftp, int n, char *s )
|
||||
{
|
||||
|
||||
DEBUG(s);
|
||||
leave(BREAK_);
|
||||
}
|
||||
|
||||
my_abort(FTP *ftp, int n, char *s )
|
||||
{
|
||||
|
||||
log(s);
|
||||
/* No access or not found, exclude network or host unreachable */;
|
||||
if (abs(n) == 550 && FtpBadReply550(s))
|
||||
leave(CANCEL_);
|
||||
leave(BREAK_);
|
||||
}
|
||||
|
||||
|
||||
domultiget(char *file)
|
||||
{
|
||||
String list,localname,tmp_name;
|
||||
char *p1;
|
||||
|
||||
sprintf(list,"/tmp/ftptry-%s-multiget.XXXXXX",USERNAME);
|
||||
mktemp(list);
|
||||
|
||||
FtpRetr(ftp,"NLST %s",file,list);
|
||||
|
||||
if ((LIST=fopen(list,"r"))==NULL) quit((char *)sys_errlist[errno]);
|
||||
|
||||
while ( fgets (tmp, sizeof tmp, LIST) != NULL )
|
||||
{
|
||||
tmp[strlen(tmp)-1]=0;
|
||||
if ((p1=strrchr(tmp,'/'))!=NULL)
|
||||
strcpy(localname,p1+1);
|
||||
else
|
||||
strcpy(localname,tmp);
|
||||
|
||||
DEBUG(localname);
|
||||
FtpGet(ftp,tmp,localname);
|
||||
}
|
||||
|
||||
fclose(LIST);
|
||||
LIST=NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr,"\
|
||||
Usage: %s [optins] [host:file]\n\
|
||||
(default host \"localhost\",\n\
|
||||
default file \"README\" or \".\" in directory mode)\n\
|
||||
\n\
|
||||
Valid options:\n\
|
||||
\n\
|
||||
-u user default anonymous\n\
|
||||
-p password default %s\n\
|
||||
-P inquire password from your terminal\n\
|
||||
-l local_file use only if remote and local file differ\n\
|
||||
-c direct output to stdout(like cat)\n\
|
||||
-r reverse mode, i.e. send file to remote host\n\
|
||||
-d directory mode, remote file is patern or \"ls\" options\n\
|
||||
default output is stdout.\n\
|
||||
-G multiget mode, file is patern for \"ls\" command\n\
|
||||
again at next try.\n\
|
||||
-b binary transfer mode\n\
|
||||
-s seconds Retry interval, default 10 minutes\n\
|
||||
-t seconds Timeout, default 10 minutes\n\
|
||||
-D Turn on debugging mode\n\
|
||||
-B Run in background and direct output to\n\
|
||||
/tmp/ftptry-%s.XXXXXX\n\
|
||||
-o file Run in background and direct output\n\
|
||||
to file\n\
|
||||
-m Send output to orel via e-mail\n\
|
||||
-I Print short introduction\n\
|
||||
\n\
|
||||
Example:\n\
|
||||
%s -Dbs 300 garbo.uwasa.fi:ls-lR.Z\n\
|
||||
Retrive file ls-lR.Z from garbo.uwasa.fi in binary mode\n\
|
||||
trying to reestablish connection every 5 minutes\n\
|
||||
on failure. Print debugging information.\n\
|
||||
\n\
|
||||
You can set default options to %s enviroment variable\n\
|
||||
",progname,password,USERNAME,progname,FTPTRY);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
char *gethost()
|
||||
{
|
||||
static String tmp;
|
||||
String tmp2;
|
||||
|
||||
gethostname(tmp2,sizeof tmp2);
|
||||
|
||||
strcpy(tmp,FtpGetHost(tmp2)->h_name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
void done(sig)
|
||||
{
|
||||
String x;
|
||||
|
||||
signal(sig,done);
|
||||
sprintf(x,"interputed by signal %d",sig);
|
||||
log(x);
|
||||
longjmp(trap,1);
|
||||
}
|
||||
|
||||
|
||||
options(int argc,char **argv)
|
||||
{
|
||||
char c;
|
||||
|
||||
while((c=getopt(argc,argv,"GOIBDru:p:Pdbs:o:l:t:cm"))!=EOF)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
|
||||
case 'G':
|
||||
mode=multiget;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
|
||||
if (localfile==NULL) localfile="*STDOUT*";
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
fprintf(stderr,intro);
|
||||
exit(0);
|
||||
|
||||
case 'r':
|
||||
|
||||
mode=put;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
||||
mode=dir;
|
||||
if (localfile==NULL) localfile="*STDOUT*";
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
FtpSetTimeout(&FtpInit,atoi(optarg));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
localfile=optarg;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
|
||||
debug=true;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
|
||||
user=optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
|
||||
password=optarg;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
|
||||
password=(char *)getpass("Password:");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
|
||||
type=binary;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
||||
sleeptime=atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
|
||||
logmode=lm_file;
|
||||
logfile=optarg;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
|
||||
logmode=lm_mail;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
|
||||
logmode=lm_file;
|
||||
logfile=NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
usage();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setoptions()
|
||||
{
|
||||
String x;
|
||||
char *p,*sp;
|
||||
int argc;
|
||||
char *argv[100];
|
||||
|
||||
|
||||
|
||||
|
||||
if ((p=(char *)getenv(FTPTRY))!=NULL && *p!=0)
|
||||
strcpy(x,p);
|
||||
else
|
||||
return;
|
||||
|
||||
|
||||
|
||||
for (argv[0]="",p=x,sp=x,argc=1; *p!=0 ; p++)
|
||||
{
|
||||
if (*p==' ')
|
||||
{
|
||||
*p=0;
|
||||
argv[argc++] = sp;
|
||||
sp = p+1;
|
||||
}
|
||||
}
|
||||
|
||||
argv[argc++]=sp;
|
||||
|
||||
options(argc,argv);
|
||||
}
|
||||
|
||||
|
||||
INLINE unsigned long maxsize(String *result, int hops)
|
||||
{
|
||||
unsigned long maxsiz=0,cursiz=0;
|
||||
int i;
|
||||
|
||||
for (i=0;i<hops;i++)
|
||||
{
|
||||
sscanf(result[i],"%*[^ ] %u %*s",&cursiz);
|
||||
if (cursiz>maxsiz)maxsiz=cursiz;
|
||||
}
|
||||
return maxsiz;
|
||||
}
|
||||
|
||||
|
||||
find_archie(char *what,char *machine, char *filename, char *localfilename)
|
||||
{
|
||||
|
||||
#define MAXHOPS 15
|
||||
|
||||
static String result[MAXHOPS];
|
||||
static int last=0;
|
||||
static int size=0;
|
||||
static int first=0;
|
||||
int rnd;
|
||||
static int init=0;
|
||||
static String oldwhat={'\0'};
|
||||
char *p1;
|
||||
int i;
|
||||
|
||||
if (!init || strcmp(oldwhat,what)!=0 || last==0)
|
||||
{
|
||||
String cmd;
|
||||
FILE *archie;
|
||||
|
||||
for (i=0;i<MAXHOPS;i++) result[i][0]=0;
|
||||
sprintf(cmd,"archie -l -m %d %s",MAXHOPS,what);
|
||||
DEBUG(cmd);
|
||||
|
||||
if ((archie = popen(cmd,"r"))==NULL)
|
||||
quit("Archie can't execute");
|
||||
|
||||
for(i=0;i<MAXHOPS;i++)
|
||||
{
|
||||
if (fgets(result[i],sizeof (result[i]), archie)==NULL)
|
||||
break;
|
||||
result[i][strlen(result[i])-1]=0;
|
||||
DEBUG(result[i]);
|
||||
}
|
||||
|
||||
|
||||
last=i;
|
||||
|
||||
if ( last==0 )
|
||||
{
|
||||
DEBUG("archie not found need file");
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
init=1;
|
||||
first=0;
|
||||
strcpy(oldwhat,what);
|
||||
size=maxsize(result,MAXHOPS);
|
||||
}
|
||||
|
||||
if (first >= last-1) first=0;
|
||||
for ( i=first; i<last; i++)
|
||||
if ( atoi ( strchr(result[i],' ') + 1 ) == size)
|
||||
{
|
||||
first=i+1;
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG("Archie select is ... (see next line)");
|
||||
DEBUG(result[i]);
|
||||
|
||||
if (sscanf ( result[i] , "%*[^ ] %*[^ ] %[^ ] %s", machine, filename )!=2)
|
||||
{
|
||||
DEBUG("Bad archie output format");
|
||||
last=0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
if ( (p1=strrchr(filename,'/'))!= NULL)
|
||||
strcpy(localfilename,p1+1);
|
||||
else
|
||||
strcpy(localfilename,filename);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
850
lib/libftp/utils/glob.c
Normal file
850
lib/libftp/utils/glob.c
Normal file
@ -0,0 +1,850 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Guido van Rossum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/*
|
||||
* glob(3) -- a superset of the one defined in POSIX 1003.2.
|
||||
*
|
||||
* The [!...] convention to negate a range is supported (SysV, Posix, ksh).
|
||||
*
|
||||
* Optional extra services, controlled by flags not defined by POSIX:
|
||||
*
|
||||
* GLOB_QUOTE:
|
||||
* Escaping convention: \ inhibits any special meaning the following
|
||||
* character might have (except \ at end of string is retained).
|
||||
* GLOB_MAGCHAR:
|
||||
* Set in gl_flags if pattern contained a globbing character.
|
||||
* GLOB_NOMAGIC:
|
||||
* Same as GLOB_NOCHECK, but it will only append pattern if it did
|
||||
* not contain any magic characters. [Used in csh style globbing]
|
||||
* GLOB_ALTDIRFUNC:
|
||||
* Use alternately specified directory access functions.
|
||||
* GLOB_TILDE:
|
||||
* expand ~user/foo to the /home/dir/of/user/foo
|
||||
* GLOB_BRACE:
|
||||
* expand {1,2}{a,b} to 1a 1b 2a 2b
|
||||
* gl_matchc:
|
||||
* Number of matches in the current invocation of glob.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DOLLAR '$'
|
||||
#define DOT '.'
|
||||
#define EOS '\0'
|
||||
#define LBRACKET '['
|
||||
#define NOT '!'
|
||||
#define QUESTION '?'
|
||||
#define QUOTE '\\'
|
||||
#define RANGE '-'
|
||||
#define RBRACKET ']'
|
||||
#define SEP '/'
|
||||
#define STAR '*'
|
||||
#define TILDE '~'
|
||||
#define UNDERSCORE '_'
|
||||
#define LBRACE '{'
|
||||
#define RBRACE '}'
|
||||
#define SLASH '/'
|
||||
#define COMMA ','
|
||||
|
||||
#ifndef DEBUG
|
||||
|
||||
#define M_QUOTE 0x8000
|
||||
#define M_PROTECT 0x4000
|
||||
#define M_MASK 0xffff
|
||||
#define M_ASCII 0x00ff
|
||||
|
||||
typedef u_short Char;
|
||||
|
||||
#else
|
||||
|
||||
#define M_QUOTE 0x80
|
||||
#define M_PROTECT 0x40
|
||||
#define M_MASK 0xff
|
||||
#define M_ASCII 0x7f
|
||||
|
||||
typedef char Char;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define CHAR(c) ((Char)((c)&M_ASCII))
|
||||
#define META(c) ((Char)((c)|M_QUOTE))
|
||||
#define M_ALL META('*')
|
||||
#define M_END META(']')
|
||||
#define M_NOT META('!')
|
||||
#define M_ONE META('?')
|
||||
#define M_RNG META('-')
|
||||
#define M_SET META('[')
|
||||
#define ismeta(c) (((c)&M_QUOTE) != 0)
|
||||
|
||||
|
||||
static int compare __P((const void *, const void *));
|
||||
static void g_Ctoc __P((const Char *, char *));
|
||||
static int g_lstat __P((Char *, struct stat *, glob_t *));
|
||||
static DIR *g_opendir __P((Char *, glob_t *));
|
||||
static Char *g_strchr __P((Char *, int));
|
||||
#ifdef notdef
|
||||
static Char *g_strcat __P((Char *, const Char *));
|
||||
#endif
|
||||
static int g_stat __P((Char *, struct stat *, glob_t *));
|
||||
static int glob0 __P((const Char *, glob_t *));
|
||||
static int glob1 __P((Char *, glob_t *));
|
||||
static int glob2 __P((Char *, Char *, Char *, glob_t *));
|
||||
static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *));
|
||||
static int globextend __P((const Char *, glob_t *));
|
||||
static const Char * globtilde __P((const Char *, Char *, glob_t *));
|
||||
static int globexp1 __P((const Char *, glob_t *));
|
||||
static int globexp2 __P((const Char *, const Char *, glob_t *, int *));
|
||||
static int match __P((Char *, Char *, Char *));
|
||||
#ifdef DEBUG
|
||||
static void qprintf __P((const char *, Char *));
|
||||
#endif
|
||||
|
||||
int
|
||||
glob(pattern, flags, errfunc, pglob)
|
||||
const char *pattern;
|
||||
int flags, (*errfunc) __P((const char *, int));
|
||||
glob_t *pglob;
|
||||
{
|
||||
const u_char *patnext;
|
||||
int c;
|
||||
Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
|
||||
|
||||
patnext = (u_char *) pattern;
|
||||
if (!(flags & GLOB_APPEND)) {
|
||||
pglob->gl_pathc = 0;
|
||||
pglob->gl_pathv = NULL;
|
||||
if (!(flags & GLOB_DOOFFS))
|
||||
pglob->gl_offs = 0;
|
||||
}
|
||||
pglob->gl_flags = flags & ~GLOB_MAGCHAR;
|
||||
pglob->gl_errfunc = errfunc;
|
||||
pglob->gl_matchc = 0;
|
||||
|
||||
bufnext = patbuf;
|
||||
bufend = bufnext + MAXPATHLEN;
|
||||
if (flags & GLOB_QUOTE) {
|
||||
/* Protect the quoted characters. */
|
||||
while (bufnext < bufend && (c = *patnext++) != EOS)
|
||||
if (c == QUOTE) {
|
||||
if ((c = *patnext++) == EOS) {
|
||||
c = QUOTE;
|
||||
--patnext;
|
||||
}
|
||||
*bufnext++ = c | M_PROTECT;
|
||||
}
|
||||
else
|
||||
*bufnext++ = c;
|
||||
}
|
||||
else
|
||||
while (bufnext < bufend && (c = *patnext++) != EOS)
|
||||
*bufnext++ = c;
|
||||
*bufnext = EOS;
|
||||
|
||||
if (flags & GLOB_BRACE)
|
||||
return globexp1(patbuf, pglob);
|
||||
else
|
||||
return glob0(patbuf, pglob);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand recursively a glob {} pattern. When there is no more expansion
|
||||
* invoke the standard globbing routine to glob the rest of the magic
|
||||
* characters
|
||||
*/
|
||||
static int globexp1(pattern, pglob)
|
||||
const Char *pattern;
|
||||
glob_t *pglob;
|
||||
{
|
||||
const Char* ptr = pattern;
|
||||
int rv;
|
||||
|
||||
/* Protect a single {}, for find(1), like csh */
|
||||
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
|
||||
return glob0(pattern, pglob);
|
||||
|
||||
while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
|
||||
if (!globexp2(ptr, pattern, pglob, &rv))
|
||||
return rv;
|
||||
|
||||
return glob0(pattern, pglob);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Recursive brace globbing helper. Tries to expand a single brace.
|
||||
* If it succeeds then it invokes globexp1 with the new pattern.
|
||||
* If it fails then it tries to glob the rest of the pattern and returns.
|
||||
*/
|
||||
static int globexp2(ptr, pattern, pglob, rv)
|
||||
const Char *ptr, *pattern;
|
||||
glob_t *pglob;
|
||||
int *rv;
|
||||
{
|
||||
int i;
|
||||
Char *lm, *ls;
|
||||
const Char *pe, *pm, *pl;
|
||||
Char patbuf[MAXPATHLEN + 1];
|
||||
|
||||
/* copy part up to the brace */
|
||||
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
|
||||
continue;
|
||||
ls = lm;
|
||||
|
||||
/* Find the balanced brace */
|
||||
for (i = 0, pe = ++ptr; *pe; pe++)
|
||||
if (*pe == LBRACKET) {
|
||||
/* Ignore everything between [] */
|
||||
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
|
||||
continue;
|
||||
if (*pe == EOS) {
|
||||
/*
|
||||
* We could not find a matching RBRACKET.
|
||||
* Ignore and just look for RBRACE
|
||||
*/
|
||||
pe = pm;
|
||||
}
|
||||
}
|
||||
else if (*pe == LBRACE)
|
||||
i++;
|
||||
else if (*pe == RBRACE) {
|
||||
if (i == 0)
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Non matching braces; just glob the pattern */
|
||||
if (i != 0 || *pe == EOS) {
|
||||
*rv = glob0(patbuf, pglob);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
|
||||
switch (*pm) {
|
||||
case LBRACKET:
|
||||
/* Ignore everything between [] */
|
||||
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
|
||||
continue;
|
||||
if (*pm == EOS) {
|
||||
/*
|
||||
* We could not find a matching RBRACKET.
|
||||
* Ignore and just look for RBRACE
|
||||
*/
|
||||
pm = pl;
|
||||
}
|
||||
break;
|
||||
|
||||
case LBRACE:
|
||||
i++;
|
||||
break;
|
||||
|
||||
case RBRACE:
|
||||
if (i) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case COMMA:
|
||||
if (i && *pm == COMMA)
|
||||
break;
|
||||
else {
|
||||
/* Append the current string */
|
||||
for (lm = ls; (pl < pm); *lm++ = *pl++)
|
||||
continue;
|
||||
/*
|
||||
* Append the rest of the pattern after the
|
||||
* closing brace
|
||||
*/
|
||||
for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
|
||||
continue;
|
||||
|
||||
/* Expand the current pattern */
|
||||
#ifdef DEBUG
|
||||
qprintf("globexp2:", patbuf);
|
||||
#endif
|
||||
*rv = globexp1(patbuf, pglob);
|
||||
|
||||
/* move after the comma, to the next string */
|
||||
pl = pm + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*rv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* expand tilde from the passwd file.
|
||||
*/
|
||||
static const Char *
|
||||
globtilde(pattern, patbuf, pglob)
|
||||
const Char *pattern;
|
||||
Char *patbuf;
|
||||
glob_t *pglob;
|
||||
{
|
||||
struct passwd *pwd;
|
||||
char *h;
|
||||
const Char *p;
|
||||
Char *b;
|
||||
|
||||
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
|
||||
return pattern;
|
||||
|
||||
/* Copy up to the end of the string or / */
|
||||
for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH;
|
||||
*h++ = *p++)
|
||||
continue;
|
||||
|
||||
*h = EOS;
|
||||
|
||||
if (((char *) patbuf)[0] == EOS) {
|
||||
/*
|
||||
* handle a plain ~ or ~/ by expanding $HOME
|
||||
* first and then trying the password file
|
||||
*/
|
||||
if ((h = getenv("HOME")) == NULL) {
|
||||
if ((pwd = getpwuid(getuid())) == NULL)
|
||||
return pattern;
|
||||
else
|
||||
h = pwd->pw_dir;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Expand a ~user
|
||||
*/
|
||||
if ((pwd = getpwnam((char*) patbuf)) == NULL)
|
||||
return pattern;
|
||||
else
|
||||
h = pwd->pw_dir;
|
||||
}
|
||||
|
||||
/* Copy the home directory */
|
||||
for (b = patbuf; *h; *b++ = *h++)
|
||||
continue;
|
||||
|
||||
/* Append the rest of the pattern */
|
||||
while ((*b++ = *p++) != EOS)
|
||||
continue;
|
||||
|
||||
return patbuf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The main glob() routine: compiles the pattern (optionally processing
|
||||
* quotes), calls glob1() to do the real pattern matching, and finally
|
||||
* sorts the list (unless unsorted operation is requested). Returns 0
|
||||
* if things went well, nonzero if errors occurred. It is not an error
|
||||
* to find no matches.
|
||||
*/
|
||||
static int
|
||||
glob0(pattern, pglob)
|
||||
const Char *pattern;
|
||||
glob_t *pglob;
|
||||
{
|
||||
const Char *qpatnext;
|
||||
int c, err, oldpathc;
|
||||
Char *bufnext, patbuf[MAXPATHLEN+1];
|
||||
|
||||
qpatnext = globtilde(pattern, patbuf, pglob);
|
||||
oldpathc = pglob->gl_pathc;
|
||||
bufnext = patbuf;
|
||||
|
||||
/* We don't need to check for buffer overflow any more. */
|
||||
while ((c = *qpatnext++) != EOS) {
|
||||
switch (c) {
|
||||
case LBRACKET:
|
||||
c = *qpatnext;
|
||||
if (c == NOT)
|
||||
++qpatnext;
|
||||
if (*qpatnext == EOS ||
|
||||
g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
|
||||
*bufnext++ = LBRACKET;
|
||||
if (c == NOT)
|
||||
--qpatnext;
|
||||
break;
|
||||
}
|
||||
*bufnext++ = M_SET;
|
||||
if (c == NOT)
|
||||
*bufnext++ = M_NOT;
|
||||
c = *qpatnext++;
|
||||
do {
|
||||
*bufnext++ = CHAR(c);
|
||||
if (*qpatnext == RANGE &&
|
||||
(c = qpatnext[1]) != RBRACKET) {
|
||||
*bufnext++ = M_RNG;
|
||||
*bufnext++ = CHAR(c);
|
||||
qpatnext += 2;
|
||||
}
|
||||
} while ((c = *qpatnext++) != RBRACKET);
|
||||
pglob->gl_flags |= GLOB_MAGCHAR;
|
||||
*bufnext++ = M_END;
|
||||
break;
|
||||
case QUESTION:
|
||||
pglob->gl_flags |= GLOB_MAGCHAR;
|
||||
*bufnext++ = M_ONE;
|
||||
break;
|
||||
case STAR:
|
||||
pglob->gl_flags |= GLOB_MAGCHAR;
|
||||
/* collapse adjacent stars to one,
|
||||
* to avoid exponential behavior
|
||||
*/
|
||||
if (bufnext == patbuf || bufnext[-1] != M_ALL)
|
||||
*bufnext++ = M_ALL;
|
||||
break;
|
||||
default:
|
||||
*bufnext++ = CHAR(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*bufnext = EOS;
|
||||
#ifdef DEBUG
|
||||
qprintf("glob0:", patbuf);
|
||||
#endif
|
||||
|
||||
if ((err = glob1(patbuf, pglob)) != 0)
|
||||
return(err);
|
||||
|
||||
/*
|
||||
* If there was no match we are going to append the pattern
|
||||
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
|
||||
* and the pattern did not contain any magic characters
|
||||
* GLOB_NOMAGIC is there just for compatibility with csh.
|
||||
*/
|
||||
if (pglob->gl_pathc == oldpathc &&
|
||||
((pglob->gl_flags & GLOB_NOCHECK) ||
|
||||
((pglob->gl_flags & GLOB_NOMAGIC) &&
|
||||
!(pglob->gl_flags & GLOB_MAGCHAR))))
|
||||
return(globextend(pattern, pglob));
|
||||
else if (!(pglob->gl_flags & GLOB_NOSORT))
|
||||
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
|
||||
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
compare(p, q)
|
||||
const void *p, *q;
|
||||
{
|
||||
return(strcmp(*(char **)p, *(char **)q));
|
||||
}
|
||||
|
||||
static int
|
||||
glob1(pattern, pglob)
|
||||
Char *pattern;
|
||||
glob_t *pglob;
|
||||
{
|
||||
Char pathbuf[MAXPATHLEN+1];
|
||||
|
||||
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
|
||||
if (*pattern == EOS)
|
||||
return(0);
|
||||
return(glob2(pathbuf, pathbuf, pattern, pglob));
|
||||
}
|
||||
|
||||
/*
|
||||
* The functions glob2 and glob3 are mutually recursive; there is one level
|
||||
* of recursion for each segment in the pattern that contains one or more
|
||||
* meta characters.
|
||||
*/
|
||||
static int
|
||||
glob2(pathbuf, pathend, pattern, pglob)
|
||||
Char *pathbuf, *pathend, *pattern;
|
||||
glob_t *pglob;
|
||||
{
|
||||
struct stat sb;
|
||||
Char *p, *q;
|
||||
int anymeta;
|
||||
|
||||
/*
|
||||
* Loop over pattern segments until end of pattern or until
|
||||
* segment with meta character found.
|
||||
*/
|
||||
for (anymeta = 0;;) {
|
||||
if (*pattern == EOS) { /* End of pattern? */
|
||||
*pathend = EOS;
|
||||
if (g_lstat(pathbuf, &sb, pglob))
|
||||
return(0);
|
||||
|
||||
if (((pglob->gl_flags & GLOB_MARK) &&
|
||||
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
|
||||
#ifdef S_ISLNK
|
||||
|| (S_ISLNK(sb.st_mode) &&
|
||||
#else
|
||||
|| ( (sb.st_mode&S_IFLNK) &&
|
||||
#endif
|
||||
(g_stat(pathbuf, &sb, pglob) == 0) &&
|
||||
S_ISDIR(sb.st_mode)))) {
|
||||
*pathend++ = SEP;
|
||||
*pathend = EOS;
|
||||
}
|
||||
++pglob->gl_matchc;
|
||||
return(globextend(pathbuf, pglob));
|
||||
}
|
||||
|
||||
/* Find end of next segment, copy tentatively to pathend. */
|
||||
q = pathend;
|
||||
p = pattern;
|
||||
while (*p != EOS && *p != SEP) {
|
||||
if (ismeta(*p))
|
||||
anymeta = 1;
|
||||
*q++ = *p++;
|
||||
}
|
||||
|
||||
if (!anymeta) { /* No expansion, do next segment. */
|
||||
pathend = q;
|
||||
pattern = p;
|
||||
while (*pattern == SEP)
|
||||
*pathend++ = *pattern++;
|
||||
} else /* Need expansion, recurse. */
|
||||
return(glob3(pathbuf, pathend, pattern, p, pglob));
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
glob3(pathbuf, pathend, pattern, restpattern, pglob)
|
||||
Char *pathbuf, *pathend, *pattern, *restpattern;
|
||||
glob_t *pglob;
|
||||
{
|
||||
register struct dirent *dp;
|
||||
DIR *dirp;
|
||||
int err;
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
/*
|
||||
* The readdirfunc declaration can't be prototyped, because it is
|
||||
* assigned, below, to two functions which are prototyped in glob.h
|
||||
* and dirent.h as taking pointers to differently typed opaque
|
||||
* structures.
|
||||
*/
|
||||
struct dirent *(*readdirfunc)();
|
||||
|
||||
*pathend = EOS;
|
||||
errno = 0;
|
||||
|
||||
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
|
||||
/* TODO: don't call for ENOENT or ENOTDIR? */
|
||||
if (pglob->gl_errfunc) {
|
||||
g_Ctoc(pathbuf, buf);
|
||||
if (pglob->gl_errfunc(buf, errno) ||
|
||||
pglob->gl_flags & GLOB_ERR)
|
||||
return (GLOB_ABEND);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
/* Search directory for matching names. */
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
readdirfunc = pglob->gl_readdir;
|
||||
else
|
||||
readdirfunc = readdir;
|
||||
while ((dp = (*readdirfunc)(dirp))) {
|
||||
register u_char *sc;
|
||||
register Char *dc;
|
||||
|
||||
/* Initial DOT must be matched literally. */
|
||||
if (dp->d_name[0] == DOT && *pattern != DOT)
|
||||
continue;
|
||||
for (sc = (u_char *) dp->d_name, dc = pathend;
|
||||
(*dc++ = *sc++) != EOS;)
|
||||
continue;
|
||||
if (!match(pathend, pattern, restpattern)) {
|
||||
*pathend = EOS;
|
||||
continue;
|
||||
}
|
||||
err = glob2(pathbuf, --dc, restpattern, pglob);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
(*pglob->gl_closedir)(dirp);
|
||||
else
|
||||
closedir(dirp);
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Extend the gl_pathv member of a glob_t structure to accomodate a new item,
|
||||
* add the new item, and update gl_pathc.
|
||||
*
|
||||
* This assumes the BSD realloc, which only copies the block when its size
|
||||
* crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
|
||||
* behavior.
|
||||
*
|
||||
* Return 0 if new item added, error code if memory couldn't be allocated.
|
||||
*
|
||||
* Invariant of the glob_t structure:
|
||||
* Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
|
||||
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
|
||||
*/
|
||||
static int
|
||||
globextend(path, pglob)
|
||||
const Char *path;
|
||||
glob_t *pglob;
|
||||
{
|
||||
register char **pathv;
|
||||
register int i;
|
||||
u_int newsize;
|
||||
char *copy;
|
||||
const Char *p;
|
||||
|
||||
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
|
||||
pathv = pglob->gl_pathv ?
|
||||
realloc((char *)pglob->gl_pathv, newsize) :
|
||||
malloc(newsize);
|
||||
if (pathv == NULL)
|
||||
return(GLOB_NOSPACE);
|
||||
|
||||
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
|
||||
/* first time around -- clear initial gl_offs items */
|
||||
pathv += pglob->gl_offs;
|
||||
for (i = pglob->gl_offs; --i >= 0; )
|
||||
*--pathv = NULL;
|
||||
}
|
||||
pglob->gl_pathv = pathv;
|
||||
|
||||
for (p = path; *p++;)
|
||||
continue;
|
||||
if ((copy = malloc(p - path)) != NULL) {
|
||||
g_Ctoc(path, copy);
|
||||
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
|
||||
}
|
||||
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
|
||||
return(copy == NULL ? GLOB_NOSPACE : 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pattern matching function for filenames. Each occurrence of the *
|
||||
* pattern causes a recursion level.
|
||||
*/
|
||||
static int
|
||||
match(name, pat, patend)
|
||||
register Char *name, *pat, *patend;
|
||||
{
|
||||
int ok, negate_range;
|
||||
Char c, k;
|
||||
|
||||
while (pat < patend) {
|
||||
c = *pat++;
|
||||
switch (c & M_MASK) {
|
||||
case M_ALL:
|
||||
if (pat == patend)
|
||||
return(1);
|
||||
do
|
||||
if (match(name, pat, patend))
|
||||
return(1);
|
||||
while (*name++ != EOS);
|
||||
return(0);
|
||||
case M_ONE:
|
||||
if (*name++ == EOS)
|
||||
return(0);
|
||||
break;
|
||||
case M_SET:
|
||||
ok = 0;
|
||||
if ((k = *name++) == EOS)
|
||||
return(0);
|
||||
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
|
||||
++pat;
|
||||
while (((c = *pat++) & M_MASK) != M_END)
|
||||
if ((*pat & M_MASK) == M_RNG) {
|
||||
if (c <= k && k <= pat[1])
|
||||
ok = 1;
|
||||
pat += 2;
|
||||
} else if (c == k)
|
||||
ok = 1;
|
||||
if (ok == negate_range)
|
||||
return(0);
|
||||
break;
|
||||
default:
|
||||
if (*name++ != c)
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return(*name == EOS);
|
||||
}
|
||||
|
||||
/* Free allocated data belonging to a glob_t structure. */
|
||||
void
|
||||
globfree(pglob)
|
||||
glob_t *pglob;
|
||||
{
|
||||
register int i;
|
||||
register char **pp;
|
||||
|
||||
if (pglob->gl_pathv != NULL) {
|
||||
pp = pglob->gl_pathv + pglob->gl_offs;
|
||||
for (i = pglob->gl_pathc; i--; ++pp)
|
||||
if (*pp)
|
||||
free(*pp);
|
||||
free(pglob->gl_pathv);
|
||||
}
|
||||
}
|
||||
|
||||
static DIR *
|
||||
g_opendir(str, pglob)
|
||||
register Char *str;
|
||||
glob_t *pglob;
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
if (!*str)
|
||||
strcpy(buf, ".");
|
||||
else
|
||||
g_Ctoc(str, buf);
|
||||
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
return((*pglob->gl_opendir)(buf));
|
||||
|
||||
return(opendir(buf));
|
||||
}
|
||||
|
||||
static int
|
||||
g_lstat(fn, sb, pglob)
|
||||
register Char *fn;
|
||||
struct stat *sb;
|
||||
glob_t *pglob;
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
g_Ctoc(fn, buf);
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
return((*pglob->gl_lstat)(buf, sb));
|
||||
return(lstat(buf, sb));
|
||||
}
|
||||
|
||||
static int
|
||||
g_stat(fn, sb, pglob)
|
||||
register Char *fn;
|
||||
struct stat *sb;
|
||||
glob_t *pglob;
|
||||
{
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
g_Ctoc(fn, buf);
|
||||
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
|
||||
return((*pglob->gl_stat)(buf, sb));
|
||||
return(stat(buf, sb));
|
||||
}
|
||||
|
||||
static Char *
|
||||
g_strchr(str, ch)
|
||||
Char *str;
|
||||
int ch;
|
||||
{
|
||||
do {
|
||||
if (*str == ch)
|
||||
return (str);
|
||||
} while (*str++);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
static Char *
|
||||
g_strcat(dst, src)
|
||||
Char *dst;
|
||||
const Char* src;
|
||||
{
|
||||
Char *sdst = dst;
|
||||
|
||||
while (*dst++)
|
||||
continue;
|
||||
--dst;
|
||||
while((*dst++ = *src++) != EOS)
|
||||
continue;
|
||||
|
||||
return (sdst);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
g_Ctoc(str, buf)
|
||||
register const Char *str;
|
||||
char *buf;
|
||||
{
|
||||
register char *dc;
|
||||
|
||||
for (dc = buf; (*dc++ = *str++) != EOS;)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
qprintf(str, s)
|
||||
const char *str;
|
||||
register Char *s;
|
||||
{
|
||||
register Char *p;
|
||||
|
||||
(void)printf("%s:\n", str);
|
||||
for (p = s; *p; p++)
|
||||
(void)printf("%c", CHAR(*p));
|
||||
(void)printf("\n");
|
||||
for (p = s; *p; p++)
|
||||
(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
|
||||
(void)printf("\n");
|
||||
for (p = s; *p; p++)
|
||||
(void)printf("%c", ismeta(*p) ? '_' : ' ');
|
||||
(void)printf("\n");
|
||||
}
|
||||
#endif
|
89
lib/libftp/utils/glob.h
Normal file
89
lib/libftp/utils/glob.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Guido van Rossum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)glob.h 8.1 (Berkeley) 6/2/93
|
||||
*/
|
||||
|
||||
#ifndef _GLOB_H_
|
||||
#define _GLOB_H_
|
||||
|
||||
|
||||
#include <cdefs.h>
|
||||
|
||||
struct stat;
|
||||
typedef struct {
|
||||
int gl_pathc; /* Count of total paths so far. */
|
||||
int gl_matchc; /* Count of paths matching pattern. */
|
||||
int gl_offs; /* Reserved at beginning of gl_pathv. */
|
||||
int gl_flags; /* Copy of flags parameter to glob. */
|
||||
char **gl_pathv; /* List of paths matching pattern. */
|
||||
/* Copy of errfunc parameter to glob. */
|
||||
int (*gl_errfunc) __P((const char *, int));
|
||||
|
||||
/*
|
||||
* Alternate filesystem access methods for glob; replacement
|
||||
* versions of closedir(3), readdir(3), opendir(3), stat(2)
|
||||
* and lstat(2).
|
||||
*/
|
||||
void (*gl_closedir) __P((void *));
|
||||
struct dirent *(*gl_readdir) __P((void *));
|
||||
void *(*gl_opendir) __P((const char *));
|
||||
int (*gl_lstat) __P((const char *, struct stat *));
|
||||
int (*gl_stat) __P((const char *, struct stat *));
|
||||
} glob_t;
|
||||
|
||||
#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
|
||||
#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
|
||||
#define GLOB_ERR 0x0004 /* Return on error. */
|
||||
#define GLOB_MARK 0x0008 /* Append / to matching directories. */
|
||||
#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
|
||||
#define GLOB_NOSORT 0x0020 /* Don't sort. */
|
||||
|
||||
#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
|
||||
#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
|
||||
#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
|
||||
#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
|
||||
#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
|
||||
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
|
||||
|
||||
#define GLOB_NOSPACE (-1) /* Malloc call failed. */
|
||||
#define GLOB_ABEND (-2) /* Unignored error. */
|
||||
|
||||
__BEGIN_DECLS
|
||||
int glob __P((const char *, int, int (*)(const char *, int), glob_t *));
|
||||
void globfree __P((glob_t *));
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_GLOB_H_ */
|
92
lib/libftp/utils/mirror.c
Normal file
92
lib/libftp/utils/mirror.c
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
/* Mirror directrory structure to another host */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/stat.h>
|
||||
#include <syslog.h>
|
||||
#include <FtpLibrary.h>
|
||||
|
||||
/* Usage: mirror <local_dir> <host> <user> <passwd> <remote_dir> */
|
||||
FTP *ftp;
|
||||
|
||||
main(int a,char **b)
|
||||
{
|
||||
|
||||
#define LOCAL_DIR b[1]
|
||||
#define HOST b[2]
|
||||
#define USER b[3]
|
||||
#define PASSWD b[4]
|
||||
#define REMOTE_DIR b[5]
|
||||
|
||||
if ( a < 5 )
|
||||
quit("Usage: mirror <local_dir> <host> <user> <passwd> <remote_dir>");
|
||||
|
||||
|
||||
FtplibDebug(yes);
|
||||
FtpLogin(&ftp,HOST,USER,PASSWD,NULL);
|
||||
FtpChdir(ftp,REMOTE_DIR);
|
||||
FtpBinary(ftp);
|
||||
doit(LOCAL_DIR);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
doit(char *dirname)
|
||||
{
|
||||
DIR *dp;
|
||||
struct direct *de;
|
||||
char n[256],fn[256];
|
||||
struct stat st;
|
||||
|
||||
|
||||
if ( (dp=opendir(dirname)) == NULL )
|
||||
{
|
||||
log(dirname);
|
||||
return;
|
||||
}
|
||||
|
||||
while ( (de = readdir(dp)) != NULL )
|
||||
{
|
||||
if ( de -> d_name[0] == '.' )
|
||||
continue;
|
||||
|
||||
sprintf(fn,"%s/%s",dirname,de->d_name);
|
||||
|
||||
if ( stat(fn,&st) != 0 ) {
|
||||
log(fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( S_ISDIR (st.st_mode) )
|
||||
{
|
||||
FtpCommand(ftp,"MKD %s",fn,0,EOF); /* Ignore errors (0,EOF) */
|
||||
doit(fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( st.st_size != FtpSize(ftp,fn))
|
||||
|
||||
FtpPut(ftp,fn,fn);
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
quit(char *s)
|
||||
{
|
||||
log(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
log(char *s)
|
||||
{
|
||||
perror(s);
|
||||
}
|
||||
|
||||
|
||||
|
961
lib/libftp/utils/readline.c
Normal file
961
lib/libftp/utils/readline.c
Normal file
@ -0,0 +1,961 @@
|
||||
#ifndef lint
|
||||
static char *RCSid = "$Id: readline.c%v 3.50.1.9 1993/08/05 05:38:59 woo Exp $";
|
||||
#endif
|
||||
|
||||
|
||||
/* GNUPLOT - readline.c */
|
||||
/*
|
||||
* Copyright (C) 1986 - 1993 Thomas Williams, Colin Kelley
|
||||
*
|
||||
* Permission to use, copy, and distribute this software and its
|
||||
* documentation for any purpose with or without fee is hereby granted,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
*
|
||||
* Permission to modify the software is granted, but not the right to
|
||||
* distribute the modified code. Modifications are to be distributed
|
||||
* as patches to released version.
|
||||
*
|
||||
* This software is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* AUTHORS
|
||||
*
|
||||
* Original Software:
|
||||
* Tom Tkacik
|
||||
*
|
||||
* Msdos port and some enhancements:
|
||||
* Gershon Elber and many others.
|
||||
*
|
||||
* There is a mailing list for gnuplot users. Note, however, that the
|
||||
* newsgroup
|
||||
* comp.graphics.gnuplot
|
||||
* is identical to the mailing list (they
|
||||
* both carry the same set of messages). We prefer that you read the
|
||||
* messages through that newsgroup, to subscribing to the mailing list.
|
||||
* (If you can read that newsgroup, and are already on the mailing list,
|
||||
* please send a message info-gnuplot-request@dartmouth.edu, asking to be
|
||||
* removed from the mailing list.)
|
||||
*
|
||||
* The address for mailing to list members is
|
||||
* info-gnuplot@dartmouth.edu
|
||||
* and for mailing administrative requests is
|
||||
* info-gnuplot-request@dartmouth.edu
|
||||
* The mailing list for bug reports is
|
||||
* bug-gnuplot@dartmouth.edu
|
||||
* The list of those interested in beta-test versions is
|
||||
* info-gnuplot-beta@dartmouth.edu
|
||||
*/
|
||||
|
||||
#ifdef READLINE
|
||||
#ifdef ATARI
|
||||
#include "plot.h"
|
||||
#endif
|
||||
#ifdef _WINDOWS
|
||||
#define _Windows
|
||||
#endif
|
||||
|
||||
/* a small portable version of GNU's readline */
|
||||
/* this is not the BASH or GNU EMACS version of READLINE due to Copyleft
|
||||
restrictions */
|
||||
/* do not need any terminal capabilities except backspace, */
|
||||
/* and space overwrites a character */
|
||||
|
||||
/* NANO-EMACS line editing facility */
|
||||
/* printable characters print as themselves (insert not overwrite) */
|
||||
/* ^A moves to the beginning of the line */
|
||||
/* ^B moves back a single character */
|
||||
/* ^E moves to the end of the line */
|
||||
/* ^F moves forward a single character */
|
||||
/* ^K kills from current position to the end of line */
|
||||
/* ^P moves back through history */
|
||||
/* ^N moves forward through history */
|
||||
/* ^H and DEL delete the previous character */
|
||||
/* ^D deletes the current character, or EOF if line is empty */
|
||||
/* ^L/^R redraw line in case it gets trashed */
|
||||
/* ^U kills the entire line */
|
||||
/* ^W kills last word */
|
||||
/* LF and CR return the entire line regardless of the cursor postition */
|
||||
/* EOF with an empty line returns (char *)NULL */
|
||||
|
||||
/* all other characters are ignored */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
|
||||
|
||||
/*
|
||||
* Set up structures using the proper include file
|
||||
*/
|
||||
#if defined(_IBMR2) || defined(alliant)
|
||||
#define SGTTY
|
||||
#endif
|
||||
|
||||
/* submitted by Francois.Dagorn@cicb.fr */
|
||||
#ifdef SGTTY
|
||||
#include <sgtty.h>
|
||||
static struct sgttyb orig_termio, rl_termio;
|
||||
/* define terminal control characters */
|
||||
static struct tchars s_tchars;
|
||||
#define VERASE 0
|
||||
#define VEOF 1
|
||||
#define VKILL 2
|
||||
#ifdef TIOCGLTC /* available only with the 'new' line discipline */
|
||||
static struct ltchars s_ltchars;
|
||||
#define VWERASE 3
|
||||
#define VREPRINT 4
|
||||
#define VSUSP 5
|
||||
#endif /* TIOCGLTC */
|
||||
#define NCCS 6
|
||||
|
||||
#else /* SGTTY */
|
||||
|
||||
/* SIGTSTP defines job control */
|
||||
/* if there is job control then we need termios.h instead of termio.h */
|
||||
/* (Are there any systems with job control that use termio.h? I hope not.) */
|
||||
#ifdef SIGTSTP
|
||||
#define TERMIOS
|
||||
#include <termios.h>
|
||||
/* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
|
||||
#ifdef ISC22
|
||||
#ifndef ONOCR /* taken from sys/termio.h */
|
||||
#define ONOCR 0000020 /* true at least for ISC 2.2 */
|
||||
#endif
|
||||
#ifndef IUCLC
|
||||
#define IUCLC 0001000
|
||||
#endif
|
||||
#endif /* ISC22 */
|
||||
|
||||
static struct termios orig_termio, rl_termio;
|
||||
#else
|
||||
#include <termio.h>
|
||||
static struct termio orig_termio, rl_termio;
|
||||
/* termio defines NCC instead of NCCS */
|
||||
#define NCCS NCC
|
||||
#endif /* SIGTSTP */
|
||||
#endif /* SGTTY */
|
||||
|
||||
/* ULTRIX defines VRPRNT instead of VREPRINT */
|
||||
#ifdef VRPRNT
|
||||
#define VREPRINT VRPRNT
|
||||
#endif
|
||||
|
||||
/* define characters to use with our input character handler */
|
||||
static char term_chars[NCCS];
|
||||
|
||||
static int term_set = 0; /* =1 if rl_termio set */
|
||||
|
||||
#define special_getc() ansi_getc()
|
||||
static char ansi_getc();
|
||||
|
||||
#else /* !MSDOS && !ATARI && !_Windows */
|
||||
|
||||
#ifdef _Windows
|
||||
#include <windows.h>
|
||||
#include "win/wtext.h"
|
||||
#include "win/wgnuplib.h"
|
||||
extern TW textwin;
|
||||
#define TEXTUSER 0xf1
|
||||
#define TEXTGNUPLOT 0xf0
|
||||
#define special_getc() msdos_getch()
|
||||
static char msdos_getch();
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS) || defined(DOS386)
|
||||
/* MSDOS specific stuff */
|
||||
#ifdef DJGPP
|
||||
#include <pc.h>
|
||||
#endif
|
||||
#ifdef __EMX__
|
||||
#include <conio.h>
|
||||
#endif
|
||||
#define special_getc() msdos_getch()
|
||||
static char msdos_getch();
|
||||
#endif /* MSDOS */
|
||||
|
||||
#ifdef ATARI
|
||||
#include <stdlib.h>
|
||||
#ifdef __PUREC__
|
||||
#include <tos.h>
|
||||
#else
|
||||
#include <osbind.h>
|
||||
#endif
|
||||
#define special_getc() tos_getch()
|
||||
static char tos_getch();
|
||||
#endif
|
||||
|
||||
#endif /* !MSDOS && !ATARI && !_Windows */
|
||||
|
||||
#if !defined(ATARI)
|
||||
/* is it <string.h> or <strings.h>? just declare what we need */
|
||||
extern int strlen();
|
||||
extern char *strcpy();
|
||||
#endif
|
||||
#define alloc malloc
|
||||
extern char *alloc(); /* we'll use the safe malloc from misc.c */
|
||||
|
||||
#define MAXBUF 1024
|
||||
#define BACKSPACE 0x08 /* ^H */
|
||||
#define SPACE ' '
|
||||
|
||||
struct hist {
|
||||
char *line;
|
||||
struct hist *prev;
|
||||
struct hist *next;
|
||||
};
|
||||
|
||||
static struct hist *history = NULL; /* no history yet */
|
||||
static struct hist *cur_entry = NULL;
|
||||
|
||||
static char cur_line[MAXBUF]; /* current contents of the line */
|
||||
static int cur_pos = 0; /* current position of the cursor */
|
||||
static int max_pos = 0; /* maximum character position */
|
||||
|
||||
|
||||
void add_history();
|
||||
static void fix_line();
|
||||
static void redraw_line();
|
||||
static void clear_line();
|
||||
static void clear_eoline();
|
||||
static void copy_line();
|
||||
static void set_termio();
|
||||
void reset_termio();
|
||||
|
||||
/* user_putc and user_puts should be used in the place of
|
||||
* fputc(ch,stderr) and fputs(str,stderr) for all output
|
||||
* of user typed characters. This allows MS-Windows to
|
||||
* display user input in a different color. */
|
||||
int
|
||||
user_putc(ch)
|
||||
int ch;
|
||||
{
|
||||
int rv;
|
||||
#ifdef _Windows
|
||||
TextAttr(&textwin,TEXTUSER);
|
||||
#endif
|
||||
rv = fputc(ch, stderr);
|
||||
#ifdef _Windows
|
||||
TextAttr(&textwin,TEXTGNUPLOT);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
user_puts(str)
|
||||
char *str;
|
||||
{
|
||||
int rv;
|
||||
#ifdef _Windows
|
||||
TextAttr(&textwin,TEXTUSER);
|
||||
#endif
|
||||
rv = fputs(str, stderr);
|
||||
#ifdef _Windows
|
||||
TextAttr(&textwin,TEXTGNUPLOT);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* This function provides a centralized non-destructive backspace capability */
|
||||
/* M. Castro */
|
||||
|
||||
backspace()
|
||||
{
|
||||
user_putc(BACKSPACE);
|
||||
}
|
||||
|
||||
char *
|
||||
readline(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
|
||||
unsigned char cur_char;
|
||||
char *new_line;
|
||||
/* unsigned char *new_line; */
|
||||
|
||||
/* set the termio so we can do our own input processing */
|
||||
set_termio();
|
||||
|
||||
/* print the prompt */
|
||||
fputs(prompt, stderr);
|
||||
cur_line[0] = '\0';
|
||||
cur_pos = 0;
|
||||
max_pos = 0;
|
||||
cur_entry = NULL;
|
||||
|
||||
/* get characters */
|
||||
for(;;) {
|
||||
cur_char = special_getc();
|
||||
#ifdef OS2
|
||||
/* for emx: remap scan codes for cursor keys */
|
||||
if( cur_char == 0 ) {
|
||||
cur_char = getc(stdin);
|
||||
switch( cur_char){
|
||||
case 75: /* left, map to ^B */
|
||||
cur_char=2;
|
||||
break ;
|
||||
case 77: /* right, map to ^F */
|
||||
cur_char=6;
|
||||
break ;
|
||||
case 115: /* ctrl left */
|
||||
case 71: /* home, map to ^A */
|
||||
cur_char=1;
|
||||
break ;
|
||||
case 116: /* ctrl right */
|
||||
case 79: /* end, map to ^E */
|
||||
cur_char=5;
|
||||
break ;
|
||||
case 72: /* up, map to ^P */
|
||||
cur_char=16;
|
||||
break ;
|
||||
case 80: /* down, map to ^N */
|
||||
cur_char=14;
|
||||
break ;
|
||||
case 83: /* delete, map to ^D */
|
||||
cur_char=4;
|
||||
break ;
|
||||
default: /* ignore */
|
||||
cur_char=0;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
#endif /*OS2*/
|
||||
if((isprint(cur_char)
|
||||
#if defined(ATARI) || defined(_Windows) || defined(MSDOS) || defined(DOS386)
|
||||
/* this should be used for all 8bit ASCII machines, I guess */
|
||||
|| ((unsigned char)cur_char > 0x7f)
|
||||
#endif
|
||||
)&& max_pos<MAXBUF-1) {
|
||||
int i;
|
||||
for(i=max_pos; i>cur_pos; i--) {
|
||||
cur_line[i] = cur_line[i-1];
|
||||
}
|
||||
user_putc(cur_char);
|
||||
cur_line[cur_pos] = cur_char;
|
||||
cur_pos += 1;
|
||||
max_pos += 1;
|
||||
if (cur_pos < max_pos)
|
||||
fix_line();
|
||||
cur_line[max_pos] = '\0';
|
||||
|
||||
/* else interpret unix terminal driver characters */
|
||||
#ifdef VERASE
|
||||
} else if(cur_char == term_chars[VERASE] ){ /* DEL? */
|
||||
if(cur_pos > 0) {
|
||||
int i;
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
cur_line[i] = cur_line[i+1];
|
||||
max_pos -= 1;
|
||||
fix_line();
|
||||
}
|
||||
#endif /* VERASE */
|
||||
#ifdef VEOF
|
||||
} else if(cur_char == term_chars[VEOF] ){ /* ^D? */
|
||||
if(max_pos == 0) {
|
||||
reset_termio();
|
||||
return((char *)NULL);
|
||||
}
|
||||
if((cur_pos < max_pos)&&(cur_char == 004)) { /* ^D */
|
||||
int i;
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
cur_line[i] = cur_line[i+1];
|
||||
max_pos -= 1;
|
||||
fix_line();
|
||||
}
|
||||
#endif /* VEOF */
|
||||
#ifdef VKILL
|
||||
} else if(cur_char == term_chars[VKILL] ){ /* ^U? */
|
||||
clear_line(prompt);
|
||||
#endif /* VKILL */
|
||||
#ifdef VWERASE
|
||||
} else if(cur_char == term_chars[VWERASE] ){ /* ^W? */
|
||||
while((cur_pos > 0) &&
|
||||
(cur_line[cur_pos-1] == SPACE)) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
}
|
||||
while((cur_pos > 0) &&
|
||||
(cur_line[cur_pos-1] != SPACE)) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
}
|
||||
clear_eoline();
|
||||
max_pos = cur_pos;
|
||||
#endif /* VWERASE */
|
||||
#ifdef VREPRINT
|
||||
} else if(cur_char == term_chars[VREPRINT] ){ /* ^R? */
|
||||
putc('\n',stderr); /* go to a fresh line */
|
||||
redraw_line(prompt);
|
||||
#endif /* VREPRINT */
|
||||
#ifdef VSUSP
|
||||
} else if(cur_char == term_chars[VSUSP]) {
|
||||
reset_termio();
|
||||
kill(0, SIGTSTP);
|
||||
|
||||
/* process stops here */
|
||||
|
||||
set_termio();
|
||||
/* print the prompt */
|
||||
redraw_line(prompt);
|
||||
#endif /* VSUSP */
|
||||
} else {
|
||||
/* do normal editing commands */
|
||||
/* some of these are also done above */
|
||||
int i;
|
||||
switch(cur_char) {
|
||||
case EOF:
|
||||
reset_termio();
|
||||
return((char *)NULL);
|
||||
case 001: /* ^A */
|
||||
while(cur_pos > 0) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
}
|
||||
break;
|
||||
case 002: /* ^B */
|
||||
if(cur_pos > 0) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
}
|
||||
break;
|
||||
case 005: /* ^E */
|
||||
while(cur_pos < max_pos) {
|
||||
user_putc(cur_line[cur_pos]);
|
||||
cur_pos += 1;
|
||||
}
|
||||
break;
|
||||
case 006: /* ^F */
|
||||
if(cur_pos < max_pos) {
|
||||
user_putc(cur_line[cur_pos]);
|
||||
cur_pos += 1;
|
||||
}
|
||||
break;
|
||||
case 013: /* ^K */
|
||||
clear_eoline();
|
||||
max_pos = cur_pos;
|
||||
break;
|
||||
case 020: /* ^P */
|
||||
if(history != NULL) {
|
||||
if(cur_entry == NULL) {
|
||||
cur_entry = history;
|
||||
clear_line(prompt);
|
||||
copy_line(cur_entry->line);
|
||||
} else if(cur_entry->prev != NULL) {
|
||||
cur_entry = cur_entry->prev;
|
||||
clear_line(prompt);
|
||||
copy_line(cur_entry->line);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 016: /* ^N */
|
||||
if(cur_entry != NULL) {
|
||||
cur_entry = cur_entry->next;
|
||||
clear_line(prompt);
|
||||
if(cur_entry != NULL)
|
||||
copy_line(cur_entry->line);
|
||||
else
|
||||
cur_pos = max_pos = 0;
|
||||
}
|
||||
break;
|
||||
case 014: /* ^L */
|
||||
case 022: /* ^R */
|
||||
putc('\n',stderr); /* go to a fresh line */
|
||||
redraw_line(prompt);
|
||||
break;
|
||||
case 0177: /* DEL */
|
||||
case 010: /* ^H */
|
||||
if(cur_pos > 0) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
cur_line[i] = cur_line[i+1];
|
||||
max_pos -= 1;
|
||||
fix_line();
|
||||
}
|
||||
break;
|
||||
case 004: /* ^D */
|
||||
if(max_pos == 0) {
|
||||
reset_termio();
|
||||
return((char *)NULL);
|
||||
}
|
||||
if(cur_pos < max_pos) {
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
cur_line[i] = cur_line[i+1];
|
||||
max_pos -= 1;
|
||||
fix_line();
|
||||
}
|
||||
break;
|
||||
case 025: /* ^U */
|
||||
clear_line(prompt);
|
||||
break;
|
||||
case 027: /* ^W */
|
||||
while((cur_pos > 0) &&
|
||||
(cur_line[cur_pos-1] == SPACE)) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
}
|
||||
while((cur_pos > 0) &&
|
||||
(cur_line[cur_pos-1] != SPACE)) {
|
||||
cur_pos -= 1;
|
||||
backspace();
|
||||
}
|
||||
clear_eoline();
|
||||
max_pos = cur_pos;
|
||||
break;
|
||||
case '\n': /* ^J */
|
||||
case '\r': /* ^M */
|
||||
cur_line[max_pos+1] = '\0';
|
||||
putc('\n', stderr);
|
||||
new_line = (char *)alloc((unsigned long) (strlen(cur_line)+1), "history");
|
||||
strcpy(new_line,cur_line);
|
||||
reset_termio();
|
||||
return(new_line);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fix up the line from cur_pos to max_pos */
|
||||
/* do not need any terminal capabilities except backspace, */
|
||||
/* and space overwrites a character */
|
||||
static void
|
||||
fix_line()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* write tail of string */
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
user_putc(cur_line[i]);
|
||||
|
||||
/* write a space at the end of the line in case we deleted one */
|
||||
user_putc(SPACE);
|
||||
|
||||
/* backup to original position */
|
||||
for(i=max_pos+1; i>cur_pos; i--)
|
||||
backspace();
|
||||
|
||||
}
|
||||
|
||||
/* redraw the entire line, putting the cursor where it belongs */
|
||||
static void
|
||||
redraw_line(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
int i;
|
||||
|
||||
fputs(prompt, stderr);
|
||||
user_puts(cur_line);
|
||||
|
||||
/* put the cursor where it belongs */
|
||||
for(i=max_pos; i>cur_pos; i--)
|
||||
backspace();
|
||||
}
|
||||
|
||||
/* clear cur_line and the screen line */
|
||||
static void
|
||||
clear_line(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<max_pos; i++)
|
||||
cur_line[i] = '\0';
|
||||
|
||||
for(i=cur_pos; i>0; i--)
|
||||
backspace();
|
||||
|
||||
for(i=0; i<max_pos; i++)
|
||||
putc(SPACE, stderr);
|
||||
|
||||
putc('\r', stderr);
|
||||
fputs(prompt, stderr);
|
||||
|
||||
cur_pos = 0;
|
||||
max_pos = 0;
|
||||
}
|
||||
|
||||
/* clear to end of line and the screen end of line */
|
||||
static void
|
||||
clear_eoline(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
int i;
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
cur_line[i] = '\0';
|
||||
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
putc(SPACE, stderr);
|
||||
for(i=cur_pos; i<max_pos; i++)
|
||||
backspace();
|
||||
}
|
||||
|
||||
/* copy line to cur_line, draw it and set cur_pos and max_pos */
|
||||
static void
|
||||
copy_line(line)
|
||||
char *line;
|
||||
{
|
||||
strcpy(cur_line, line);
|
||||
user_puts(cur_line);
|
||||
cur_pos = max_pos = strlen(cur_line);
|
||||
}
|
||||
|
||||
/* add line to the history */
|
||||
void
|
||||
add_history(line)
|
||||
char *line;
|
||||
{
|
||||
struct hist *entry;
|
||||
entry = (struct hist *)alloc((unsigned long)sizeof(struct hist),"history");
|
||||
entry->line = alloc((unsigned long)(strlen(line)+1),"history");
|
||||
strcpy(entry->line, line);
|
||||
|
||||
entry->prev = history;
|
||||
entry->next = NULL;
|
||||
if(history != NULL) {
|
||||
history->next = entry;
|
||||
}
|
||||
history = entry;
|
||||
}
|
||||
|
||||
|
||||
/* Convert ANSI arrow keys to control characters */
|
||||
static char
|
||||
ansi_getc()
|
||||
{
|
||||
char c = getc(stdin);
|
||||
if (c == 033) {
|
||||
c = getc(stdin); /* check for CSI */
|
||||
if (c == '[') {
|
||||
c = getc(stdin); /* get command character */
|
||||
switch (c) {
|
||||
case 'D': /* left arrow key */
|
||||
c = 002;
|
||||
break;
|
||||
case 'C': /* right arrow key */
|
||||
c = 006;
|
||||
break;
|
||||
case 'A': /* up arrow key */
|
||||
c = 020;
|
||||
break;
|
||||
case 'B': /* down arrow key */
|
||||
c = 016;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
#if defined(MSDOS) || defined(_Windows) || defined(DOS386)
|
||||
|
||||
/* Convert Arrow keystrokes to Control characters: */
|
||||
static char
|
||||
msdos_getch()
|
||||
{
|
||||
#ifdef DJGPP
|
||||
char c;
|
||||
int ch = getkey();
|
||||
c = (ch & 0xff00) ? 0 : ch & 0xff;
|
||||
#else
|
||||
char c = getch();
|
||||
#endif
|
||||
|
||||
if (c == 0) {
|
||||
#ifdef DJGPP
|
||||
c = ch & 0xff;
|
||||
#else
|
||||
c = getch(); /* Get the extended code. */
|
||||
#endif
|
||||
switch (c) {
|
||||
case 75: /* Left Arrow. */
|
||||
c = 002;
|
||||
break;
|
||||
case 77: /* Right Arrow. */
|
||||
c = 006;
|
||||
break;
|
||||
case 72: /* Up Arrow. */
|
||||
c = 020;
|
||||
break;
|
||||
case 80: /* Down Arrow. */
|
||||
c = 016;
|
||||
break;
|
||||
case 115: /* Ctl Left Arrow. */
|
||||
case 71: /* Home */
|
||||
c = 001;
|
||||
break;
|
||||
case 116: /* Ctl Right Arrow. */
|
||||
case 79: /* End */
|
||||
c = 005;
|
||||
break;
|
||||
case 83: /* Delete */
|
||||
c = 004;
|
||||
break;
|
||||
default:
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (c == 033) { /* ESC */
|
||||
c = 025;
|
||||
}
|
||||
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif /* MSDOS */
|
||||
|
||||
#ifdef ATARI
|
||||
|
||||
/* Convert Arrow keystrokes to Control characters: TOS version */
|
||||
|
||||
/* the volatile could be necessary to keep gcc from reordering
|
||||
the two Super calls
|
||||
*/
|
||||
#define CONTERM ((/*volatile*/ char *)0x484L)
|
||||
|
||||
static void
|
||||
remove_conterm()
|
||||
{
|
||||
void *ssp=(void*)Super(0L);
|
||||
*CONTERM &= ~0x8;
|
||||
Super(ssp);
|
||||
}
|
||||
|
||||
static char
|
||||
tos_getch()
|
||||
{
|
||||
long rawkey;
|
||||
char c;
|
||||
int scan_code;
|
||||
void *ssp;
|
||||
static int init = 1;
|
||||
static int in_help = 0;
|
||||
|
||||
if (in_help) {
|
||||
switch(in_help) {
|
||||
case 1:
|
||||
case 5: in_help++; return 'e';
|
||||
case 2:
|
||||
case 6: in_help++; return 'l';
|
||||
case 3:
|
||||
case 7: in_help++; return 'p';
|
||||
case 4: in_help = 0; return 0x0d;
|
||||
case 8: in_help = 0; return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if (init) {
|
||||
ssp = (void*)Super(0L);
|
||||
if( !(*CONTERM & 0x8) ) {
|
||||
*CONTERM |= 0x8;
|
||||
} else {
|
||||
init=0;
|
||||
}
|
||||
(void)Super(ssp);
|
||||
if( init ) {
|
||||
atexit(remove_conterm);
|
||||
init = 0;
|
||||
}
|
||||
}
|
||||
|
||||
(void)Cursconf(1, 0); /* cursor on */
|
||||
rawkey = Cnecin();
|
||||
c = (char)rawkey;
|
||||
scan_code= ((int)(rawkey>>16)) & 0xff; /* get the scancode */
|
||||
if( rawkey&0x07000000 ) scan_code |= 0x80; /* shift or control */
|
||||
|
||||
switch (scan_code) {
|
||||
case 0x62: /* HELP */
|
||||
if (max_pos==0) {
|
||||
in_help = 1;
|
||||
return 'h';
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case 0xe2: /* shift HELP */
|
||||
if (max_pos==0) {
|
||||
in_help = 5;
|
||||
return 'h';
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case 0x48: /* Up Arrow */
|
||||
return 0x10; /* ^P */
|
||||
case 0x50: /* Down Arrow */
|
||||
return 0x0e; /* ^N */
|
||||
case 0x4b: /* Left Arrow */
|
||||
return 0x02; /* ^B */
|
||||
case 0x4d: /* Right Arrow */
|
||||
return 0x06; /* ^F */
|
||||
case 0xcb: /* Shift Left Arrow */
|
||||
case 0xf3: /* Ctrl Left Arrow (TOS-bug ?) */
|
||||
case 0x47: /* Home */
|
||||
return 0x01; /* ^A */
|
||||
case 0xcd: /* Shift Right Arrow */
|
||||
case 0xf4: /* Ctrl Right Arrow (TOS-bug ?) */
|
||||
case 0xc7: /* Shift Home */
|
||||
case 0xf7: /* Crtl Home */
|
||||
return 0x05; /* ^E */
|
||||
case 0x61: /* Undo - redraw line */
|
||||
return 0x0c; /* ^L */
|
||||
default:
|
||||
if (c == 0x1b) return 0x15; /* ESC becomes ^U */
|
||||
if (c == 0x7f) return 0x04; /* Del becomes ^D */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif /* ATARI */
|
||||
|
||||
/* set termio so we can do our own input processing */
|
||||
static void
|
||||
set_termio()
|
||||
{
|
||||
#if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
|
||||
/* set termio so we can do our own input processing */
|
||||
/* and save the old terminal modes so we can reset them later */
|
||||
if(term_set == 0) {
|
||||
/*
|
||||
* Get terminal modes.
|
||||
*/
|
||||
#ifdef SGTTY
|
||||
ioctl(0, TIOCGETP, &orig_termio);
|
||||
#else /* SGTTY */
|
||||
#ifdef TERMIOS
|
||||
#ifdef TCGETS
|
||||
ioctl(0, TCGETS, &orig_termio);
|
||||
#else
|
||||
tcgetattr(0, &orig_termio);
|
||||
#endif /* TCGETS */
|
||||
#else
|
||||
ioctl(0, TCGETA, &orig_termio);
|
||||
#endif /* TERMIOS */
|
||||
#endif /* SGTTY */
|
||||
|
||||
/*
|
||||
* Save terminal modes
|
||||
*/
|
||||
rl_termio = orig_termio;
|
||||
|
||||
/*
|
||||
* Set the modes to the way we want them
|
||||
* and save our input special characters
|
||||
*/
|
||||
#ifdef SGTTY
|
||||
rl_termio.sg_flags |= CBREAK;
|
||||
rl_termio.sg_flags &= ~(ECHO|XTABS);
|
||||
ioctl(0, TIOCSETN, &rl_termio);
|
||||
|
||||
ioctl(0, TIOCGETC, &s_tchars);
|
||||
term_chars[VERASE] = orig_termio.sg_erase;
|
||||
term_chars[VEOF] = s_tchars.t_eofc;
|
||||
term_chars[VKILL] = orig_termio.sg_kill;
|
||||
#ifdef TIOCGLTC
|
||||
ioctl(0, TIOCGLTC, &s_ltchars);
|
||||
term_chars[VWERASE] = s_ltchars.t_werasc;
|
||||
term_chars[VREPRINT] = s_ltchars.t_rprntc;
|
||||
term_chars[VSUSP] = s_ltchars.t_suspc;
|
||||
|
||||
/* disable suspending process on ^Z */
|
||||
s_ltchars.t_suspc = 0;
|
||||
ioctl(0, TIOCSLTC, &s_ltchars);
|
||||
#endif /* TIOCGLTC */
|
||||
#else /* SGTTY */
|
||||
#ifdef IUCLC
|
||||
rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IUCLC|IXON|IXOFF);
|
||||
#else
|
||||
rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IXON|IXOFF);
|
||||
#endif
|
||||
rl_termio.c_iflag |= (IGNBRK|IGNPAR);
|
||||
|
||||
/* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
|
||||
|
||||
rl_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
|
||||
#ifdef OS2
|
||||
/* for emx: remove default terminal processing */
|
||||
rl_termio.c_lflag &= ~(IDEFAULT);
|
||||
#endif /* OS2 */
|
||||
rl_termio.c_lflag |= (ISIG);
|
||||
rl_termio.c_cc[VMIN] = 1;
|
||||
rl_termio.c_cc[VTIME] = 0;
|
||||
|
||||
#ifndef VWERASE
|
||||
#define VWERASE 3
|
||||
#endif
|
||||
term_chars[VERASE] = orig_termio.c_cc[VERASE];
|
||||
term_chars[VEOF] = orig_termio.c_cc[VEOF];
|
||||
term_chars[VKILL] = orig_termio.c_cc[VKILL];
|
||||
#ifdef TERMIOS
|
||||
term_chars[VWERASE] = orig_termio.c_cc[VWERASE];
|
||||
#ifdef VREPRINT
|
||||
term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
|
||||
#else
|
||||
#ifdef VRPRNT
|
||||
term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
|
||||
#endif
|
||||
#endif
|
||||
term_chars[VSUSP] = orig_termio.c_cc[VSUSP];
|
||||
|
||||
/* disable suspending process on ^Z */
|
||||
rl_termio.c_cc[VSUSP] = 0;
|
||||
#endif /* TERMIOS */
|
||||
#endif /* SGTTY */
|
||||
|
||||
/*
|
||||
* Set the new terminal modes.
|
||||
*/
|
||||
#ifdef SGTTY
|
||||
ioctl(0, TIOCSLTC, &s_ltchars);
|
||||
#else
|
||||
#ifdef TERMIOS
|
||||
#ifdef TCSETSW
|
||||
ioctl(0, TCSETSW, &rl_termio);
|
||||
#else
|
||||
tcsetattr(0, TCSADRAIN, &rl_termio);
|
||||
#endif /* TCSETSW */
|
||||
#else
|
||||
ioctl(0, TCSETAW, &rl_termio);
|
||||
#endif /* TERMIOS */
|
||||
#endif /* SGTTY */
|
||||
term_set = 1;
|
||||
}
|
||||
#endif /* !MSDOS && !ATARI && !defined(_Windows) */
|
||||
}
|
||||
|
||||
void
|
||||
reset_termio()
|
||||
{
|
||||
#if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
|
||||
/* reset saved terminal modes */
|
||||
if(term_set == 1) {
|
||||
#ifdef SGTTY
|
||||
ioctl(0, TIOCSETN, &orig_termio);
|
||||
#ifdef TIOCGLTC
|
||||
/* enable suspending process on ^Z */
|
||||
s_ltchars.t_suspc = term_chars[VSUSP];
|
||||
ioctl(0, TIOCSLTC, &s_ltchars);
|
||||
#endif /* TIOCGLTC */
|
||||
#else /* SGTTY */
|
||||
#ifdef TERMIOS
|
||||
#ifdef TCSETSW
|
||||
ioctl(0, TCSETSW, &orig_termio);
|
||||
#else
|
||||
tcsetattr(0, TCSADRAIN, &orig_termio);
|
||||
#endif /* TCSETSW */
|
||||
#else
|
||||
ioctl(0, TCSETAW, &orig_termio);
|
||||
#endif /* TERMIOS */
|
||||
#endif /* SGTTY */
|
||||
term_set = 0;
|
||||
}
|
||||
#endif /* !MSDOS && !ATARI && !_Windows */
|
||||
}
|
||||
#endif /* READLINE */
|
824
lib/libftp/utils/uftp.c
Normal file
824
lib/libftp/utils/uftp.c
Normal file
@ -0,0 +1,824 @@
|
||||
/* File Transfer Protocol Toolkit based on libftp */
|
||||
|
||||
#include "uftp.h"
|
||||
#include <varargs.h>
|
||||
|
||||
|
||||
FTP *ftp[NFRAMES];
|
||||
LINKINFO iftp[NFRAMES];
|
||||
int frame=0;
|
||||
|
||||
|
||||
int status;
|
||||
jmp_buf start;
|
||||
int lastcmd=0;
|
||||
int glassmode=0;
|
||||
int trymode=1;
|
||||
int restmode=1;
|
||||
int hashmode=0;
|
||||
int sleeptime=30;
|
||||
time_t noopinterval=0;
|
||||
time_t nooptimeout=1;
|
||||
time_t prevtime=0;
|
||||
|
||||
String cmd;
|
||||
String prompt="%T %u@%H:%d> ";
|
||||
String defaultuser;
|
||||
|
||||
ALIAS *firstalias=NULL;
|
||||
|
||||
/* if main have any arguments, interprets each it as command with args */
|
||||
|
||||
|
||||
main(int argc, char **argv)
|
||||
|
||||
{
|
||||
register int i;
|
||||
register char *p1;
|
||||
FILE *fp;
|
||||
String tmp;
|
||||
|
||||
if (setjmp(start)!=0)
|
||||
goto main_loop;
|
||||
|
||||
setsignals();
|
||||
|
||||
|
||||
|
||||
FtpSetErrorHandler(&FtpInit,my_error);
|
||||
FtpSetIOHandler(&FtpInit,my_error);
|
||||
|
||||
strcpy(defaultuser,getpwuid(getuid())->pw_name);
|
||||
|
||||
|
||||
memset(ftp,0,sizeof(FTP*)*NFRAMES);
|
||||
memset(iftp,0,sizeof(LINKINFO)*NFRAMES);
|
||||
|
||||
|
||||
|
||||
batch(SYSTEMRC);
|
||||
|
||||
if (access(getrcname(),F_OK))
|
||||
{
|
||||
FILE *out=fdopen(open(getrcname(),O_WRONLY|O_CREAT|O_TRUNC,0700),"w");
|
||||
|
||||
printf("Create default rc-file \"%s\"\n",getrcname());
|
||||
|
||||
if (out==NULL)
|
||||
perror(getrcname());
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
fprintf(out,"set timeout 120\nset hash\nset debug\nset bin\n");
|
||||
fprintf(out,"set prompt \"%%T %%u@%%h:%%d\\> \"\n");
|
||||
fprintf(out,"alias a alias\na ed ! emacs\nalias tn ! telnet\n");
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
batch(getrcname());
|
||||
batch(getaliasrcname());
|
||||
|
||||
|
||||
for (i=1, tmp[0]=0; i< argc; i++)
|
||||
{
|
||||
strcat(tmp,argv[i]);
|
||||
if (i+1!=argc) strcat(tmp," ");
|
||||
}
|
||||
|
||||
if (tmp[0]!=0)
|
||||
{
|
||||
String new;
|
||||
|
||||
/*
|
||||
if (!strcmp(defaultuser,"ftp") || !strcmp(defaultuser,"anonymous"))
|
||||
strcpy(new,"ftp ");
|
||||
else
|
||||
*/
|
||||
strcpy(new,"open ");
|
||||
|
||||
if (ifalias(tmp))
|
||||
execute (tmp);
|
||||
else
|
||||
strcat(new,tmp),
|
||||
execute(new);
|
||||
}
|
||||
|
||||
|
||||
main_loop:
|
||||
|
||||
setsignals();
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
setjmp(start);
|
||||
if (lastcmd) exit(0);
|
||||
|
||||
|
||||
if (isatty(fileno(stdin)))
|
||||
p1=readline(getprompt());
|
||||
else
|
||||
p1=gets(cmd);
|
||||
|
||||
if (p1==NULL)
|
||||
{
|
||||
putchar('\n');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
strcpy(cmd,p1);
|
||||
|
||||
if (cmd[0]) add_history(cmd);
|
||||
execute(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE char *findspace(char *str)
|
||||
{
|
||||
while ( !isspace(*str) && *str != '\0' ) str++;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *word(char *str, int n)
|
||||
{
|
||||
String new;
|
||||
register char *p1, *p2;
|
||||
register int i;
|
||||
|
||||
strcpy(new,str);
|
||||
|
||||
p1=new;
|
||||
|
||||
while (isspace(*p1)) p1++;
|
||||
|
||||
if (n>1 )
|
||||
for (i=0;i<n-1;i++) /* Skip n-1 words */
|
||||
{
|
||||
if ((*p1=='"')||(*p1=='\''))
|
||||
{
|
||||
p1=strchr(p1+1,*p1);
|
||||
if (p1==NULL) return "";
|
||||
p1++;
|
||||
while ( isspace(*p1) ) p1++;
|
||||
continue;
|
||||
}
|
||||
p1=findspace(p1);
|
||||
if ( *p1=='\0' ) return "";
|
||||
p1++;
|
||||
while ( isspace(*p1) ) p1++;
|
||||
}
|
||||
|
||||
if ((*p1=='"')|(*p1=='\''))
|
||||
{
|
||||
p2=strchr(p1+1,*p1);
|
||||
if (p2==NULL) return p1+1;
|
||||
*p2=0;
|
||||
return p1+1;
|
||||
}
|
||||
|
||||
if ((p2=findspace(p1)) != NULL )
|
||||
{
|
||||
*p2=0;
|
||||
return p1;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/* Exacute few command separated by ';' . The character ' must use for mark complex
|
||||
works*/
|
||||
|
||||
execute (char *cmd)
|
||||
{
|
||||
String w1,w2,w3,w4,w5,w6;
|
||||
String newcmd;
|
||||
char *p;
|
||||
|
||||
if (!*cmd || *cmd=='#' ) return;
|
||||
|
||||
for ( p=newcmd ; *cmd; cmd++)
|
||||
{
|
||||
if ( *cmd == '\'' )
|
||||
{
|
||||
*p++=*cmd++;
|
||||
while ( *cmd != '\'' && *cmd != 0 ) *p++=*cmd++;
|
||||
if ( *cmd == 0 )
|
||||
return puts("Unbalanced \', please corrected!\n");
|
||||
*p++=*cmd;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( *cmd == ';' )
|
||||
{
|
||||
*p=0;
|
||||
execute(newcmd);
|
||||
p=newcmd;
|
||||
continue;
|
||||
}
|
||||
*p++=*cmd;
|
||||
}
|
||||
|
||||
|
||||
*p=0;
|
||||
cmd=newcmd;
|
||||
|
||||
if ( *cmd=='\\' )
|
||||
cmd++;
|
||||
else
|
||||
{
|
||||
String new;
|
||||
strcpy(new,"\\");
|
||||
strcat(new,expandalias(cmd));
|
||||
return execute(new);
|
||||
}
|
||||
|
||||
if ( *cmd == '!' )
|
||||
{
|
||||
int pid,_pid;
|
||||
union wait status;
|
||||
|
||||
if (!(pid=fork()))
|
||||
{
|
||||
execlp((getenv("SHELL")==NULL)?"/bin/sh":(char *)getenv("SHELL"),
|
||||
"shell","-c",cmd+1,NULL);
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
_pid=wait(&status);
|
||||
if (_pid==pid)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
redir(cmd);
|
||||
|
||||
if (cmd[strlen(cmd)-1]=='&')
|
||||
{
|
||||
String tmp;
|
||||
|
||||
cmd[strlen(cmd)-1]=0;
|
||||
|
||||
strcpy(tmp,"bg ");
|
||||
strcat(tmp,cmd);
|
||||
|
||||
strcpy(cmd,tmp);
|
||||
}
|
||||
|
||||
strcpy(w1,word(cmd,1));
|
||||
strcpy(w2,word(cmd,2));
|
||||
strcpy(w3,word(cmd,3));
|
||||
strcpy(w4,word(cmd,4));
|
||||
strcpy(w5,word(cmd,5));
|
||||
strcpy(w6,word(cmd,6));
|
||||
|
||||
return executev(w1,w2,w3,w4,w5,w6);
|
||||
}
|
||||
|
||||
executev(ARGS)
|
||||
{
|
||||
CMDS *xcmd=&cmds[0];
|
||||
String tmp;
|
||||
|
||||
if (isdigit(*w1))
|
||||
return
|
||||
atoi(w1)<NFRAMES?frame=atoi(w1):0,
|
||||
executev(w2,w3,w4,w5,w6,"");
|
||||
|
||||
while ( xcmd -> cmd != NULL )
|
||||
{
|
||||
if ( !strcmp(xcmd->cmd,w1) && (xcmd -> func != NULL) )
|
||||
{
|
||||
int status;
|
||||
|
||||
if ( xcmd -> need && LINK == NULL)
|
||||
return puts("Need connection to server");
|
||||
iftp[frame].lock=1; unsetsignals();
|
||||
status = (*xcmd->func)(w1,w2,w3,w4,w5,w6);
|
||||
iftp[frame].lock=0; setsignals();
|
||||
redirback();
|
||||
return status;
|
||||
}
|
||||
xcmd++;
|
||||
}
|
||||
|
||||
|
||||
if (LINK!=NULL && glassmode)
|
||||
return FtpCommand(LINK,cmd,"",0,EOF);
|
||||
|
||||
printf("%s: unknown command\n",w1);
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void intr(int sig)
|
||||
{
|
||||
printf("Interupted by signal %d\n",sig);
|
||||
if (LINK!=NULL) FtpSetHashHandler(LINK,NULL);
|
||||
setsignals();
|
||||
reset_termio(); /* From readline */
|
||||
prevtime = time((time_t *)0);
|
||||
longjmp(start,1);
|
||||
}
|
||||
|
||||
newframe(int connecteble)
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (connecteble)
|
||||
for (i=0; i<NFRAMES; i++) if (ftp[i]!=NULL) return frame=i;
|
||||
for (i=0; i<NFRAMES; i++) if (ftp[i]==NULL) return frame=i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATUS my_error(FTP *ftp, int code, char *msg)
|
||||
{
|
||||
|
||||
if (code==LQUIT||(ftp==NULL)) log(msg);
|
||||
else
|
||||
FtpLog(ftp->title,msg);
|
||||
|
||||
if ( abs(code) == 530 && (strstr(msg,"anonymous")!=NULL))
|
||||
{
|
||||
Ftp_reopen();
|
||||
longjmp(start,1);
|
||||
}
|
||||
longjmp(start,1);
|
||||
}
|
||||
|
||||
char *getrcname()
|
||||
{
|
||||
static String rcpath;
|
||||
struct passwd *pwd=getpwuid(getuid());
|
||||
|
||||
sprintf(rcpath,"%s/.uftprc",pwd->pw_dir);
|
||||
return rcpath;
|
||||
}
|
||||
|
||||
char *getaliasrcname()
|
||||
{
|
||||
static String rcpath;
|
||||
struct passwd *pwd=getpwuid(getuid());
|
||||
|
||||
sprintf(rcpath,"%s/.uftp_aliases",pwd->pw_dir);
|
||||
return rcpath;
|
||||
}
|
||||
|
||||
char *makestr(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
char *p1;
|
||||
va_list args;
|
||||
String new={0};
|
||||
|
||||
va_start(args);
|
||||
|
||||
while(1)
|
||||
{
|
||||
p1=va_arg(args,char *);
|
||||
if (p1==NULL) break;
|
||||
if (*p1!=0)
|
||||
{
|
||||
if (new[0]!=0) strcat(new," ");
|
||||
strcat(new,p1);
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
#define ADD(str,chr) (*str++=chr,*str=0)
|
||||
|
||||
INLINE ADDSTR(char **str, char *str1)
|
||||
{
|
||||
while (*str1) *(*str)++=*str1++;
|
||||
}
|
||||
|
||||
char *expandalias(char *str)
|
||||
{
|
||||
ALIAS *a=firstalias;
|
||||
String new={0},w1={0};
|
||||
char *p,*p1=new,*args;
|
||||
int dollar=0;
|
||||
|
||||
strcpy(w1,word(str,1));
|
||||
|
||||
if ( (p=strchr(str,' '))!=NULL )
|
||||
args=p+1;
|
||||
else
|
||||
args="";
|
||||
|
||||
while (a)
|
||||
{
|
||||
if (!strcmp(a->name,w1))
|
||||
break;
|
||||
a=a->next;
|
||||
}
|
||||
|
||||
if (!a)
|
||||
return str;
|
||||
|
||||
for ( p=a->str; *p; p++)
|
||||
{
|
||||
if ( *p != '$' )
|
||||
{
|
||||
ADD(p1,*p);
|
||||
continue;
|
||||
}
|
||||
|
||||
dollar=1;
|
||||
p++;
|
||||
|
||||
if (isdigit(*p))
|
||||
{
|
||||
ADDSTR(&p1,word(str,(*p)-'0'+1));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (*p)
|
||||
{
|
||||
|
||||
case '\0':
|
||||
case '$': ADD(p1,'$');continue;
|
||||
case '*': ADDSTR(&p1,args);continue;
|
||||
default: ADD(p1,'$');ADD(p1,*p);continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dollar)
|
||||
{
|
||||
ADD(p1,' ');
|
||||
ADDSTR(&p1,args);
|
||||
}
|
||||
|
||||
*p=0;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
ifalias(char *cmd)
|
||||
{
|
||||
String what;
|
||||
ALIAS *a=firstalias;
|
||||
|
||||
|
||||
strcpy(what,word(cmd,1));
|
||||
|
||||
while ( a!=NULL)
|
||||
{
|
||||
if (!strcmp(a->name,what))
|
||||
return 1;
|
||||
a=a->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *getprompt()
|
||||
{
|
||||
|
||||
static String _prompt;
|
||||
String tmp;
|
||||
char *s;
|
||||
|
||||
_prompt[0]=0;
|
||||
|
||||
for(s=prompt;*s;s++)
|
||||
switch (*s)
|
||||
{
|
||||
case '%':
|
||||
switch (*++s)
|
||||
{
|
||||
|
||||
case 'H':
|
||||
strcat(_prompt,iftp[frame].host);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
strcpy(tmp,iftp[frame].host);
|
||||
if (strchr(tmp,'.')!=NULL) *(char *)strchr(tmp,'.')=0;
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
gethostname(tmp, sizeof tmp);
|
||||
strcat(_prompt,gethostbyname(tmp)->h_name);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
gethostname(tmp, sizeof tmp);
|
||||
strcpy(tmp,gethostbyname(tmp)->h_name);
|
||||
if (strchr(tmp,'.')!=NULL) *(char *)strchr(tmp,'.')=0;
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
strcat(_prompt,iftp[frame].user);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
strcat(_prompt,iftp[frame].pwd);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
strcat(_prompt,(char *)getcwd(tmp,sizeof(tmp)));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
sprintf(tmp,"%d",frame);
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
sprintf(tmp,"%d",(LINK==NULL)?0:LINK->port);
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
sprintf(tmp,"%d",(LINK==NULL)?0:LINK->timeout.tv_sec);
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
|
||||
|
||||
case 'T':
|
||||
|
||||
{
|
||||
time_t t=time((time_t *)0);
|
||||
struct tm *lt=localtime(&t);
|
||||
sprintf(tmp,"%02d:%02d:%02d",lt->tm_hour,
|
||||
lt->tm_min,lt->tm_sec);
|
||||
strcat(_prompt,tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
|
||||
sprintf(tmp,"%d",getpid());
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
|
||||
default:
|
||||
sprintf(tmp,"%%%c",*s);
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case '^':
|
||||
|
||||
++s;
|
||||
if (isalpha(*s))
|
||||
{
|
||||
sprintf(tmp,"%c",toupper(*s)-'A'+1);
|
||||
strcat(_prompt,tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
sprintf(tmp,"%c",*s);
|
||||
strcat(_prompt,tmp);
|
||||
break;
|
||||
}
|
||||
return _prompt;
|
||||
}
|
||||
|
||||
|
||||
void noop()
|
||||
{
|
||||
int i;
|
||||
time_t curtime,save;
|
||||
STATUS (*func1)(),(*func2)(),(*func3)();
|
||||
|
||||
|
||||
if (noopinterval==0) return;
|
||||
|
||||
curtime = time((time_t *)0);
|
||||
|
||||
signal(SIGALRM,noop);
|
||||
|
||||
if (prevtime==0)
|
||||
{
|
||||
prevtime=curtime;
|
||||
alarm(noopinterval);
|
||||
return;
|
||||
}
|
||||
|
||||
if (curtime-prevtime < noopinterval)
|
||||
{
|
||||
alarm(prevtime+noopinterval-curtime);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Waiting...");fflush(stdout);
|
||||
|
||||
for (i=0;i<NFRAMES;i++)
|
||||
{
|
||||
if ( ftp[i]==NULL || FTPCMD(ftp[i]) == NULL || iftp[i].lock )
|
||||
continue;
|
||||
|
||||
func1=ftp[i]->debug; ftp[i]->debug=NULL;
|
||||
func2=ftp[i]->error; ftp[i]->error=NULL;
|
||||
func3=ftp[i]->IO; ftp[i]->IO=NULL;
|
||||
save = ftp[i]->timeout.tv_sec;
|
||||
ftp[i]->timeout.tv_sec = nooptimeout;
|
||||
|
||||
FtpCommand(ftp[i],"NOOP","",0,EOF);
|
||||
|
||||
ftp[i]->timeout.tv_sec = save;
|
||||
ftp[i]->debug=func1;
|
||||
ftp[i]->error=func1;
|
||||
ftp[i]->IO=func1;
|
||||
|
||||
}
|
||||
|
||||
alarm(noopinterval);
|
||||
prevtime=curtime;
|
||||
|
||||
for (i=0;i<10;i++) putchar(8),putchar(' '),putchar(8);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
setsignals()
|
||||
{
|
||||
signal(SIGINT,intr);
|
||||
signal(SIGQUIT,intr);
|
||||
noop();
|
||||
}
|
||||
|
||||
unsetsignals()
|
||||
{
|
||||
signal(SIGALRM,SIG_IGN);
|
||||
alarm(0);
|
||||
}
|
||||
|
||||
|
||||
int myhash(FTP *ftp,unsigned int chars)
|
||||
{
|
||||
|
||||
if (hashmode)
|
||||
{
|
||||
if (chars==0) return ftp -> counter=0;
|
||||
ftp -> counter += chars;
|
||||
fprintf(stdout,"%10u bytes transfered\r",ftp -> counter);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (!lastcmd)
|
||||
{
|
||||
noop();
|
||||
alarm(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *makefilename(char *f1, char *f2)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (*f2!=0)
|
||||
return f2;
|
||||
|
||||
if ( (p=strrchr(f1,'/'))!=NULL)
|
||||
return p+1;
|
||||
return f1;
|
||||
}
|
||||
|
||||
redir(char *cmdline)
|
||||
{
|
||||
char *p=cmdline;
|
||||
String result;
|
||||
char *r=result;
|
||||
|
||||
for ( ; *p ; p++ , r++ )
|
||||
{
|
||||
if ( *p == '\\' )
|
||||
{
|
||||
*r = * ++ p ;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( *p == '>' || *p == '<' )
|
||||
{
|
||||
String filename;
|
||||
char *q=filename;
|
||||
char c=*p;
|
||||
|
||||
for (p++;isspace(*p)&&*p!=0;p++);
|
||||
if (*p=='"')
|
||||
{
|
||||
for (p++; *p!='"' && *p!=0 ; p++,q++) *q=*p;
|
||||
if (*p!='"') p++;
|
||||
}
|
||||
else
|
||||
for (; !isspace(*p) && *p!=0 ; p++,q++) *q=*p;
|
||||
|
||||
*q=0;
|
||||
|
||||
if ( c == '>' )
|
||||
output(filename);
|
||||
else
|
||||
input(filename);
|
||||
}
|
||||
*r=*p;
|
||||
}
|
||||
*r=0;
|
||||
strcpy(cmdline,result);
|
||||
}
|
||||
|
||||
int itty=-1,otty=-1;
|
||||
FILE *is=NULL,*os=NULL;
|
||||
|
||||
|
||||
input(char *filename)
|
||||
{
|
||||
|
||||
if ((is=Ftpfopen(filename,"r"))==NULL)
|
||||
{
|
||||
perror(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
fflush(stdin);
|
||||
itty=dup(0);
|
||||
close(0);
|
||||
dup2(fileno(is),0);
|
||||
|
||||
}
|
||||
|
||||
output(char *filename)
|
||||
{
|
||||
|
||||
if ((os=Ftpfopen(filename,"w"))==NULL)
|
||||
{
|
||||
perror(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
otty=dup(1);
|
||||
close(1);
|
||||
dup2(fileno(os),1);
|
||||
}
|
||||
|
||||
redirback()
|
||||
{
|
||||
|
||||
if (itty!=-1)
|
||||
{
|
||||
fflush(stdin);
|
||||
close(0);
|
||||
Ftpfclose(is);
|
||||
dup2(itty,0);
|
||||
is=NULL;
|
||||
itty=-1;
|
||||
}
|
||||
|
||||
if (otty!=-1)
|
||||
{
|
||||
fflush(stdout);
|
||||
close(1);
|
||||
Ftpfclose(os);
|
||||
dup2(otty,1);
|
||||
os=NULL;
|
||||
otty=-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
batch(char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
String tmp;
|
||||
|
||||
if ((fp=fopen(filename,"r"))!=NULL)
|
||||
{
|
||||
|
||||
while ( fgets(tmp, sizeof tmp, fp) != NULL)
|
||||
{
|
||||
tmp[strlen(tmp)-1]=0;
|
||||
execute(tmp);
|
||||
if (tmp[0]) add_history(tmp);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
83
lib/libftp/utils/uftp.h
Normal file
83
lib/libftp/utils/uftp.h
Normal file
@ -0,0 +1,83 @@
|
||||
#include <FtpLibrary.h>
|
||||
#include <strings.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/file.h>
|
||||
#include <arpa/telnet.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
|
||||
|
||||
#define SYSTEMRC "/usr/share/etc/uftprc"
|
||||
#define LINK ftp[frame]
|
||||
#define NFRAMES 10
|
||||
#define TIME(proc) settimer(), status = proc , showtimer(), status
|
||||
#define ARGS char *w1,char *w2,char *w3,char *w4,char *w5,char *w6
|
||||
#define log(x) FtpLog("uftp",x)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
String host;
|
||||
String user;
|
||||
String pass;
|
||||
String pwd;
|
||||
int lock;
|
||||
} LINKINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *cmd;
|
||||
int (*func)();
|
||||
int need;
|
||||
char *help;
|
||||
} CMDS;
|
||||
|
||||
typedef struct _alias
|
||||
{
|
||||
String name,str;
|
||||
struct _alias *next;
|
||||
} ALIAS;
|
||||
|
||||
extern ALIAS *firstalias;
|
||||
extern FTP *ftp[NFRAMES];
|
||||
extern LINKINFO iftp[NFRAMES];
|
||||
extern int frame;
|
||||
extern int lastcmd;
|
||||
extern int glassmode;
|
||||
extern int trymode;
|
||||
extern int hashmode;
|
||||
extern int restmode;
|
||||
extern int sleeptime;
|
||||
extern time_t noopinterval,nooptimeout;
|
||||
extern CMDS cmds[];
|
||||
extern int status;
|
||||
extern String prompt;
|
||||
extern String defaultuser;
|
||||
extern jmp_buf start;
|
||||
|
||||
char *word(char *,int);
|
||||
char *readline(char *);
|
||||
char *getpass(char *);
|
||||
char *getrcname();
|
||||
char *getaliasrcname();
|
||||
char *makestr();
|
||||
char *expandalias(char *str);
|
||||
char *getprompt();
|
||||
char *makefilename(char *,char *);
|
||||
|
||||
void intr(int);
|
||||
void noop();
|
||||
int myhash(FTP *,unsigned int);
|
||||
STATUS my_error(FTP *, int, char *);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
452
lib/libftp/utils/uftp.man
Normal file
452
lib/libftp/utils/uftp.man
Normal file
@ -0,0 +1,452 @@
|
||||
.TH \fBuftp\fR 1
|
||||
.SH Name
|
||||
uftp \- universal file transfer program
|
||||
.SH Syntax
|
||||
\fBuftp\fR
|
||||
.PP
|
||||
\fBuftp alias_name [args_for_alias]\fR
|
||||
.PP
|
||||
\fBuftp hostname\fR
|
||||
|
||||
.SH Description
|
||||
|
||||
|
||||
The uftp is user interactive and non-interactive program to the ARPANET File Transfer Protocol (RFC959).
|
||||
The uftp allows user to transfer files, group of files in foreground and background modes. uftp runs on the client host.
|
||||
|
||||
|
||||
.SH Basic features
|
||||
|
||||
|
||||
|
||||
Auto retrying of connection to remote node until it is succeeded.
|
||||
.PP
|
||||
Automatic reconnection with continue to transfer if the connection was broken.
|
||||
.PP
|
||||
Several sessions (frames) at once. Dynamically switching between them.
|
||||
.PP
|
||||
Setup commands, which are executed after "open" and "cd" commands. (aliases autologin & autocd )
|
||||
.PP
|
||||
Cleaning timeout on the remote server.
|
||||
.PP
|
||||
The user can setup any system parameters, like timeouts, reconnect delays, default port number,
|
||||
automatic binary mode, automatic "hash" mode and interval to clean timeouts on FTP server.
|
||||
.PP
|
||||
User can setup the prompt with the descriptions of local and remote directories, full or short site name,
|
||||
time, frame number,
|
||||
remote user's name, port number, timeout, process identification.
|
||||
.PP
|
||||
Several commands in one line.
|
||||
.PP
|
||||
Aliases with arguments, which may contain few commands separated by ';'.
|
||||
.PP
|
||||
Redirection input/output irrespective of context or/and command.
|
||||
.PP
|
||||
The local files are libftp-files, which split on local files, pipes and ftp-files. This particular file specification
|
||||
can be used in any context, including for file names of redirection input/output streams.
|
||||
.PP
|
||||
Any command may be executed in background mode, though the current frame is not droped out and user can continue
|
||||
his work.
|
||||
.PP
|
||||
Creation of alias described the current frame, and save all exist aliases to personal
|
||||
automatic startup file, which is differ from startup file. This file user can make himself.
|
||||
|
||||
|
||||
.SH Environment description
|
||||
|
||||
|
||||
|
||||
Command line mode supports all edit key bindings. (uftp using readline library).
|
||||
Before each command user can see the prompt with description of current frame.
|
||||
If debug mode is enabled user see the protocol between uftp and ftp-daemon (ftpd).
|
||||
|
||||
|
||||
|
||||
.SH Commands
|
||||
|
||||
|
||||
.IP \fBconnect\fR 10
|
||||
[host-name]
|
||||
|
||||
Connect to remote site.
|
||||
|
||||
.IP \fBopen\fR 10
|
||||
[host-name] [user-name] [password] [directory]
|
||||
|
||||
Makes connection to remote site, sent login, password and change directory.
|
||||
If the "try" option is set an attempt to connect will be forced until success.
|
||||
|
||||
.IP \fBftp\fR 10
|
||||
[hostname] [directory]
|
||||
|
||||
Anonymous connection to ftp-site.
|
||||
|
||||
.IP \fBreopen\fR 10
|
||||
|
||||
Reopen broken frame.
|
||||
|
||||
.IP \fBclose\fR 10
|
||||
|
||||
Close the current connection.
|
||||
|
||||
.IP \fBquit\fR 10
|
||||
|
||||
Quit from uftp (You can press Contol-D)
|
||||
|
||||
.IP \fBlist\fR 10
|
||||
|
||||
Description list of all frames.
|
||||
|
||||
.IP \fBuser\fR 10
|
||||
[user-name] [password]
|
||||
|
||||
Send user's name to site, automatically require password if needed.
|
||||
|
||||
.IP \fBpass\fR 10
|
||||
[password]
|
||||
|
||||
Specify user's password.
|
||||
|
||||
.IP \fBbin\fR 10
|
||||
|
||||
Set binary transfer mode.
|
||||
|
||||
.IP \fBascii\fR 10
|
||||
|
||||
Set ASCII transfer mode.
|
||||
|
||||
.IP \fBcd\fR 10
|
||||
directory_name
|
||||
|
||||
Change the current directory on remote site.
|
||||
|
||||
.IP \fBacd\fR 10
|
||||
[directory_name]
|
||||
|
||||
Archie searching by specified pattern with subsequent connection to desired point.
|
||||
Maximum number of possible points is 20.
|
||||
Afterwards user can select any point. If user don't specify "directory_name",
|
||||
last search buffer is displayed for selection, if this buffer is not empty.
|
||||
|
||||
.IP \fBlcd\fR 10
|
||||
directory_name
|
||||
|
||||
Local change directory. User can use metacharacters.
|
||||
|
||||
.IP \fBabort\fR 10
|
||||
|
||||
Abort execute of last procedure with server.
|
||||
|
||||
Warning: this procedure sometimes is not correctly working.
|
||||
|
||||
.IP \fBmkdir\fR 10
|
||||
directory_name
|
||||
|
||||
Create new directory on the server.
|
||||
|
||||
.IP \fBrm\fR 10
|
||||
filename_or_pattern
|
||||
|
||||
Remove specified file(s) on the server.
|
||||
|
||||
.IP \fBmv\fR 10
|
||||
old_filename new_filename
|
||||
|
||||
Move file on the server.
|
||||
|
||||
.IP \fBdir\fR 10
|
||||
[keys] [filename_spec] ....
|
||||
|
||||
Make long list of specified file(s) with date, size, etc...
|
||||
|
||||
.IP \fBls\fR 10
|
||||
[keys] [filename_spec] ....
|
||||
|
||||
Make short list of specified file(s).
|
||||
|
||||
.IP \fBget\fR 10
|
||||
remote_filename [local_filename_or_directory]
|
||||
|
||||
Receive the file from the server to local file system (only one file!).
|
||||
If option "rest" is turn on then transfer starts from the end of local file.
|
||||
|
||||
.IP \fBmget\fR 10
|
||||
[remote_filename] [local_directory]
|
||||
|
||||
Receive many files from the server to local file system.
|
||||
|
||||
.IP \fBreget\fR 10
|
||||
remote_filename [local_filename_or_directory].
|
||||
|
||||
The same as get, but the option "rest" is ignored.
|
||||
|
||||
.IP \fBaget\fR 10
|
||||
[pattern_for_archie]
|
||||
|
||||
Getting the file, which need to find via archie service. See also "acd" description.
|
||||
|
||||
.IP \fBbget\fR 10
|
||||
[libftp_file] [local_file]
|
||||
|
||||
Get file specified as libftp-file. See libftp file specification. Operation
|
||||
proceedes until success.
|
||||
|
||||
.IP \fBput\fR 10
|
||||
local_filename [remote_filename]
|
||||
|
||||
Put one file to server.
|
||||
|
||||
.IP \fBmput\fR 10
|
||||
local_filename(s)
|
||||
|
||||
Put specified file(s) to server.
|
||||
|
||||
.IP \fBreput\fR 10
|
||||
The same as put, but the option "rest" is ignored.
|
||||
|
||||
.IP \fBbput\fR 10
|
||||
[[local_file] libftp_file]
|
||||
|
||||
Put file specified as libftp-file. See libftp file specification. Operation
|
||||
proceedes until success.
|
||||
|
||||
.IP \fBcopy\fR 10
|
||||
[frame/]filename [frame/]filename
|
||||
|
||||
Copy one file from first frame to second. If the frame number is not specified
|
||||
then use current frame number. Transfer operation executes via libftp cache.
|
||||
|
||||
|
||||
.IP \fBccopy\fR 10
|
||||
[frame/]filename [frame/]filename
|
||||
|
||||
Copy one file from first frame to second. If the frame number is not specified
|
||||
then used current frame number. Transfer operation executes via leased line
|
||||
between two servers cache.
|
||||
|
||||
|
||||
.IP \fBcat\fR 10
|
||||
filename
|
||||
|
||||
Display context of specified file on screen.
|
||||
|
||||
.IP \fBpage\fR 10
|
||||
|
||||
The same as cat, but with using of pager. Name of pager specified in environment variable
|
||||
PAGER or "more" by default.
|
||||
|
||||
.IP \fBbg\fR 10
|
||||
any_command
|
||||
|
||||
any_command &
|
||||
|
||||
Run any command in background mode. Default output is redirected to
|
||||
/tmp/uftp-<user_name>.XXXXXX file.
|
||||
|
||||
.IP \fBarchie\fR 10
|
||||
[pattern]
|
||||
|
||||
Archie search. In case if argument are omitted, reprint last search.
|
||||
|
||||
.IP \fBdup\fR 10
|
||||
|
||||
Create new frame as current.
|
||||
|
||||
.IP \fBquote\fR 10
|
||||
|
||||
Send raw command to server. If option "glassmode" is set then all non-recognized
|
||||
commands send to server as raw also.
|
||||
|
||||
.IP \fBhelp\fR 10
|
||||
[command]
|
||||
|
||||
Print brief help or help for specified command.
|
||||
|
||||
.IP \fBalias\fR 10
|
||||
alias_name alias_string
|
||||
|
||||
Makes new alias, if the alias string uftp contains string like $1, $2, $* then
|
||||
it will be replaced by argument to alias. If this sequences in alias is not found, then
|
||||
all existing alias's arguments will append to end of alias call string. User can insert to alias
|
||||
string like \\\> \\\< for future redirect input/output. Quotes ' and " can be used
|
||||
also.
|
||||
|
||||
.IP \fBunalias\fR 10
|
||||
alias_name
|
||||
|
||||
Remove specified alias.
|
||||
|
||||
.IP \fBmkalias\fR 10
|
||||
alias_name
|
||||
|
||||
Makes new alias, which user can use in future for login to this point again.
|
||||
See also "savealias"
|
||||
|
||||
.IP \fBsavealias\fR 10
|
||||
|
||||
Save all aliases in startup file.
|
||||
|
||||
|
||||
.SH Libftp file specification
|
||||
|
||||
All local files interpret as libftp's files. Libftp responds to three types of files such
|
||||
as local file, ftp files and program
|
||||
pipes. All files can be described as next syntax:
|
||||
|
||||
|string - interprets string as shell command, which must be \
|
||||
executed with appropriate input/output for file. It depends where
|
||||
this file is specified.
|
||||
|
||||
hostname:filename - interprets as file, which must be taken
|
||||
using ftp protocol with anonymous access
|
||||
|
||||
user@hostname:filename - interprets as file accesses via ftp
|
||||
with password yourname@your_host.your_domain
|
||||
|
||||
user/pass@hostname:filename - also ftp file.
|
||||
|
||||
*STDIN*, *STDOUT*, *STDERR* or char '-' - opened streams.
|
||||
|
||||
anything - local file name.
|
||||
|
||||
.SH String syntax
|
||||
|
||||
The strings starting from char '!' interpret as shell command.
|
||||
The strings or aliases containing one or few char ';' will be executed as a chain commands.
|
||||
The chains of characters between " or ' interpret as one set without syntax resolving.
|
||||
In any command string user can redirect input or/and output
|
||||
using char > and < . For the complex file name it must quoted by ' or ".
|
||||
|
||||
Examples:
|
||||
|
||||
dir >filename
|
||||
|
||||
cat filename >'|mail -s "my files" fiend@hostname.domain'
|
||||
|
||||
dir -R etc bin >"|gzip >result.gz"
|
||||
|
||||
cat filename > user/password@hostname:/dir/filename.ext
|
||||
|
||||
put - < "|finger @hostname" newfile.finger
|
||||
|
||||
|
||||
.SH Options (command set)
|
||||
|
||||
.IP \fBset\fR
|
||||
|
||||
|
||||
Show all current settings.
|
||||
|
||||
.IP \fBset\fR
|
||||
frame <frame_number>
|
||||
|
||||
Switch to another frame. You can also switch by insert on frame number to the
|
||||
begin of command line.
|
||||
|
||||
.IP \fBset\fR
|
||||
timeout <seconds>
|
||||
|
||||
Set timeout for send/receive operations.
|
||||
|
||||
.IP \fBset\fR
|
||||
noop <secs>
|
||||
|
||||
Set interval for send NOOP command to each connected server for cleaning
|
||||
timeouts.
|
||||
|
||||
.IP \fBset\fR
|
||||
nooptimeout <seconds>
|
||||
|
||||
Set timeout for NOOP operation.
|
||||
|
||||
.IP \fBset\fR
|
||||
sleep <secs>
|
||||
|
||||
Set pause interval between transfer attempts.
|
||||
|
||||
.IP \fBset\fR
|
||||
debug <y|n>
|
||||
|
||||
Enable or disable protocol debug output
|
||||
|
||||
.IP \fBset\fR
|
||||
try <y|n>
|
||||
|
||||
Enable or disable retrys after lost peer.
|
||||
|
||||
.IP \fBset\fR
|
||||
hash <y|n>
|
||||
|
||||
Enable or disable trace for the transfer operations.
|
||||
|
||||
.IP \fBset\fR
|
||||
restore <y|n>
|
||||
|
||||
Enable or disable default transfer starting from end of file.
|
||||
|
||||
.IP \fBset\fR
|
||||
bin <y|n>
|
||||
|
||||
Automatic binary mode.
|
||||
|
||||
.IP \fBset\fR
|
||||
glass <y|n>
|
||||
|
||||
This command only to debug the protocol. After glassmode it is enable
|
||||
to send raw to server of all unresponded commands.
|
||||
|
||||
.IP \fBset\fR
|
||||
prompt <prompt_string>
|
||||
|
||||
Set the prompt. Prompt is a string, which may contain %<char>
|
||||
or ^<char> combitanions with the next embodies:
|
||||
|
||||
%H, %h - full and short remote host names
|
||||
%M, %m - full and short local host names
|
||||
%u - remote user's name
|
||||
%d - remote current directory
|
||||
%D - local current directory
|
||||
%f - number of current frame
|
||||
%p - the ftp's port number
|
||||
%t - timeout
|
||||
%T - current time
|
||||
%P - uftp process id
|
||||
%% - character %
|
||||
^<char>- control character
|
||||
%^ - character ^
|
||||
|
||||
|
||||
.IP \fBset\fR
|
||||
port <number>
|
||||
|
||||
Set default FTP's port for next sessions.
|
||||
|
||||
.IP \fBset\fR
|
||||
user <user_name>
|
||||
|
||||
Set default user's name.
|
||||
|
||||
.SH Startup file
|
||||
|
||||
User can modify his startup file created automatically. This file may
|
||||
contain some uftp's commands separated by new-line. The name of this file is ~/.uftprc.
|
||||
The file ~/.uftp_aliases is created automatically by uftp's command "savealias",
|
||||
so it is not needed to edit handly.
|
||||
|
||||
.SH Author of uftp and libftp
|
||||
|
||||
Oleg Orel
|
||||
|
||||
Department of Electronics and automatisation.
|
||||
|
||||
Institute for High Energy Physics
|
||||
|
||||
Protvino, Russia
|
||||
|
||||
E-mail: orel@oea.ihep.su, orel@dxcern.cern.ch
|
||||
|
||||
|
||||
|
||||
.SH See also
|
||||
|
||||
\fBncftp\fR (1), \fBftp\fR (1), \fBftpd\fR (8)
|
1202
lib/libftp/utils/uftpcmd.c
Normal file
1202
lib/libftp/utils/uftpcmd.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user