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:
Jordan K. Hubbard 1995-04-25 15:05:11 +00:00
parent 6ec8ee4578
commit 6f52f41fb2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/libftp/; revision=8064
47 changed files with 8593 additions and 0 deletions

47
lib/libftp/FtpAbort.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
all clean cleandist install:
@echo -n

51
lib/libftp/doc/example.c Normal file
View 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);
}

View 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
View 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
View 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 же сое действие что и функция \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 же сое действие что и функция \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} в основном предназначен для неитерактивной
передачи данных, поэтому необходимая информация для выполнения передачи задася в виде опций при запуске программы.
При запуске \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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff