diff options
author | jkh <jkh@FreeBSD.org> | 1995-04-25 15:05:11 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1995-04-25 15:05:11 +0000 |
commit | 02ace706173509b7d8549494277ff682b7cefb8a (patch) | |
tree | 437a6d909f192743fe7d26def0fdfae947754209 /lib | |
download | FreeBSD-src-02ace706173509b7d8549494277ff682b7cefb8a.zip FreeBSD-src-02ace706173509b7d8549494277ff682b7cefb8a.tar.gz |
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>
Diffstat (limited to 'lib')
47 files changed, 8593 insertions, 0 deletions
diff --git a/lib/libftp/FtpAbort.c b/lib/libftp/FtpAbort.c new file mode 100644 index 0000000..50b32e6 --- /dev/null +++ b/lib/libftp/FtpAbort.c @@ -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; + } +} + + + diff --git a/lib/libftp/FtpArchie.c b/lib/libftp/FtpArchie.c new file mode 100644 index 0000000..7f039be --- /dev/null +++ b/lib/libftp/FtpArchie.c @@ -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; +} diff --git a/lib/libftp/FtpBye.c b/lib/libftp/FtpBye.c new file mode 100644 index 0000000..de300d5 --- /dev/null +++ b/lib/libftp/FtpBye.c @@ -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); +} + diff --git a/lib/libftp/FtpClose.c b/lib/libftp/FtpClose.c new file mode 100644 index 0000000..26dbc51 --- /dev/null +++ b/lib/libftp/FtpClose.c @@ -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); +} diff --git a/lib/libftp/FtpCommand.c b/lib/libftp/FtpCommand.c new file mode 100644 index 0000000..06421ba --- /dev/null +++ b/lib/libftp/FtpCommand.c @@ -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); +} + + + diff --git a/lib/libftp/FtpConnect.c b/lib/libftp/FtpConnect.c new file mode 100644 index 0000000..6869e60 --- /dev/null +++ b/lib/libftp/FtpConnect.c @@ -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); +} + + + diff --git a/lib/libftp/FtpCopy.c b/lib/libftp/FtpCopy.c new file mode 100644 index 0000000..d09fd36 --- /dev/null +++ b/lib/libftp/FtpCopy.c @@ -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; +} + + + + + + + diff --git a/lib/libftp/FtpData.c b/lib/libftp/FtpData.c new file mode 100644 index 0000000..e0c768e --- /dev/null +++ b/lib/libftp/FtpData.c @@ -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; +} + + + + + diff --git a/lib/libftp/FtpDebug.c b/lib/libftp/FtpDebug.c new file mode 100644 index 0000000..c7fa811 --- /dev/null +++ b/lib/libftp/FtpDebug.c @@ -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; +} diff --git a/lib/libftp/FtpFilenameChecker.c b/lib/libftp/FtpFilenameChecker.c new file mode 100644 index 0000000..47483d4 --- /dev/null +++ b/lib/libftp/FtpFilenameChecker.c @@ -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; + }; + +} + + diff --git a/lib/libftp/FtpFull.c b/lib/libftp/FtpFull.c new file mode 100644 index 0000000..aefaa2d --- /dev/null +++ b/lib/libftp/FtpFull.c @@ -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; +} + + + + + + + + diff --git a/lib/libftp/FtpGetHost.c b/lib/libftp/FtpGetHost.c new file mode 100644 index 0000000..e0c2305 --- /dev/null +++ b/lib/libftp/FtpGetHost.c @@ -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); +} + + diff --git a/lib/libftp/FtpGood.c b/lib/libftp/FtpGood.c new file mode 100644 index 0000000..332232a --- /dev/null +++ b/lib/libftp/FtpGood.c @@ -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++; + } +} + diff --git a/lib/libftp/FtpIO.c b/lib/libftp/FtpIO.c new file mode 100644 index 0000000..3686981 --- /dev/null +++ b/lib/libftp/FtpIO.c @@ -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; +} + + + + + + + + + + + + diff --git a/lib/libftp/FtpInit.c b/lib/libftp/FtpInit.c new file mode 100644 index 0000000..eee7cea --- /dev/null +++ b/lib/libftp/FtpInit.c @@ -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; +} + + diff --git a/lib/libftp/FtpLibrary.h b/lib/libftp/FtpLibrary.h new file mode 100644 index 0000000..02aa662 --- /dev/null +++ b/lib/libftp/FtpLibrary.h @@ -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_ */ + + + diff --git a/lib/libftp/FtpLogin.c b/lib/libftp/FtpLogin.c new file mode 100644 index 0000000..27e43ae --- /dev/null +++ b/lib/libftp/FtpLogin.c @@ -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); +} diff --git a/lib/libftp/FtpMessage.c b/lib/libftp/FtpMessage.c new file mode 100644 index 0000000..dd02261 --- /dev/null +++ b/lib/libftp/FtpMessage.c @@ -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') ; +} + + + + + diff --git a/lib/libftp/FtpMove.c b/lib/libftp/FtpMove.c new file mode 100644 index 0000000..31d6c25 --- /dev/null +++ b/lib/libftp/FtpMove.c @@ -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; +} diff --git a/lib/libftp/FtpNumber.c b/lib/libftp/FtpNumber.c new file mode 100644 index 0000000..56411f8 --- /dev/null +++ b/lib/libftp/FtpNumber.c @@ -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') ; +} diff --git a/lib/libftp/FtpOpenDir.c b/lib/libftp/FtpOpenDir.c new file mode 100644 index 0000000..2d3e56e --- /dev/null +++ b/lib/libftp/FtpOpenDir.c @@ -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); +} diff --git a/lib/libftp/FtpPasv.c b/lib/libftp/FtpPasv.c new file mode 100644 index 0000000..88b000d --- /dev/null +++ b/lib/libftp/FtpPasv.c @@ -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); + } +} + + + + + diff --git a/lib/libftp/FtpPort.c b/lib/libftp/FtpPort.c new file mode 100644 index 0000000..c6b0ca2 --- /dev/null +++ b/lib/libftp/FtpPort.c @@ -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); +} diff --git a/lib/libftp/FtpPwd.c b/lib/libftp/FtpPwd.c new file mode 100644 index 0000000..fb74841 --- /dev/null +++ b/lib/libftp/FtpPwd.c @@ -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; +} diff --git a/lib/libftp/FtpRetr.c b/lib/libftp/FtpRetr.c new file mode 100644 index 0000000..889621f --- /dev/null +++ b/lib/libftp/FtpRetr.c @@ -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); +} + + + + + + + + + + + + diff --git a/lib/libftp/FtpSize.c b/lib/libftp/FtpSize.c new file mode 100644 index 0000000..040e16b --- /dev/null +++ b/lib/libftp/FtpSize.c @@ -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; +} diff --git a/lib/libftp/FtpStor.c b/lib/libftp/FtpStor.c new file mode 100644 index 0000000..2fe218c --- /dev/null +++ b/lib/libftp/FtpStor.c @@ -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); +} + + + + + + + diff --git a/lib/libftp/FtpSyscalls.c b/lib/libftp/FtpSyscalls.c new file mode 100644 index 0000000..d1c74e6 --- /dev/null +++ b/lib/libftp/FtpSyscalls.c @@ -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) diff --git a/lib/libftp/FtpType.c b/lib/libftp/FtpType.c new file mode 100644 index 0000000..6c32016 --- /dev/null +++ b/lib/libftp/FtpType.c @@ -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; +} + + diff --git a/lib/libftp/Ftpfopen.c b/lib/libftp/Ftpfopen.c new file mode 100644 index 0000000..b7b96d5 --- /dev/null +++ b/lib/libftp/Ftpfopen.c @@ -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; + } + +} diff --git a/lib/libftp/Makefile b/lib/libftp/Makefile new file mode 100644 index 0000000..d75e47a --- /dev/null +++ b/lib/libftp/Makefile @@ -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> diff --git a/lib/libftp/doc/Makefile b/lib/libftp/doc/Makefile new file mode 100644 index 0000000..82fe3e0 --- /dev/null +++ b/lib/libftp/doc/Makefile @@ -0,0 +1,2 @@ +all clean cleandist install: + @echo -n diff --git a/lib/libftp/doc/example.c b/lib/libftp/doc/example.c new file mode 100644 index 0000000..7f09287 --- /dev/null +++ b/lib/libftp/doc/example.c @@ -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); + +} diff --git a/lib/libftp/doc/example.tex b/lib/libftp/doc/example.tex new file mode 100644 index 0000000..47c4a9d --- /dev/null +++ b/lib/libftp/doc/example.tex @@ -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} diff --git a/lib/libftp/doc/libftp.tex b/lib/libftp/doc/libftp.tex new file mode 100644 index 0000000..f7d14e8 --- /dev/null +++ b/lib/libftp/doc/libftp.tex @@ -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} + + + + + + + + + + + + diff --git a/lib/libftp/doc/rus.tex b/lib/libftp/doc/rus.tex new file mode 100644 index 0000000..2361c11 --- /dev/null +++ b/lib/libftp/doc/rus.tex @@ -0,0 +1,521 @@ +\documentstyle[russian,fancyheadings,twoside,epsf,indentfirst]{article} +% Vertical sizes +%\vsize=20cm +%\voffset=-2.3cm +%\topmargin=0cm +%\headheight=0.9cm +%\footskip=1cm +%\footheight=0.9cm +%\textheight=16cm +%\headrulewidth 0.01cm +%\footrulewidth 0.0cm +% horisontal sizes +%\hsize=30cm +%\hoffset=-4.3cm +%\hoffset=-2.3cm +%\textwidth=13cm +% Modes +% \special{landscape} +\pagestyle{empty} +\pagestyle{fancyplain} +\newcommand{\tit}[1]{#1} +\rhead[\fancyplain{}{\tit{\leftmark}}]{\fancyplain{}{\tit{\rightmark}}} +\lhead[\fancyplain{}{\tit{\rightmark}}]{\fancyplain{}{\tit{\leftmark}}} +\chead{\hfill} +\lfoot[\fancyplain{}{\tit{\thepage}}]{\fancyplain{}{\hfill}} +\rfoot[\fancyplain{}{\hfill}]{\fancyplain{}{\tit{\thepage}}} +\cfoot{\hfill} +\renewcommand{\sectionmark}[1]{\markboth{#1}{\ }} +\renewcommand{\subsectionmark}[1]{\markright{\ }} +\newcommand{\look}[1]{(çÌÁ×Á~\ref{#1}, ÓÔÒ.~\pageref{#1})} +\newcommand{\toindex}[1]{\underline{\bf#1}\index{#1}} +\newcommand{\add}[1]{\symbol{64}} +\newcommand{\ps}[1]{\symbol{37}s} +\newcommand{\twcol}[4]{ +\noindent\parbox[t]{#1\textwidth}{#3} \hfill \parbox[t]{#2\textwidth}{#4\hfill}\\ +} +\newcommand{\tc}[2]{\twcol{0.49}{0.49}{#1}{#2}} +\newcommand{\tcc}[2]{\twcol{0.49}{0.49}{\toindex{#1}}{#2}} +\newcommand{\ttt}[2]{\bigskip + +{\bf#1} + +#2} +\newcommand{\ts}[1]{{\bf#1}} +\newcommand{\dl}[2]{\parbox[t]{0.4\textwidth}{#1\hfill}\hfill + \parbox[t]{0.4\textwidth}{#2\hfill}} +\makeindex +\begin{document} +\title{\bf\it òõëï÷ïäóô÷ï ðïìøúï÷áôåìñ âéâìéïôåëé "LIBFTP"} +\author{ïÌÅÇ ïÒÅÌ} +\date{\today} +\newpage +\maketitle + +\section*{ìÉÃÅÎÚÉÑ} + +ðÒÏÄÕËÔ ÐÒÅÄÎÁÚÎÁÞÅÎ ÄÌÑ ÎÁÐÉÓÁÎÉÑ Ó×ÏÂÏÄÎÏÇÏ ÎÅËÏÍÍÅÒÞÅÓËÏÇÏ ÐÒÏÇÒÁÍÍÎÏÇÏ +ÏÂÅÓÐÅÞÅÎÉÑ. ïÎ ÍÏÖÅÔ ÉÓÐÒÁ×ÌÑÔØÓÑ É ÄÏÐÉÓÙ×ÁÔØÓÑ. +á×ÔÏÒ ÂÕÄÅÔ ÂÌÁÇÏÄÁÒÅÎ ÚÁ ÐÏÌÕÞÅÎÉÅ ÓÏ×ÅÔÏ×, ÎÏ×ÙÈ ËÏÍÐÏÎÅÎÔ É ÐÒÁ×ÏË +ÓÕÝÅÓÔ×ÕÀÝÉÈ ÐÏÄÐÒÏÇÒÁÍÍ. + +ëÏÍÍÅÒÞÅÓËÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÜÔÏÊ ÂÉÂÌÉÏÔÅËÉ ×ÏÚÍÏÖÎÏ Ó ÐÒÉ×ÌÅÞÅÎÉÅÍ +Å\"Å Á×ÔÏÒÁ. + +\section*{ðÒÉÞÉÎÙ ÓÏÚÄÁÎÉÑ É ÉÓÔÏÒÉÑ ÒÁÚ×ÉÔÉÑ} + +äÌÑ ÌÀÄÅÊ, ËÏÔÏÒÙÅ ÈÏÔÑ ÂÙ ÏÄÉÎ ÒÁÚ ÐÉÓÁÌÉ ÐÒÏÇÒÁÍÍÕ Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ +ÓÉÓÔÅÍÎÙÈ ×ÙÚÏ×Ï× ÔÉÐÁ socket, connect, bind.... ÎÅ ÓÅËÒÅÔ, ÞÔÏ ÐÏÞÔÉ ×ÓÅÇÄÁ +ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔØ ×ÙÚÏ×Ï× ÆÕÎËÃÉÊ ÄÌÑ ÓÏÚÄÁÎÉÑ ÓÏÅÄÉÎÅÎÉÑ ÐÏ ÐÒÏÔÏËÏÌÕ TCP ÏÄÎÁ É ÔÁ ÖÅ. ïÔÓÀÄÁ ×ÏÚÎÉËÁÅÔ ÒÅÚÏÎÎÙÊ +×ÏÐÒÏÓ ``á ÐÏÞÅÍÕ ÓÏÂÓÔ×ÅÎÎÏ ÎÅ ÉÍÅÔØ ÂÉÂÌÉÏÔÅËÉ ÂÏÌÅÅ ×ÙÓÏËÏÇÏ +ÕÒÏ×ÎÑ, ÄÌÑ ÕÐÒÏÝÅÎÉÑ ÐÒÏÃÅÓÓÁ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÑ?''. +üÔÏ ÐÏÓÌÕÖÉÌÏ ÐÒÉÞÉÎÏÊ ÓÏÚÄÁÎÉÑ \ts{libftp}. + +ðÏÓÌÅ ÒÅÁÌÉÚÁÃÉÉ ``ÎÉÖÎÅÊ'' ÞÁÓÔÉ ÂÉÂÌÉÏÔÅËÉ, ÂÙÌÉ ÓÏÚÄÁÎÙ +ÆÕÎËÃÉÉ ÂÏÌÅÅ ×ÙÓÏËÏÇÏ ÕÒÏ×ÎÑ, ÔÁËÉÅ ËÁË +ÐÅÒÅÄÁÞÁ ÃÅÌÏÇÏ ÆÁÊÌÁ ÉÌÉ ÞÔÅÎÉÅ ÓÐÉÓËÁ ÆÁÊÌÏ×. ðÒÉ ÎÁÐÉÓÁÎÉÉ +ÜÔÉÈ ÐÒÏÃÅÄÕÒ ×ÏÚÎÉËÌÁ ÎÅÏÂÈÏÄÉÍÏÓÔØ ÕÄÏÂÎÏÊ ÏÔÌÁÄËÉ ÓÂÏÊÎÙÈ ÓÌÕÞÁÅ×, +ÄÌÑ ÏÓ×ÏÂÏÖÄÅÎÉÑ ÐÒÏÇÒÁÍÍÙ ÏÔ ÂÅÓËÏÎÅÞÎÏÇÏ ÞÉÓÌÁ ÕÓÌÏ×ÉÊ +(ÏÂÒÁÂÏÔËÁ ×ÏÚ×ÒÁÝÁÅÍÏÇÏ +ÂÉÂÌÉÏÔÅÞÎÙÍÉ ÆÕÎËÃÉÑÍÉ ÓÔÁÔÕÓÁ). +äÌÑ ÜÔÏÇÏ ÂÙÌ ÓÏÚÄÁÎ ÍÁËÒÏÓ \ts{EXIT}, ËÏÔÏÒÙÊ ÐÒÉ ×ÏÚ×ÒÁÔÅ ÆÕÎËÃÉÑÍÉ ÓÔÁÔÕÓÁ, +ÐÒÏ×ÅÒÑÅÔ ÅÇÏ, É × ÓÌÕÞÁÅ ÎÅÏÂÈÏÄÉÍÏÓÔÉ ×ÙÚÙ×ÁÅÔ ÚÁÒÁÎÅÅ ÕÓÔÁÎÏ×ÌÅÎÎÙÅ +ÆÕÎËÃÉÉ. + +ðÒÉ ÐÅÒÅÄÁÞÉ ÆÁÊÌÏ× ÐÏ ÓÅÔÉ, ËÏÔÏÒÁÑ × ÏÓÎÏ×ÎÏÍ ÓÏÓÔÏÉÔ ÉÚ dialup-slip'Ï× +(ÔÉÐÉÞÎÁÑ ÓÉÔÕÁÃÉÑ ÄÌÑ exUSSR) +ÞÁÓÔÏ ×ÏÚÎÉËÁÀÔ ÓÉÔÕÁÃÉÉ ``ÐÏÌÏÍËÉ ÓÅÔÉ'' É ÆÁÊÌ ÂÏÌØÛÏÇÏ ÒÁÚÍÅÒÁ ÐÅÒÅÄÁÔØ +ÓÔÁÎÏ×ÉÔÓÑ ÐÒÁËÔÉÞÅÓËÉ ÎÅ×ÏÚÍÏÖÎÏ\footnote{ëÏÎÅÞÎÏ ÍÏÖÎÏ ÐÅÒÉÏÄÉÞÅÓËÉ +ÚÁÐÕÓËÁÔØ ftp, É ÇÏ×ÏÒÉÔØ × ÎÅÍ ``reget filename''}, ÜÔÏ ÐÏÓÌÕÖÉÌÏ ÐÒÉÞÉÎÏÊ +ÎÁÐÉÓÁÎÉÑ ÐÒÏÇÒÁÍÍÙ \toindex{ftptry}\footnote{ðÒÏÇÒÁÍÍÁ \ts{ftptry} ÂÕÄÅÔ ÏÐÉÓÁÎÁ ÎÉÖÅ} Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ ÂÉÂÌÉÏÔÅËÉ libftp. +äÌÑ Å\"Å ÒÅÁÌÉÚÁÃÉÉ × ÂÉÂÌÉÏÔÅËÕ ÂÙÌÉ ÄÏÂÁ×ÌÅÎÙ ÆÕÎËÃÉÉ +\toindex{FtpRestorTimeout} É \toindex{FtpReretrTimeout}, +ËÏÔÏÒÙÅ × ÏÔÌÉÞÉÉ ÏÔ ÆÕÎËÃÉÊ \ts{FtpStorTimeout} É \ts{FtpRetrTimeout} +ÎÅ ÐÅÒÅÄÁÀÔ Á ÄÏËÁÞÉ×ÁÀÔ ÆÁÊÌÙ. + +\section*{îÅÄÏÓÔÁÔËÉ - ÄÌÑ ÉÓÐÒÁ×ÌÅÎÉÑ × ÓÌÅÄÕÀÝÉÈ ×ÅÒÓÉÑÈ} + +\begin{itemize} + +\item ÷ ÐÒÏÃÅÄÕÒÁÈ ÞÔÅÎÉÑ ÐÏÔÏËÁ ÉÚ socket'Ï× ÉÓÐÏÌØÚÕÅÔÓÑ ÍÅÈÁÎÉÚÍÙ +setjmp-longjmp, alarm+SIGALRM, SIGIO, ËÏÔÏÒÙÅ ÂÕÄÕÔ ÚÁÍÅÎÅÎÙ ÎÁ select. +üÔÏÔ ÎÅÄÏÓÔÁÔÏË (ÉÓÐÏÌØÚÏ×ÁÎÉÅ SIGALRM) ÐÒÏÑ×ÌÑÅÔÓÑ ÐÒÉ ÒÁÂÏÔÅ Ó X11 +\footnote{ÔÁÍ ÔÏÖÅ ÉÓÐÏÌØÚÕÅÔÓÑ alarm} + +\item ðÅÒÅÍÅÎÎÁÑ FtpDataStart\footnote{ó ËÁËÏÇÏ ÂÁÊÔÁ ÐÅÒÅÄÁ×ÁÔØ ÆÁÊÌÙ} ÎÅ ÐÒÉÎÁÄÌÅÖÉÔ ÓÔÒÕËÔÕÒÅ FTP, Á Ñ×ÌÑÅÔÓÑ ÏÂÛÅÊ ÄÌÑ ×ÓÅÈ. + +\item ïÔÓÕÔÓÔ×ÉÅ ÒÁÂÏÔÙ Ó \toindex{site-specific} ftpd ËÏÍÁÎÄÁÍÉ +\end{itemize} + +\section*{éÄÅÉ ÄÌÑ ÄÁÌØÎÅÊÛÉÈ ÒÅÁÌÉÚÁÃÉÉ} + +\begin{itemize} + +\item òÁÚÒÁÂÏÔËÁ ÐÒÏÇÒÁÍÍÙ ÄÕÂÌÉÒÏ×ÁÎÉÑ ÄÅÒÅ×Á +ÄÉÒÅËÔÏÒÉÊ ÏÄÎÏÊ ÍÁÛÉÎÙ ÎÁ ÄÒÕÇÕÀ. \footnote{òÁÚÒÁÂÏÔËÁ ÉÄÅÔ × ÄÁÎÎÙÊ ÍÏÍÅÎÔ} + +\item òÁÚÒÁÂÏÔËÁ ÉÎÔÅÒÆÅÊÓÁ × ÏËÒÕÖÅÎÉÉ X-window's ÄÌÑ ÍÁÎÉÐÕÌÑÃÉÉ +ÆÁÊÌÁÍÉ ÎÁÈÏÄÑÝÉÈÓÑ ÎÁ ÒÁÚÎÙÈ ÍÁÛÉÎÁÈ Ó ×ÏÚÍÏÖÎÏÓÔØÀ ÎÅÉÎÔÅÒÁËÔÉ×ÎÏÊ ÐÅÒÅÄÁÞÉ +(ÄÌÑ ÍÅÄÌÅÎÎÙÈ ÓÅÔÅÊ) + +\item óÏÚÄÁÎÉÅ ÍÕÌØÔÉÐÌÅËÓÉÒÕÀÝÅÇÏ ÁÐÐÁÒÁÔÁ ÄÌÑ ÏÄÎÏ×ÒÅÍÅÎÎÏÊ +ÏÂÒÁÂÏÔËÉ ÎÅÓËÏÌØËÉÈ ÐÏÔÏËÏ× ÄÁÎÎÙÈ. + +\item óÏÚÄÁÎÉÅ ÏÂßÅËÔÁ FTP ÄÌÑ C++ + +\end{itemize} + +\section*{÷×ÅÄÅÎÉÅ} + +âÉÂÌÉÏÔÅËÁ ``libftp'' ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÄÌÑ ÎÁÐÉÓÁÎÉÑ ÐÒÉËÌÁÄÎÙÈ ÐÒÏÇÒÁÍÍ × ËÏÔÏÒÙÈ +ÓÕÝÅÓÔ×ÕÅÔ ÎÅÏÂÈÏÄÉÍÏÓÔØ ÐÅÒÅÄÁ×ÁÔØ ÆÁÊÌÙ ÐÏ ÓÅÔÉ TCP/IP. OÎÁ +Ñ×ÌÑÅÔÓÑ ÎÁÂÏÒÏÍ ÆÕÎËÃÉÊ ÎÁÞÉÎÁÑ ÏÔ ÐÒÉÍÉÔÉ×ÎÙÈ ÆÕÎËÃÉÊ, ÔÁËÉÈ ËÁË ÏÔËÒÙÔÉÅ ÓÏÅÄÉÎÅÎÉÑ ÐÏ ÐÒÏÔÏËÏÌÕ FTP ÎÁ ÕÄÁÌÅÎÎÕÀ ÍÁÛÉÎÕ, ÄÏ ÆÕÎËÃÉÊ ×ÙÓÏËÏÇÏ ÕÒÏ×ÎÑ, ËÏÔÏÒÙÅ ÐÅÒÅÄÁÀÔ +ÆÁÊÌÙ ÓÁÍÉ ÐÒÏÉÚ×ÏÄÑ ÓÏÅÄÉÎÅÎÉÅ/ÒÁÚßÅÄÉÎÅÎÉÅ Ó ÓÅÒ×ÅÒÏÍ. +÷ÓÅ ÆÕÎËÃÉÉ ÉÍÅÀÔ ÐÒÏÔÏÔÉÐÙ × ÆÁÊÌÅ \toindex{FtpLibrary.h}, +ËÏÔÏÒÙÊ ÄÏÌÖÅÎ ÂÙÔØ ÐÏÍÅÝÅÎ +× ËÁÔÁÌÏÇ ÓÔÁÎÄÁÒÔÎÙÈ ÚÁÇÏÌÏ×ËÏ×\footnote{îÁÐÒÉÍÅÒ /usr/include}. +üÔÉ ÐÒÏÔÏÔÉÐÙ ÐÒÁËÔÉÞÅÓËÉ ÐÏÌÎÏÓÔØÀ ÏÐÉÓÙ×ÁÀÔ +ÎÁÚÎÁÞÅÎÉÅ ÆÕÎËÃÉÊ É ÉÈ ÁÒÇÕÍÅÎÔÙ, ÎÏ ÔÅÍ ÎÅ ÍÅÎÅÅ ÎÅÏÂÈÏÄÉÍÏ ÓËÁÚÁÔØ Ï ÏÂÝÅÊ ÉÄÅÏÌÏÇÉÉ +ÐÏÓÔÒÏÅÎÉÑ ÂÉÂÌÉÏÔÅËÉ É ÅÅ ËÏÍÐÏÎÅÎÔ. + +÷ÓÑ ÂÉÂÌÉÏÔÅËÁ, Ñ×ÌÑÑÓØ ËÌÉÅÎÔÏÍ, ÉÓÐÏÌØÚÕÅÔ +Ó ÐÒÏÔÉ×ÏÐÏÌÏÖÎÏÊ ÓÔÏÒÏÎÙ ÓÏÅÄÉÎÅÎÉÑ ÓÔÁÎÄÁÒÔÎÙÊ \toindex{FTPD} +\footnote{äÌÑ ÒÁÂÏÔÙ ÆÕÎËÃÉÊ FtpRertrTimeout, FtpRestorTimeout ÎÅÏÂÈÏÄÉÍÏ +ÞÔÏÂÙ ÓÅÒ×ÅÒ ÏÔÒÁÂÁÔÙ×ÁÌ ËÏÍÁÎÄÕ REST}. + +÷Ï ÍÎÏÇÉÈ ÏÐÅÒÁÃÉÏÎÎÙÈ ÓÉÓÔÅÍÁÈ ÓÕÝÅÓÔ×ÕÅÔ ÐÒÏÂÌÅÍÁ ÏÂÒÁÂÏÔËÉ +ÒÁÚÎÏÇÏ ÒÏÄÁ ÏÛÉÂÏË, × ÔÏÍ ÞÉÓÌÅ ÏÛÉÂÏË +××ÏÄÁ/×Ù×ÏÄÁ, × ÄÁÎÎÏÍ ÉÎÓÔÒÕÍÅÎÔÁÒÉÉ ÉÓÐÏÌØÚÏ×ÁÎ ÅÄÉÎÙÊ ÍÅÈÁÎÉÚÍ ×ÏÚ×ÒÁÔÁ +ÒÅÚÕÌØÔÁÔÁ ÒÁÂÏÔÙ ÌÀÂÏÊ ÆÕÎËÃÉÉ (ÍÁËÒÏËÏÍÁÎÄÁ \ts{EXIT}, ÏÐÒÅÄÅÌÅÎÎÁÑ × \ts{FtpLibrary.h}) +ËÏÔÏÒÙÊ ÐÏÚ×ÏÌÑÅÔ +ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ ÕÓÔÁÎÏ×É× Ó×ÏÉ ÉÌÉ ÓÔÁÎÄÁÒÔÎÙÅ ÆÕÎËÃÉÉ ÏÂÒÁÂÏÔËÉ +ÏÛÉÂÏË É ÆÕÎËÃÉÉ +ÏÔÌÁÄËÉ, ÐÉÓÁÔØ ÓÍÙÓÌÏ×ÕÀ ÞÁÓÔØ ÐÒÏÇÒÁÍÍÙ, ÄÕÍÁÑ ÔÏÌØËÏ Ï ÅÅ ÍÅÔÏÄÅ ÒÁÂÏÔÙ +× ÉÄÅÁÌØÎÙÈ ÕÓÌÏ×ÉÑÈ. ÷ ÆÕÎËÃÉÑÈ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ × ÏÂÅ ÓÔÏÒÏÎÙ ÓÕÝÅÓÔ×ÕÅÔ +×ÏÚÍÏÖÎÏÓÔØ ÕÓÔÁÎÏ×ÉÔØ ÍÁËÓÉÍÁÌØÎÏÅ ×ÒÅÍÑ ÏÖÉÄÁÎÉÑ ÐÏÔÏËÁ ÄÁÎÎÙÈ, ÐÏ ÉÓÔÅÞÅÎÉÉ ËÏÔÏÒÏÇÏ, ×ÏÚÍÏÖÎÏ ×ÙÚ×ÁÔØ ÏÐÒÅÄÅÌÅÎÎÕÀ ÐÒÏÃÅÄÕÒÕ. + + +ðÒÉ ÒÁÂÏÔÅ Ó ÂÉÂÌÉÏÔÅËÏÊ, ÐÅÒ×ÏÊ ×ÓÅÇÄÁ ×ÙÚÙ×ÁÅÔÓÑ ÐÒÏÃÅÄÕÒÁ +ÓÏÅÄÉÎÅÎÉÑ Ó ÓÅÒ×ÅÒÏÍ\footnote{úÁ ÉÓËÌÀÞÅÎÉÅÍ FtplibDebug} (\ts{FtpLogin} ÉÌÉ \ts{FtpConnect}) +ËÏÔÏÒÁÑ ×ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ×ÎÏ×Ø ÓÏÚÄÁÎÎÕÀ ÓÔÒÕËÔÕÒÕ ÄÁÎÎÙÈ (ÔÉÐÁ \ts{FTP}) +Ï ÓÏÅÄÉÎÅÎÉÉ Ó ÓÅÒ×ÅÒÏÍ. + + + + +\section{óÔÒÕËÔÕÒÁ ÄÁÎÎÙÈ FTP} + + +\tc{int \toindex{sock}}{--- ÄÅÓËÒÉÐÔÏÒ ËÁÎÁÌÁ ÐÅÒÅÄÁÞÉ ËÏÍÁÎÄ ÎÁ ÓÅÒ×ÅÒ;} +\tc{FILE *\toindex{data}}{--- ÏÐÉÓÁÎÉÅ ËÁÎÁÌÁ ÄÌÑ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ ÎÁ ÓÅÒ×ÅÒ;} +\tc{int \toindex{errno}}{ --- ÚÎÁÞÅÎÉÅ ÐÏÓÌÅÄÎÅÇÏ ×ÏÚ×ÒÁÝÅÎÎÏÇÏ ÂÉÂÌÉÏÔÅËÏÊ ÚÎÁÞÅÎÉÑ. + ÷ ÓÌÕÞÁÅ ÅÓÌÉ ÏÎÏ ÏÔÒÉÃÁÔÅÌØÎÏ ÉÌÉ ÒÁ×ÎÏ ÎÕÌÀ, + ÔÏ ÐÒÏÉÚÏÛÌÁ ÏÛÉÂËÁ;} +\tc{char \toindex{mode}}{--- ÔÉÐ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ;} +\tc{int ch}{--- ×ÓÐÏÍÏÇÁÔÅÌØÎÁÑ ÐÅÒÅÍÅÎÎÁÑ ÉÓÐÏÌØÚÕÅÍÁÑ ÄÌÑ ÐÒÅÏÂÒÁÚÏ×ÁÎÉÑ + ÐÏÔÏËÁ × ÒÅÖÉÍÅ ÐÅÒÅÄÁÞÉ ÔÅËÓÔÏ×ÙÈ ÆÁÊÌÏ×;} +\tc{STATUS (*func)()}{--- ÁÄÒÅÓ ÆÕÎËÃÉÉ, ËÏÔÏÒÁÑ ×ÙÚÙ×ÁÅÔÓÑ × ÓÌÕÞÁÅ ËÏÇÄÁ ÏÔ ÓÅÒ×ÅÒÁ + ÐÏÌÕÞÅÎ ÏÔ×ÅÔ Ï ÏÛÉÂËÅ;} +\tc{STATUS (*debug)()}{--- ÁÄÒÅÓ ÆÕÎËÃÉÉ, ËÏÔÏÒÁÑ ×ÙÚÙ×ÁÅÔÓÑ ÄÌÑ ÏÔÌÁÄËÉ ÐÒÏÔÏËÏÌÁ;} +\tc{STATUS (*IO)()}{--- ÆÕÎËÃÉÑ ×ÙÚÙ×ÁÅÍÁÑ × ÓÌÕÞÁÅ ÐÏÔÅÒÉ Ó×ÑÚÉ Ó ÓÅÒ×ÅÒÏÍ, ÉÌÉ + ÐÏ ÉÓÔÅÞÅÎÉÀ ÍÁËÓÉÍÁÌØÎÏÇÏ ×ÒÅÍÅÎÉ ÎÁ ÐÒÉÅÍ/ÐÅÒÅÄÁÞÕ ÏÄÎÏÇÏ + ÓÉÍ×ÏÌÁ.} + + +\section{ ðÒÏÃÅÄÕÒÙ ÓÏÅÄÉÎÅÎÉÑ/ÒÁÚßÅÄÉÎÅÎÉÑ Ó ÓÅÒ×ÅÒÏÍ} + +\ttt{STATUS \toindex{FtpConnect}(FTP~**, char~*hostname +\footnote{éÍÑ ÍÁÛÉÎÙ ÍÏÖÅÔ ÂÙÔØ ËÁË ÓÉÍ×ÏÌØÎÏÅ ÔÁË É ÃÉÆÒÏ×ÏÅ, ÎÁÐÒÉÍÅÒ +\ts{dxcern.cern.ch} ÉÌÉ \ts{128.141.201.96}} +)} +{ + óÏÚÄÁÅÔ ËÁÎÁÌ ÓÏÅÄÉÎÅÎÉÑ Ó ÓÅÒ×ÅÒÏÍ, ÎÁÈÏÄÑÝÉÍÓÑ ÎÁ ÍÁÛÉÎÅ hostname, + É ÓÏÚÄÁÅÔ ÓÔÒÕËÔÕÒÕ FTP, ×ÏÚ×ÒÁÝÁÑ ÎÁ ÎÅÅ ÕËÁÚÁÔÅÌØ. åÓÌÉ ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ + ÂÙÌÁ ×ÙÐÏÌÎÅÎÁ ÐÒÏÃÅÄÕÒÁ \toindex{FtplibDebug}(1), + ÔÏ ÄÏ ÓÏÅÄÉÎÅÎÉÑ Ó ÓÅÒ×ÅÒÏÍ ×ËÌÀÞÁÅÔ ÓÔÁÎÄÁÒÔÎÙÅ + ÐÏÄÐÒÏÇÒÁÍÍÙ ÏÂÒÁÂÏÔËÉ ÏÛÉÂÏË \toindex{FtpDebugDebug}, \toindex{FtpDebugError}, + \toindex{FtpDebugIO} \look{debug}. +} +\ttt{STATUS \toindex{FtpUser}(FTP~*, char~*user)} +{ + ðÏÓÙÌÁÅÔ ÓÅÒ×ÅÒÕ ÉÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ. òÁÎÅÅ ÄÏÌÖÎÏ ÂÙÌÏ ÂÙÔØ ÐÒÏÉÚ×ÅÄÅÎÏ ÓÏÅÄÉÎÅÎÉÅ +} + +\ttt{STATUS \toindex{FtpPassword}(FTP~*, char~*password)} +{ + ðÏÓÙÌÁÅÔ ÓÅÒ×ÅÒÕ ÐÁÒÏÌØ. òÁÎÅÅ ÄÏÌÖÎÁ ÂÙÌÁ ÂÙÔØ ×ÙÐÏÌÎÅÎÁ ÐÒÏÃÅÄÕÒÁ \ts{FtpUser} +}\ttt{STATUS \toindex{FtpAccount}(FTP~*, char~*acct)} +{ + ðÏÓÙÌÁÅÔ ÓÅÒ×ÅÒÕ ÉÍÑ account'a üÔÁ ÆÕÎËÃÉÑ ÓÄÅÌÁÎÁ ÄÌÑ ÐÏÌÎÏÇÏ ÓÏÏÔ×ÅÔÓÔ×ÉÑ + ÂÉÂÌÉÏÔÅËÉ ÐÒÏÔÏËÏÌÕ \ts{FTP}, ÎÏ Ô.Ë. ÍÁÌÏ ÔÁËÉÈ ÏÐÅÒÁÃÉÏÎÎÙÈ ÓÉÓÔÅÍ × ËÏÔÏÒÙÈ ÎÅÏÂÈÏÄÉÍ ÜÔÏÔ + ÁÔÒÉÂÕÔ ÐÏÌØÚÏ×ÁÔÅÌÑ ÔÏ ÆÕÎËÃÉÑ \ts{FtpAccount} × ÏÂÝÅÍ ÔÏ ÎÅ ÎÕÖÎÁ. + ðÒÅÄ×ÁÒÉÔÅÌØÎÏ ÄÏÌÖÎÁ ÂÙÌÁ ÂÙÔØ ×ÙÐÏÌÎÅÎÁ ÐÒÏÃÅÄÕÒÁ + \ts{FtpUser}. +} + +\ttt{ +STATUS \toindex{FtpLogin}(FTP~**, char~*hostname, char~*user, char~*password, char~*account)} +{ + ðÏÓÌÅÄÏ×ÁÔÅÌØÎÏ ×ÙÐÏÌÎÑÅÔ ÐÒÏÃÅÄÕÒÙ \ts{FtpConnect}, \ts{FtpUser}, \ts{FtpPassword}, \ts{FtpAccount} +(ÅÓÌÉ ÐÁÒÁÍÅÔÒ account ÒÁ×ÅÎ NULL, ÔÏ ÐÒÏÃÅÄÕÒÁ FtpAccount ÎÅ ×ÙÚÙ×ÁÅÔÓÑ)} + +\ttt{STATUS \toindex{FtpBye}(FTP~*)} +{ úÁ×ÅÒÛÁÅÔ ÓÅÁÎÓ ÒÁÂÏÔÙ Ó ÓÅÒ×ÅÒÏÍ \footnote{ëÁË ×ÉÄÎÏ ÉÚ ÏÐÉÓÁÎÉÑ ÐÒÏÃÅÄÕÒ ÓÏÅÄÉÎÅÎÉÑ/ÒÁÚßÅÄÉÎÅÎÉÑ ÉÚ ÏÄÎÏÊ ÐÒÏÇÒÁÍÍÙ ÍÏÖÎÏ ÏÄÎÏ×ÒÅÍÅÎÎÏ ÓÏÅÄÉÎÑÔÓÑ Ó ÎÅÓËÏÌØËÉÍÉ ÓÅÒ×ÅÒÁÍÉ} } + + + + +\section{ðÒÏÃÅÄÕÒÙ ÏÔÌÁÄËÉ ÐÒÏÇÒÁÍÍÙ} \label{debug} + +óÕÝÅÓÔ×ÕÅÔ ×ÏÚÍÏÖÎÏÓÔØ ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ ÏÐÒÅÄÅÌÉÔØ ÔÒÉ +ÐÒÏÃÅÄÕÒÙ:~\footnote{åÓÌÉ × ÌÀÂÕÀ ÉÚ ÆÕÎËÃÉÊ, ÏÐÉÓÁÎÎÙÈ ÎÉÖÅ, ×ÍÅÓÔÏ ÐÁÒÁÍÅÔÒÁ function ÐÅÒÅÄÁÔØ ÚÎÁÞÅÎÉÅ \ts{NULL}, ÔÏ ÜÔÏ ÂÕÄÅÔ ÏÚÎÁÞÁÔØ +ÏÔËÌÀÞÅÎÉÅ ÏÔÌÁÄËÉ. ðÒÉ ÏÔËÌÀÞÅÎÎÏÊ ÏÔÌÁÄËÅ ÒÅÚÕÌØÔÁÔ ÒÁÂÏÔÙ ÍÏÖÎÏ +ÏÐÒÅÄÅÌÉÔØ ÉÌÉ ÖÅ ÐÏ ×ÏÚ×ÒÁÝÁÅÍÏÍÕ ÆÕÎËÃÉÅÊ ÚÎÁÞÅÎÉÀ (åÓÌÉ ÏÎÁ ÔÉÐÁ \toindex{STATUS}) ÉÌÉ +ÐÏ ÐÅÒÅÍÅÎÎÏÊ errno × ÓÔÒÕËÔÕÒÅ \ts{FTP}} + +\ttt{\toindex{FtpSetDebugHandler}(FTP *,function)} +{ õÓÔÁÎÁ×ÌÉ×ÁÅÔ ÐÒÏÃÅÄÕÒÕ ÏÔÌÁÄËÉ ÐÒÏÔÏËÏÌÁ Ó ÕÄÁÌÅÎÎÙÍ ÓÅÒ×ÅÒÏÍ. + åÓÌÉ ÅÅ ÏÐÒÅÄÅÌÉÔØ, ÔÏ ÏÎÁ ×ÓÅÇÄÁ ÂÕÄÅÔ ×ÙÚÙ×ÁÅÔÓÑ ÉÚ ÓÔÁÎÄÁÒÔÎÏÊ ÆÕÎËÃÉÉ + ÐÒÉÅÍÁ/ÐÅÒÅÄÁÞÉ ÓÏÏÂÝÅÎÉÑ Ó/ÎÁ ÓÅÒ×ÅÒÁ. äÏÌÖÎÁ ÄÅÌÁÔØ ×ÏÚ×ÒÁÔ, ÎÏ × ÐÒÉÎÃÉÐÅ + ÉÍÅÅÔ ÐÏÌÎÏÅ ÐÒÁ×Ï ÐÒÅÒÙ×ÁÔØ ×ÙÐÏÌÎÅÎÉÅ ÐÒÏÇÒÁÍÍÙ × ÓÌÕÞÁÅ ÎÅÏÂÈÏÄÉÍÏÓÔÉ. +} + +\ttt{\toindex{FtpSetErrorHandler}(FTP *,function)} +{ + ïÐÒÅÄÅÌÑÅÔ ÆÕÎËÃÉÀ ÏÂÒÁÂÏÔËÉ ÏÛÉÂÏË. + ðÏÓÌÅ ÅÅ ÏÐÒÅÄÅÌÅÎÉÑ, × ÓÌÕÞÁÅ ×ÏÚ×ÒÁÝÅÎÉÑ ÓÅÒ×ÅÒÏÍ + ÎÅÕÄÏ×ÌÅÔ×ÏÒÉÔÅÌØÎÏÇÏ ÏÔ×ÅÔÁ, ÂÕÄÅÔ ×ÙÚÙ×ÁÔØÓÑ ÕËÁÚÁÎÎÁÑ ÆÕÎËÃÉÑ. + ðÒÉ ÜÔÏÍ ÚÎÁË Õ ËÏÄÁ ÏÛÉÂËÉ ÍÅÎÑÅÔÓÑ ÎÁ '-', É Ô.Ï. ÒÅÚÕÌØÔÁÔ + ÓÔÁÎÏ×ÉÔÓÑ ÍÅÎØÛÅ ÎÕÌÑ. +} +\ttt{\toindex{FtpSetIOHandler}(FTP *,function)} +{ + ïÐÒÅÄÅÌÅÎÉÅ ÆÕÎËÃÉÉ ÏÂÒÁÂÏÔËÉ ÏÛÉÂÏË ××ÏÄÁ/×Ù×ÏÄÁ. + ðÒÉ ÐÅÒÅÄÁÞÅ ÄÁÎÎÙÈ ÉÌÉ ËÏÍÁÎÄ ÎÁ ÓÅÒ×ÅÒ, ÍÏÖÅÔ ×ÏÚÎÉËÎÕÔØ ÓÉÔÕÁÃÉÑ ËÏÇÄÁ + Ó×ÑÚØ Ó ÓÅÒ×ÅÒÏÍ ÂÕÄÅÔ ÐÏÔÅÒÑÎÁ (ÓÀÄÁ ×ÈÏÄÑÔ ÐÒÁËÔÉÞÅÓËÉ ×ÓÅ ÓÂÏÉ ÓÅÔÉ + É ÓÂÏÉ ÐÒÉ ÒÁÂÏÔÅ ÓÅÒ×ÅÒÁ ÎÁ ÕÄÁÌÅÎÎÏÊ ÍÁÛÉÎÅ) ÐÒÉ ÜÔÏÍ ÂÕÄÅÔ ×ÙÚ×ÁÎÁ + ÕËÁÚÁÎÎÁÑ ÆÕÎËÃÉÑ. ïÎÁ ×ÙÚÙ×ÁÅÔÓÑ ÔÁË ÖÅ ÐÏ ÉÓÔÅÞÅÎÉÀ + ÍÁËÓÉÍÁÌØÎÏÇÏ ×ÒÅÍÅÎÉ ÐÒÉ ÏÖÉÄÁÎÉÉ ÏÞÅÒÅÄÎÏÇÏ ÓÉÍ×ÏÌÁ Ó ÓÅÒ×ÅÒÁ ×Ï ×ÒÅÍÑ + ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ. (\toindex{timeout}) +} + +\ttt{\toindex{FtpDebug}(FTP *)} +{ +ðÏÄËÌÀÞÅÎÉÅ ÓÔÁÎÄÁÒÔÎÙÈ ÆÕÎËÃÉÊ ÏÔÌÁÄËÉ ÐÒÏÔÏËÏÌÁ ÔÁËÉÈ ËÁË +\tc{\toindex{FtpDebugError}}{--- ÐÅÞÁÔÁÅÔ ÓÔÒÏËÕ ×ÏÚ×ÒÁÝÅÎÎÕÀ ÓÅÒ×ÅÒÏÍ É ÐÒÅÒÙ×ÁÅÔ ÐÒÏÇÒÁÍÍÕ;} +\tc{\toindex{FtpDebugDebug}}{--- ÐÅÞÁÔÁÅÔ ÓÔÒÏËÕ ×ÏÚ×ÒÁÝÅÎÎÕÀ ÓÅÒ×ÅÒÏÍ;} +\tc{\toindex{FtpDebugIO}}{--- ÐÅÞÁÔÁÅÔ ÓÔÒÏËÕ \ts{strerror(errno)} É ÐÒÅÒÙ×ÁÅÔ ÐÒÏÇÒÁÍÍÕ.} +} + +÷Ï ×ÓÅ ÐÒÏÃÅÄÕÒÙ ÐÅÒÅÄÁÀÔÓÑ ÔÒÉ ÁÒÇÕÍÅÎÔÁ:\\ +1. óÔÒÕËÔÕÒÁ \ts{FTP};\\ +2. úÎÁÞÅÎÉÅ ×ÏÚ×ÒÁÝÅÎÎÏÅ ÆÕÎËÃÉÅÊ, ÅÓÌÉ ÏÎÏ ÍÅÎØÛÅ ÅÄÉÎÉÃÙ ÔÏ ÐÒÏÉÚÏÛÌÁ ÏÛÉÂËÁ;\\ +3. óÉÍ×ÏÌØÎÏÅ ÓÏÏÂÝÅÎÉÅ Ï ÏÛÉÂËÅ (char *). + +\ttt{\toindex{FtplibDebug}(\ts{on} or \ts{off})} +{ ÷ËÌÀÞÁÅÔ/×ÙËÌÀÞÁÅÔ Á×ÔÏÍÁÔÉÞÅÓËÏÅ ×ËÌÀÞÅÎÉÅ ×ÓÅÈ ×ÉÄÏ× ÏÔÌÁÄËÉ ÐÒÉ + ×ÙÐÏÌÎÅÎÉÉ ÆÕÎËÃÉÉ \ts{FtpConnect(FtpLogin)}} +\section{ðÒÏÃÅÄÕÒÙ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ Ó ÓÅÒ×ÅÒÁ} + +\ttt{STATUS \toindex{FtpRetrTimeout}(FTP~*, char~*command, char~*inp, char~*out +\footnote{åÓÌÉ ÉÍÑ ÌÏËÁÌØÎÏÇÏ ÆÁÊÌÁ \ts{out} ÓÏ×ÐÁÄÅÔ ÓÏ ÓÔÒÏËÁÍÉ \ts{*STDIN*}, \ts{*STDOUT*}, \ts{*STDERR*} ÔÏ +×ÍÅÓÔÏ ÏÔËÒÙÔÉÑ ÎÏ×ÏÇÏ ÆÁÊÌÁ ÐÒÏÉÚÏÊÄÅÔ ÄÕÂÌÉÒÏ×ÁÎÉÅ ÐÏÔÏËÁ ÓÏÏÔ×ÅÔÓÔ×ÅÎÎÏ Ó ËÁÎÁÌÁÍÉ +\ts{stdin}, \ts{stdout}, \ts{stderr} (ïÂÒÁÂÏÔËÕ ÄÁÎÎÏÊ ÓÐÅÃÉÆÉËÁÃÉÉ ÆÁÊÌÏ× +ÐÒÏÉÚ×ÏÄÉÔ ÆÕÎËÃÉÑ \toindex{Ftpfopen}, ËÏÔÏÒÁÑ ÐÒÉ ÎÅÏÂÈÏÄÉÍÏÓÔÉ ÍÏÖÅÔ ÂÙÔØ ×ÙÚ×ÁÎÁ ÓÁÍÏÓÔÏÑÔÅÌØÎÏ, Ó ÔÁËÉÍÉ ÖÅ ÁÒÇÕÍÅÎÔÁÍÉ, ËÁË ÓÉÓÔÅÍÎÁÑ ÆÕÎËÃÉÑ fopen)}, + long~time)} +{ + ðÏÓÙÌÁÅÔ ËÏÍÁÎÄÕ \ts{command} ÎÁ ÓÅÒ×ÅÒ, ÐÒÉÞÅÍ ÅÓÌÉ × ËÏÍÁÎÄÅ + ×ÓÔÒÅÔÉÔÓÑ ÐÏÄÓÔÒÏËÁ \ps, ÔÏ ÎÁ ÅÅ ÍÅÓÔÏ ÂÕÄÅÔ ÐÏÄÓÔÁ×ÌÅÎÁ ÓÔÒÏËÁ \ts{inp}. + óÏÚÄÁÅÔ ËÁÎÁÌ ÄÌÑ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ, É ÔÏ ÞÔÏ ÂÕÄÅÔ ÐÅÒÅÄÁÎÏ + ÓÅÒ×ÅÒÏÍ × ÜÔÏÔ ËÁÎÁÌ ÂÕÄÅÔ ÓËÏÐÉÒÏ×ÁÎÏ × ÌÏËÁÌØÎÙÊ ÆÁÊÌ \ts{out}. + åÓÌÉ × ÔÅÞÅÎÉÉ ×ÒÅÍÅÎÉ \ts{time}(× ÓÅËÕÎÄÁÈ) + Ó ÓÅÒ×ÅÒÁ ÎÅ ÐÒÉÄÅÔ ÎÅ ÏÄÎÏÇÏ ÓÉÍ×ÏÌÁ, ÔÏ + ÆÕÎËÃÉÑ ×ÏÚ×ÒÁÔÉÔ ÓÔÁÔÕÓ ËÏÔÏÒÙÊ ÂÕÄÅÔ ÏÚÎÁÞÁÔØ ÏÛÉÂËÕ ××ÏÄÁ/×Ù×ÏÄÁ. + ÷ ÓÌÕÞÁÅ ËÏÇÄÁ \toindex{timeout}=0, + ÍÁËÓÉÍÁÌØÎÏÅ ×ÒÅÍÑ ÏÖÉÄÁÎÉÑ ÎÁ ÕÒÏ×ÎÅ ÂÉÂÌÉÏÔÅËÉ ÒÁ×ÎÏ + ÂÅÓËÏÎÅÞÎÏÓÔÉ, × ÜÔÏÍ ÓÌÕÞÁÅ ÏÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ ÍÏÖÅÔ ×ÏÚÎÉËÎÕÔØ + ÐÏ ÉÓÔÅÞÅÎÉÀ timeout'a × ÑÄÒÅ TCP/IP (ÉÌÉ ÓÉÓÔÅÍÙ). ôÁËÉÍ ÏÂÒÁÚÏÍ, ÅÓÌÉ \ts{timeout} × + ÐÁÒÁÍÅÔÒÅ time ÂÏÌØÛÅ ÞÅÍ timeout × ÑÄÒÅ TCP/IP, ÏÎ ÎÉËÏÇÄÁ + ÎÅ ÐÒÅÒ×ÅÔ ÐÅÒÅÄÁÞÕ ÄÁÎÎÙÈ. \footnote{\ts{Timeout} × ÑÄÒÁÈ ÒÁÚÎÙÈ TCP/IP(ÓÉÓÔÅÍÁÈ) ÒÁÚÎÙÊ} +} + +\ttt{STATUS \toindex{FtpReretrTimeout}(FTP~*, char~*command, char~*inp, char~*out, long~time)} +{ + ðÒÏÉÚ×ÏÄÉÔ Ôo ÖÅ ÓaÍÏÅ ÄÅÊÓÔ×ÉÅ ÞÔÏ É ÆÕÎËÃÉÑ \ts{FtpRetrTimeout}, ÚÁ +ÉÓËÌÀÞÅÎÉÅ ÔÏÇÏ, ÞÔÏ ÐÅÒÅÄ ÐÅÒÅÄÁÞÅÊ ÐÒÏ×ÅÒÑÅÔÓÑ ÆÁÊÌ \ts{out}, É × ÓÌÕÞÁÅ +ÅÇÏ ÓÕÝÅÓÔ×Ï×ÁÎÉÑ ÐÅÒÅÄÁÞÁ Ó ÓÅÒ×ÅÒÁ ÎÁÞÉÎÁÅÔÓÑ Ó ÂÁÊÔÁ Ó ÎÏÍÅÒÏÍ \ts{<ÒÁÚÍÅÒ ÆÁÊÌÁ out>}+1.} +\ttt{\toindex{FtpRetr}(FTP~*, char~*command, char~*inp, char~*out)} +{ + ÷ÙÚÙ×ÁÅÔ ÔÏ ÖÅ ÄÅÊÓÔ×ÉÅ ÞÔÏ É FtpRetrTimeout, ÎÏ Ó ×ÙËÌÀÞÅÎÎÙÍ timeout'ÏÍ. +} + +\ttt{\toindex{FtpGetTimeout}(FTP~*, char~*inp, char~*out, long~time)} +{ + ðÅÒÅÄÁÅÔ Ó ÓÅÒ×ÅÒÁ ÆÁÊÌ \ts{inp} × ÌÏËÁÌØÎÙÊ ÆÁÊÌ \ts{out}, ÐÒÉ ÜÔÏÍ ÕÓÔÁÎÁ×ÌÉ×ÁÅÔÓÑ + \ts{timeout=time}. +} + +\ttt{\toindex{FtpGet}(FTP~*, char~*in, char~*out)} +{ + ÷ÙÚÙ×ÁÅÔ ÆÕÎËÃÉÀ \ts{FtpGetTimeout} Ó ×ÙËÌÀÞÅÎÎÙÍ ÍÁËÓÉÍÁÌØÎÙÍ ×ÒÅÍÅÎÅÍ +ÏÖÉÄÁÎÉÑ ÄÁÎÎÙÈ} + +\ttt{\toindex{FtpDirectory}(FTP~*, char~*pat\footnote{üÔÏ ÐÅÒ×ÙÊ ÁÒÇÕÍÅÎÔ ÄÌÑ ËÏÍÁÎÄÙ ls(dir)}, char~*out)} +{ + ðÅÒÅÄÁÅÔ ÓÏÄÅÒÖÉÍÏÅ ÄÉÒÅËÔÏÒÉÉ, ÏÐÉÓÁÎÎÏÇÏ ÐÁÒÁÍÅÔÒÏÍ \ts{pat}, Ó ÓÅÒ×ÅÒÁ × ÆÁÊÌ \ts{out}. +} +\ttt{\toindex{FtpDir}(FTP~*, char~*out)} +{ + ðÅÒÅÄÁÅÔ ÓÏÄÅÒÖÉÍÏÅ ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ Ó ÓÅÒ×ÅÒÁ × ÆÁÊÌ \ts{out}. +} + +\section{ðÒÏÃÅÄÕÒÙ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ ÎÁ ÓÅÒ×ÅÒ} + +\ttt{\toindex{FtpStorTimeout}(FTP~*, char~*command, char~*inp, char~*out, long~time)} +{ + ðÅÒÅÄÁÅÔ ÓÏÄÅÒÖÉÍÏÅ ÌÏËÁÌØÎÏÇÏ ÆÁÊÌÁ \ts{inp} ÎÁ ÓÅÒ×ÅÒ, ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ ÐÏÓÌÁ× +ÅÍÕ ËÏÍÁÎÄÕ, ÓÏÓÔÁ×ÌÅÎÎÕÀ ÉÚ \ts{command} É \ts{out}. ðÁÒÁÍÅÔÒ \ts{time}, ÚÁÄÁÅÔ ÍÁËÓÉÍÁÌØÎÏÅ +×ÒÅÍÑ ÎÁ ÏÔÐÒÁ×ËÕ ÏÄÎÏÇÏ ÓÉÍ×ÏÌÁ. +} + +\ttt{STATUS \toindex{FtpRestorTimeout}(FTP~*, char~*command, char~*inp, char~*out, long~time)} +{ + ðÒÏÉÚ×ÏÄÉÔ Ôo ÖÅ ÓaÍÏÅ ÄÅÊÓÔ×ÉÅ ÞÔÏ É ÆÕÎËÃÉÑ \ts{FtpStorTimeout}, ÚÁ +ÉÓËÌÀÞÅÎÉÅ ÔÏÇÏ, ÞÔÏ ÐÅÒÅÄ ÐÅÒÅÄÁÞÅÊ ÐÒÏ×ÅÒÑÅÔÓÑ ÆÁÊÌ \ts{out} ÎÁ ÓÅÒ×ÅÒÅ, +É, × ÓÌÕÞÁÅ ÅÇÏ ÓÕÝÅÓÔ×Ï×ÁÎÉÑ, ÐÅÒÅÄÁÞÁ ÎÁ ÓÅÒ×ÅÒ ÎÁÞÉÎÁÅÔÓÑ Ó ÂÁÊÔÁ Ó ÎÏÍÅÒÏÍ \ts{<ÒÁÚÍÅÒ ÆÁÊÌÁ out>}+1.} + +\ttt{\toindex{FtpStor}(FTP~*, char~*command, char~*inp, char*~out)} +{ + ÷ÙÚÙ×ÁÅÔ ÚÁÐÕÓË ÐÒÏÃÅÄÕÒÙ \ts{FtpStorTimeout} Ó ÐÁÒÁÍÅÔÒÏÍ \ts{time=0}. +} + +\ttt{\toindex{FtpPutTimeout}(FTP~*, char~*in, char~*out, long~time)} +{ ðÅÒÅÄÁÅÔ ÌÏËÁÌØÎÙÊ ÆÁÊÌ \ts{in} ÎÁ ÓÅÒ×ÅÒ × ÆÁÊÌ Ó ÉÍÅÎÅÍ \ts{out}, ÐÒÉ ÜÔÏÍ \ts{timeout=time}} + +\ttt{\toindex{FtpPut}(FTP~*, char~*in, char~*out)} +{ + ÷ÙÚÙ×ÁÅÔ ÐÒÏÃÅÄÕÒÕ \ts{FtpPutTimeout} Ó ÐÁÒÁÍÅÔÒÏÍ \ts{time=0}} + + +\section{ðÒÏÃÅÄÕÒÙ ÞÔÅÎÉÑ/ÚÁÐÉÓÉ × ÆÁÊÌ ÎÁ ÓÅÒ×ÅÒÅ} + +äÌÑ ÔÏÇÏ, ÞÔÏÂÙ ÐÒÏÉÚ×ÏÄÉÔØ ××ÏÄ/×Ù×ÏÄ ÉÚ/× ÆÁÊÌÙ ËÏÔÏÒÙÅ ÎÁÈÏÄÑÔÓÑ ÎÁ ÓÅÒ×ÅÒÅ, +ÐÒÉÞÅÍ ÎÅ ËÏÐÉÒÕÑ ÉÈ ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ × ÌÏËÁÌØÎÙÊ ÆÁÊÌ, Á ÒÁÂÏÔÁÑ ÎÅÐÏÓÒÅÄÓÔ×ÅÎÎÏ Ó ÏÒÉÇÉÎÁÌÏÍ, +ÓÕÝÅÓÔ×ÕÅÔ ×ÏÚÍÏÖÎÏÓÔØ ÏÔËÒÙÔØ ÆÁÊÌ ÎÁ ÓÅÒ×ÅÒÅ ÎÁ ÞÔÅÎÉÅ/ÚÁÐÉÓØ/ÄÏÚÁÐÉÓØ É +ÚÁÔÅÍ Ó ÐÏÍÏÝØÀ ÏÂÙÞÎÙÈ ÐÒÏÃÅÄÕÒ ××ÏÄÁ/×Ù×ÏÄÁ ÉÌÉ ÖÅ ÐÒÉ ÐÏÍÏÝÉ ÐÒÏÃÅÄÕÒ +\ts{FtpRead} É \ts{FtpWrite}, ËÏÔÏÒÙÅ × ÏÔÌÉÞÉÉ ÏÔ ÐÅÒ×ÙÈ ÐÒÅÏÂÒÁÚÕÀÔ ÔÅËÓÔÏ×ÙÅ ÆÁÊÌÙ, +ÐÒÏÉÚ×ÏÄÉÔØ ÎÅÏÂÈÏÄÉÍÙÅ ÏÐÅÒÁÃÉÉ. +\footnote{åÓÔÅÓÔ×ÅÎÎÏ, ÔÁËÉÅ ÆÕÎËÃÉÉ ËÁË \ts{seek}, \ts{ioctl}, ... + ÄÌÑ ÜÔÉÈ ÆÁÊÌÏ× ÎÅÄÏÐÕÓÔÉÍÙ.} + + +\ttt{\toindex{FtpData}(FTP~*, char~*command, char~*param, char~*mode)} +{ óÏÚÄÁÅÔ ËÁÎÁÌ ÄÌÑ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ ÐÏÓÌÁ× ÓÅÒ×ÅÒÕ ËÏÍÁÎÄÕ ËÏÔÏÒÁÑ +ÓÏÓÔÁ×ÌÑÅÔÓÑ ÉÚ ÐÁÒÁÍÅÔÒÏ× \ts{command} É \ts{param}. ðÁÒÁÍÅÔÒ \ts{mode} ÕËÁÚÙ×ÁÅÔ ÍÏÖÅÔ ÂÙÔØ +ÉÌÉ ``r'' ÉÌÉ ``w''} + +\ttt{\toindex{FtpOpenRead}(FTP~*,char~*filename)} +{ ïÔËÒÙ×ÁÅÔ ÄÌÑ ÞÔÅÎÉÑ ÆÁÊÌ Ó ÉÍÅÎÅÍ \ts{filename} ÎÁ ÓÅÒ×ÅÒÅ } + +\ttt{\toindex{FtpOpenWrite}(FTP~*,char~*filename)} +{ ïÔËÒÙ×ÁÅÔ ÄÌÑ ÚÁÐÉÓÉ ÆÁÊÌ Ó ÉÍÅÎÅÍ \ts{filename} ÎÁ ÓÅÒ×ÅÒÅ } + +\ttt{\toindex{FtpOpenAppend}(FTP~*,char~*filename)} +{ ïÔËÒÙ×ÁÅÔ ÄÌÑ ÄÏÚÁÐÉÓÉ ÆÁÊÌ Ó ÉÍÅÎÅÍ \ts{filename} ÎÁ ÓÅÒ×ÅÒÅ } + +\ttt{\toindex{FtpOpenDir}(FTP~*, char~*files)} +{ + óÏÚÄÁÅÔ ËÁÎÁÌ ÄÌÑ ÞÔÅÎÉÑ ÕÄÁÌÅÎÎÏÇÏ ÌÉÓÔÉÎÇÁ ÄÉÒÅËÔÏÒÉÉ, ÐÁÒÁÍÅÔÒ files ÐÅÒÅÄÁÅÔÓÑ +ËÏÍÁÎÄÅ \ts{ls} ÎÁ ÓÅÒ×ÅÒÅ × ËÁÞÅÓÔ×Å 1-ÇÏ ÐÁÒÁÍÅÔÒÁ +} + +\ttt{int \toindex{FtpRead}(FTP~*)}{þÉÔÁÅÔ ÓÉÍ×ÏÌ ÉÚ ÐÏÔÏËÁ ÄÁÎÎÙÈ, ÅÓÌÉ ÂÙÌÁ ÕÓÔÁÎÏ×ÌÅÎÁ + ÔÅËÓÔÏ×ÁÑ ÍÏÄÁ ÐÅÒÅÄÁÞÉ \footnote{õÓÔÁÎÏ×ÌÅÎÁ ÐÏ ÕÍÏÌÞÁÎÉÀ.}, ÐÒÅÏÂÒÁÚÕÅÔ ÐÅÒÅÈÏÄÙ ÎÁ ÎÏ×ÕÀ ÓÔÒÏËÕ. ðÒÉ ÏÂÎÁÒÕÖÅÎÉÉ +ËÏÎÃÁ ÐÏÔÏËÁ ×ÏÚ×ÒÁÝÁÅÔ \toindex{EOF}} + +\ttt{\toindex{FtpGetString}(FTP~*, char~*str)} +{ þÔÅÎÉÅ ÏÄÎÏÊ ÓÔÒÏËÉ ÉÚ ÐÏÔÏËÁ ÄÁÎÎÙÈ ÐÒÉ ÐÏÍÏÝÉ ÆÕÎËÃÉÉ \ts{FtpRead}.} + +\ttt{\toindex{FtpWrite}(FTP~*, char~c)}{ðÉÛÅÔ ÓÉÍ×ÏÌ × ÐÏÔÏË ÄÁÎÎÙÈ, ÅÓÌÉ ÂÙÌÁ ÕÓÔÁÎÏ×ÌÅÎÁ + ÔÅËÓÔÏ×ÁÑ ÍÏÄÁ ÐÅÒÅÄÁÞÉ, ÐÒÅÏÂÒÁÚÕÅÔ ÐÅÒÅÈÏÄÙ ÎÁ ÎÏ×ÕÀ ÓÔÒÏËÕ. ðÒÉ ÏÂÎÁÒÕÖÅÎÉÉ +ÏÛÉÂËÉ ××ÏÄÁ/×Ù×ÏÄÁ ×ÏÚ×ÒÁÝÁÅÔ \toindex{EOF}} + +\ttt{\toindex{FtpClose}(FTP~*)} +{úÁËÒÙ×ÁÅÔ ÒÁÎÅÅ ÏÔËÒÙÔÙÊ ÐÏÔÏË ÄÁÎÎÙÈ.} + +\section{ëÏÍÁÎÄÙ ÄÌÑ ÓÅÒ×ÅÒÁ É ×ÓÐÏÍÏÇÁÔÅÌØÎÙÅ ÆÕÎËÃÉÉ} + +\ttt{\toindex{FtpCommand}(FTP~*, char~*command, char~*param, int~ok1, ok2, ok3, ..., okN, EOF)} +{ ðÏÓÙÌÁÅÔ ËÏÍÁÎÄÕ, ÓÏÓÔÁ×ÌÅÎÎÕÀ ÉÚ ÐÁÒÁÍÅÔÒÏ× \ts{command} É \ts{param}, É ÓÞÉÔÙ×ÁÅÔ +ÏÔ×ÅÔ ÓÅÒ×ÅÒÁ, ÅÓÌÉ ËÏÄ ÏÔ×ÅÔÁ ÎÅ ÓÏ×ÐÁÄÁÅÔ ÎÅ Ó ÏÄÎÉÍ ÚÎÁÞÅÎÉÅÍ \ts{ok}, ÔÏ +ÚÎÁË ËÏÄÁ ÏÔ×ÅÔÁ ÍÅÎÑÅÔÓÑ ÎÁ '-'. ÷ ÓÌÕÞÁÅ ÅÓÌÉ ÕÓÔÁÎÏ×ÌÅÎ handler ÏÂÒÁÂÏÔËÉ +ÏÛÉÂÏË ×ÙÚÙ×ÁÅÔ ÅÇÏ. +} + +\ttt{\toindex{FtpType}(FTP~*,char~*mode)} +{õÓÔÁÎÁ×ÌÉ×ÁÅÔ ÍÏÄÕ ÐÅÒÅÄÁÞÉ ÆÁÊÌÏ×, mode ÍÏÖÅÔ ÂÙÔØ ``A'', ``I'', ``S'',....} + +\ttt{\toindex{FtpBinary}(FTP~*)} +{õÓÔÁÎÁ×ÌÉ×ÁÅÔ Ä×ÏÉÞÎÕÀ ÍÏÄÕ ÐÅÒÅÄÁÞÉ ÆÁÊÌÏ×} + +\ttt{\toindex{FtpAscii}(FTP~*)} +{õÓÔÁÎÁ×ÌÉ×ÁÅÔ ÔÅËÓÔÏ×ÕÀ ÍÏÄÕ ÐÅÒÅÄÁÞÉ ÆÁÊÌÏ×} + + +\ttt{\toindex{FtpMkdir}(FTP~*,char *dirname)} +{óÏÚÄÁÅÔ ÄÉÒÅËÔÏÒÉÀ ÎÁ ÓÅÒ×ÅÒÅ} + +\ttt{\toindex{FtpChdir}(FTP~*,char *dirname)} +{íÅÎÑÅÔ ÁËÔÉ×ÎÕÀ ÄÉÒÅËÔÏÒÉÀ ÎÁ ÓÅÒ×ÅÒÅ} + +\ttt{\toindex{FtpRm}(FTP~*,char *filename)} +{õÄÁÌÑÅÔ ÆÁÊÌ ÎÁ ÓÅÒ×ÅÒÅ} + +\ttt{char~*\toindex{FtpPwd}(FTP~*)} +{÷ÏÚ×ÒÁÝÁÅÔ ÁËÔÉ×ÎÕÀ ÄÉÒÅËÔÏÒÉÀ ÎÁ ÓÅÒ×ÅÒÅ} + +\ttt{int \toindex{FtpSize}(FTP~*,char *filename)} +{÷ÏÚ×ÒÁÝÁÅÔ ÒÁÚÍÅÒ ÆÁÊÌÁ × ÂÁÊÔÁÈ, ÅÓÌÉ ÆÁÊÌ Ó ÕËÁÚÁÎÎÙÍ ÉÍÅÎÅÍ ÏÔÓÕÔÓÔ×ÕÅÔ, +ÔÏ ×ÏÚ×ÒÁÝÁÅÔÓÑ ÓÔÁÔÕÓ ÏÛÉÂËÉ, Ô.Å. ÚÎÁÞÅÎÉÅ ÍÅÎØÛÅ ÎÕÌÑ} + +\ttt{\toindex{FtpMove}(FTP~*,char *oldfilename, char *newfilename)} +{ðÅÒÅÉÍÅÎÏ×Ù×ÁÅÔ ÎÁ ÓÅÒ×ÅÒÅ ÆÁÊÌ \ts{oldfilename} × ÆÁÊÌ \ts{newfilename}} + +\ttt{\toindex{FtpPort}(FTP~*, int~a, int~b, int~c, int~d, int~e, int~f)} +{ëÏÍÁÎÄÁ ÓÅÒ×ÅÒÕ ÓÏÚÄÁÔØ ËÁÎÁÌ ÄÌÑ ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ. ðÒÉÞÅÍ \ts{a.b.c.d} ÜÔÏ IP ÁÄÒÅÓ +ËÌÉÅÎÔÁ Á \ts{e*256+f} ÎÏÍÅÒ ÐÏÒÔÁ.} + +\ttt{struct hostent *\toindex{FtpGetHost}(char *hostname)} +{÷ÏÚ×ÒÁÝÁÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÓÔÒÕËÔÕÒÕ ÔÉÐÁ hostent. + áÒÇÕÍÅÎÔ -- ÜÔÏ ÓÔÒÏËÁ ÓÏÄÅÒÖÁÝÁÑ ÉÌÉ ÉÍÑ ÍÁÛÉÎÙ, +ÉÌÉ ÅÅ IP ÁÄÒÅÓ × ÓÔÒÏÞÎÏÍ ×ÉÄÅ\footnote{îÁÐÒÉÍÅÒ: ``dxunk8.oea.ihep.su'' ÉÌÉ +``192.102.229.71''}.} + +\section{ðÏÄÐÒÏÇÒÁÍÍÙ ÐÅÒÅÄÁÞÉ ÓÏÏÂÝÅÎÉÊ ×/ÉÚ ÓÅÒ×ÅÒÁ} + +\ttt{\toindex{FtpSendMessage}(FTP~*, char~*message)} +{ðÏÓÙÌÁÅÔ ÓÏÏÂÝÅÎÉÅ ÓÅÒ×ÅÒÕ} + +\ttt{int \toindex{FtpGetMessage}(FTP~*)} +{ðÒÉÎÉÍÁÅÔ ÓÏÏÂÝÅÎÉÅ ÏÔ ÓÅÒ×ÅÒÁ É ×ÏÚ×ÒÁÝÁÅÔ ÅÇÏ ËÏÄ} + +\ttt{\toindex{FtpMessage}(int Number)} +{÷ÏÚ×ÒÁÝÁÅÔ ÐÏ ËÏÄÕ ÓÏÏÂÝÅÎÉÑ ÅÇÏ ÓÏÄÅÒÖÉÍÏÅ} + +\section{æÕÎËÃÉÉ ÐÏÌÎÏÇÏ ÓÅÁÎÓÁ ÒÁÂÏÔÙ} + +\ttt{FILE *\toindex{FtpFullOpen}(char *filename,char *mode)} +{ òÁÚÂÉÒÁÅÔ ÓÔÒÏËÕ filename, ËÏÔÏÒÁÑ ÄÏÌÖÎÁ ÂÙÔØ ÔÉÐÁ +\\ \ts{host/user/password:filename} ÉÌÉ ÖÅ ÔÉÐÁ \ts{filename}, × ÚÁ×ÉÓÉÍÏÓÔÉ ÏÔ ÜÔÏÇÏ +ÏÔËÒÙ×ÁÅÔÓÑ ÆÁÊÌ ÉÌÉ ÎÁ ÓÅÒ×ÅÒÅ \ts{host} ÉÌÉ ÌÏËÁÌØÎÙÊ ÆÁÊÌ. ðÁÒÁÍÅÔÒ mode ÄÏÌÖÅÎ +ÓÏÄÅÒÖÁÔØ ÏÄÉÎ ÉÌÉ Ä×Á ÓÉÍ×ÏÌÁ. ðÅÒ×ÙÊ ÚÁÄÁÅÔ ÔÉÐ ÏÔËÒÙÔÉÑ ÆÁÊÌÁ ``r'',``w'' ÉÌÉ +``a''. ÷ÔÏÒÏÊ ÓÉÍ×ÏÌ ÍÏÖÅÔ ÓÏÄÅÒÖÁÔØ ÓÉÍ×ÏÌ ``b'' ÞÔÏ ÂÕÄÅÔ ÚÁÄÁ×ÁÔØ Ä×ÏÉÞÎÕÀ ÍÏÄÕ ÐÅÒÅÄÁÞÉ} +\ttt{\toindex{FtpFullClose}(FILE *f)} +{úÁËÒÙÔÉÅ ÆÁÊÌÁ} + + +\section{ïÐÉÓÁÎÉÅ ÐÒÉÍÅÒÏ× É ÐÒÉËÌÁÄÎÙÈ ÐÒÏÇÒÁÍÍ} + +\subsection{ðÒÏÇÒÁÍÍÁ get}\index{get} + +ëÏÐÉÒÏ×ÁÎÉÅ ÆÁÊÌÁ Ó ÓÅÒ×ÅÒÁ × ÌÏËÁÌØÎÙÊ ÆÁÊÌ Ó ÔÁËÉÍ ÖÅ ÉÍÅÎÅÍ Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ ÆÕÎËÃÉÊ ÐÏÌÎÏÇÏ ÓÅÁÎÓÁ. + + +\subsection{ðÒÏÇÒÁÍÍÁ fcp}\index{fcp} + +ðÒÏÇÒÁÍÍÁ fcp ÄÅÍÏÎÓÔÒÉÒÕÅÔ ÐÒÏÓÔÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÆÕÎËÃÉÊ ÐÏÌÎÏÇÏ ÓÅÁÎÓÁ ÒÁÂÏÔÙ +(FtpFullOpen É FtpFullClose). éÍÑ ÆÁÊÌÁ ÐÅÒÅÄÁ×ÁÅÍÏÇÏ × ËÁÞÅÓÔ×Å +ÐÁÒÁÍÅÔÒÁ, ÍÏÖÅÔ ÏÐÉÓÙ×ÁÔØ É ÌÏËÁÌØÎÙÊ É ÕÄÁÌÅÎÎÙÊ ÆÁÊÌ. üÔÏ ÐÏÚ×ÏÌÑÅÔ +ÐÒÏÉÚ×ÏÄÉÔØ ÐÅÒÅÄÁÞÕ ËÁË Ó ÓÅÒ×ÅÒÁ × ÌÏËÁÌØÎÙÊ ÆÁÊÌ, ÔÁË É ÎÁÏÂÏÒÏÔ, + Á ÔÁËÖÅ Ó ÓÅÒ×ÅÒÁ ÎÁ ÓÅÒ×ÅÒ. + +\subsection{ðÒÏÇÒÁÍÍÁ ftptry}\index{ftptry} + +ðÒÅÄÎÁÚÎÁÞÅÎÁ ÄÌÑ ÐÅÒÅÄÁÞÉ ÆÁÊÌÏ× ÂÏÌØÛÏÇÏ ÒÁÚÍÅÒÁ ÐÏ ÓÅÔÑÍ ËÏÔÏÒÙÅ +ÏÞÅÎØ ÞÁÓÔÏ ``ÌÏÍÁÀÔÓÑ''. üÔÏ ÐÒÅÖÄÅ ×ÓÅÇÏ ÏÔÎÏÓÉÔÓÑ Ë ÓÅÔÑÍ ÐÏÓÔÒÏÅÎÎÙÈ +ÎÁ dialup-ÌÉÎÉÑÈ. + +\ts{ftptry} × ÏÓÎÏ×ÎÏÍ ÐÒÅÄÎÁÚÎÁÞÅÎ ÄÌÑ ÎÅÉÔÅÒÁËÔÉ×ÎÏÊ +ÐÅÒÅÄÁÞÉ ÄÁÎÎÙÈ, ÐÏÜÔÏÍÕ ÎÅÏÂÈÏÄÉÍÁÑ ÉÎÆÏÒÍÁÃÉÑ ÄÌÑ ×ÙÐÏÌÎÅÎÉÑ ÐÅÒÅÄÁÞÉ ÚÁÄÁeÔÓÑ × ×ÉÄÅ ÏÐÃÉÊ ÐÒÉ ÚÁÐÕÓËÅ ÐÒÏÇÒÁÍÍÙ. + +ðÒÉ ÚÁÐÕÓËÅ \ts{ftptry} ÂÅÚ ËÌÀÞÅÊ, ÎÁ ÜËÒÁÎ ×Ù×ÏÄÉÔÓÑ ÓÐÉÓÏË ×ÓÅÈ ÄÏÐÕÓÔÉÍÙÈ +ÏÐÃÉÊ É ÏÄÉÎ ÐÒÉÍÅÒ ÚÁÐÕÓËÁ, ÐÏÜÔÏÍÕ × ÄÁÎÎÏÍ ÒÕËÏ×ÏÄÓÔ×Å ËÌÀÞÉ +É ÉÈ ÎÁÚÎÁÞÅÎÉÑ ÏÐÉÓÙ×ÁÔØ ÎÅ ÉÍÅÅÔ ÓÍÙÓÌÁ. +îÅÏÂÈÏÄÉÍÏ ÔÏÌØËÏ ÓËÁÚÁÔØ Ï ÔÏÍ, ÞÔÏ +ÔÁË ËÁË ÎÅËÏÔÏÒÙÅ ÏÐÃÉÉ ÎÅÏÂÈÏÄÉÍÏ ÓÔÁ×ÉÔØ ÐÒÁËÔÉÞÅÓËÉ ×ÓÅÇÄÁ, +ÔÏ ÍÏÖÎÏ ÐÒÅÄ×ÁÒÉÔÅÌØÎÏ +ÕÓÔÁÎÏ×ÉÔØ ÐÅÒÅÍÅÎÎÕÀ ÏËÒÕÖÅÎÉÑ ``FTPTRY''\index{FTPTRY enviroment} +ÐÏ ÁÎÁÌÏÇÉÉ Ó ÔÅÍ ËÁË ÜÔÏ ÄÅÌÁÅÔÓÑ +× ÐÒÏÇÒÁÍÍÅ ``less'' +\footnote{îÁÐÒÉÍÅÒ: \% setenv FTPTRY ``-DBb -u anonymous -s 60 -t 15''}, +É ÐÉÓÁÔØ × ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÅ ÔÏÌØËÏ ÔÅ ÏÐÃÉÉ ËÏÔÏÒÙÅ ÒÅÄËÏ +ÉÓÐÏÌØÚÕÀÔÓÑ ÉÌÉ ÎÅ ÐÉÓÁÔØ ÉÈ ×ÏÏÂÝÅ. + + +\newpage +\input rus.ind +\newpage +\tableofcontents +\end{document} + + diff --git a/lib/libftp/utils/Makefile b/lib/libftp/utils/Makefile new file mode 100644 index 0000000..783451b --- /dev/null +++ b/lib/libftp/utils/Makefile @@ -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 diff --git a/lib/libftp/utils/cdefs.h b/lib/libftp/utils/cdefs.h new file mode 100644 index 0000000..c104b9e --- /dev/null +++ b/lib/libftp/utils/cdefs.h @@ -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_ */ diff --git a/lib/libftp/utils/ftptry.c b/lib/libftp/utils/ftptry.c new file mode 100644 index 0000000..623d0da --- /dev/null +++ b/lib/libftp/utils/ftptry.c @@ -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); +} + + + + + + diff --git a/lib/libftp/utils/glob.c b/lib/libftp/utils/glob.c new file mode 100644 index 0000000..d80b146 --- /dev/null +++ b/lib/libftp/utils/glob.c @@ -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 diff --git a/lib/libftp/utils/glob.h b/lib/libftp/utils/glob.h new file mode 100644 index 0000000..bffb28c --- /dev/null +++ b/lib/libftp/utils/glob.h @@ -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_ */ diff --git a/lib/libftp/utils/mirror.c b/lib/libftp/utils/mirror.c new file mode 100644 index 0000000..babd840 --- /dev/null +++ b/lib/libftp/utils/mirror.c @@ -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); +} + + + diff --git a/lib/libftp/utils/readline.c b/lib/libftp/utils/readline.c new file mode 100644 index 0000000..34612ba --- /dev/null +++ b/lib/libftp/utils/readline.c @@ -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 */ diff --git a/lib/libftp/utils/uftp.c b/lib/libftp/utils/uftp.c new file mode 100644 index 0000000..49037ad0 --- /dev/null +++ b/lib/libftp/utils/uftp.c @@ -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); + } +} + + + + + + diff --git a/lib/libftp/utils/uftp.h b/lib/libftp/utils/uftp.h new file mode 100644 index 0000000..3e7b3fe --- /dev/null +++ b/lib/libftp/utils/uftp.h @@ -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 *); + + + + + + + + + diff --git a/lib/libftp/utils/uftp.man b/lib/libftp/utils/uftp.man new file mode 100644 index 0000000..9cf95d3 --- /dev/null +++ b/lib/libftp/utils/uftp.man @@ -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) diff --git a/lib/libftp/utils/uftpcmd.c b/lib/libftp/utils/uftpcmd.c new file mode 100644 index 0000000..959de40 --- /dev/null +++ b/lib/libftp/utils/uftpcmd.c @@ -0,0 +1,1202 @@ +#include "uftp.h" + +String tmp; + +jmp_buf connectstack; + + + +Ftp_connect_hook(FTP *ftp,int code, char *msg) +{ + FtpLog(ftp->title,msg); + longjmp(connectstack,1); + +} + + +Ftp_connect(ARGS) +{ + STATUS (*func1)(),(*func2)(); + + if (*w2==0) w2=readline("Host:"); + + if (FtpGetHost(w2)==NULL && FtpInit.IO != NULL) + { + char *msg; + extern int h_errno; + + switch(h_errno) + { + case HOST_NOT_FOUND: msg = "Host unknown"; break; + case TRY_AGAIN: msg = "Hostname lookup failure";break; + default: msg = "gethostbyname failure"; + } + return (*FtpInit.IO)(LINK,QUIT,msg); + } + + newframe(0); + + func1 = FtpInit.error; + func2 = FtpInit.IO; + + if (trymode) + { + FtpSetErrorHandler(&FtpInit,Ftp_connect_hook); + FtpSetIOHandler(&FtpInit,Ftp_connect_hook); + setjmp(connectstack); + } + + FtpConnect(&LINK,w2); + strcpy(iftp[frame].host,FtpGetHost(w2)->h_name); + + FtpSetErrorHandler(LINK,func1); + FtpSetErrorHandler(&FtpInit,func1); + FtpSetIOHandler(LINK,func2); + FtpSetIOHandler(&FtpInit,func2); + + return; +} + +Ftp_user(ARGS) +{ + + if (*w2==0) + { + sprintf(tmp,"login (default %s):",defaultuser); + w2=readline(tmp); + if (*w2==0) + w2=defaultuser; + } + strcpy(iftp[frame].user,w2); + strcpy(iftp[frame].pass,w3); + if (FtpUser(LINK,w2)==331) Ftp_pass("",w3,"","","",""); +} + +Ftp_pass(ARGS) +{ + if (*w2==0) + { + String pass; + String host; + + gethostname(host, sizeof host); + strcpy(host,FtpGetHost(host)->h_name); + sprintf(pass,"%s@%s",getpwuid(getuid())->pw_name,host); + sprintf(tmp,"Password (default %s):",pass); + w2=getpass(tmp); + if (*w2==0) w2=pass; + } + + strcpy(iftp[frame].pass,w2); + FtpPassword(LINK,w2); + strcpy(iftp[frame].pwd,FtpPwd(LINK)); +} + +Ftp_open(ARGS) +{ + register char *p1; + STATUS (*err)(); + + Ftp_connect("",w2,"","","",""); + Ftp_user("",w3,w4,"","","" ); + if (ifalias("autologin")) execute("autologin"); + if (*w5) + Ftp_cd("cd",w5,"","","",""); +} + +Ftp_reopen(ARGS) +{ + String host,user,pass,pwd; + + strcpy(host,iftp[frame].host); + strcpy(user,iftp[frame].user); + strcpy(pass,iftp[frame].pass); + strcpy(pwd,iftp[frame].pwd); + + Ftp_close("","","","","",""); + Ftp_open("",host,user,pass,pwd,""); +} + +Ftp_ftp(ARGS) +{ + String pass; + String host; + + gethostname(host, sizeof host); + strcpy(host,FtpGetHost(host)->h_name); + sprintf(pass,"%s@%s",getpwuid(getuid())->pw_name,host); + + Ftp_open("",w2,"anonymous",pass,w3,""); + return; +} + +Ftp_quit(ARGS) +{ + exit(0); +} + +Ftp_mput_handler() +{ + log("File(s) or directory not found"); + longjmp(start,1); +} + + +Ftp_lcd(ARGS) +{ + glob_t gl; + + bzero(&gl,sizeof gl); + + glob(w2,GLOB_BRACE|GLOB_TILDE|GLOB_QUOTE, + Ftp_mput_handler, &gl); + + + if (gl.gl_matchc<1 || chdir(*gl.gl_pathv)) + perror(w2); + + printf("Local directory is \"%s\"\n",getwd(tmp)); +} + +Ftp_dir(ARGS) +{ + char *cmd1; + String cmd; + char mode=LINK->mode; + + if ( !strcmp(w1,"dir") ) + cmd1="LIST"; + else + cmd1="NLST"; + + strcpy(cmd,makestr(cmd1,w2,w3,w4,w5,w6,NULL)); + + if ( LINK->mode != 'A' ) FtpAscii(LINK); + FtpRetr(LINK,cmd,"","-"); + if ( LINK->mode != mode ) FtpType(LINK,mode); + +} + +Ftp_close(ARGS) +{ + register int i; + + if (isdigit(*w2)) + { + i=atoi(w2); + } + else + { + i=frame; + } + + FtpQuickBye(ftp[i]); + + iftp[i].host[0]=0; + iftp[i].pwd[0]=0; + ftp[i]=NULL; + newframe(1); +} + + +INLINE SetLogicalVar(char arg, int * var, char *msg) +{ + switch(arg) + { + + case 'y': + + *var=1; + break; + + case 'n': + + *var=0; + break; + + default: + + (*var)?(*var=0):(*var=1); + break; + } + return printf("%s %s\n",msg,(*var)?"enable":"disable"); +} + + +Ftp_set(ARGS) +{ + if (!strcmp("frame",w2)) + return atoi(w3)<NFRAMES?frame=atoi(w3):0; + + if (!strcmp("timeout",w2)) + { + FtpSetTimeout(&FtpInit,atoi(w3)); + if (LINK!=0) + FtpSetTimeout(LINK,atoi(w3)); + return; + } + + if (!strcmp("sleep",w2)) + { + sleeptime=atoi(w3); + return; + } + + if (!strcmp("debug",w2)) + { + if ( *w3=='y' || *w3==0) + { + if (LINK!=NULL) FtpSetDebugHandler(LINK,FtpDebugDebug); + FtpSetDebugHandler(&FtpInit,FtpDebugDebug); + return puts("Debuging on for current and next session"); + } + if ( *w3 == 'n') + { + if (LINK!=NULL) FtpSetDebugHandler(LINK,NULL); + FtpSetDebugHandler(&FtpInit,NULL); + return puts("Debuging off for current and next session"); + } + } + + if (!strcmp("bin",w2)) + { + if ( *w3=='y' || *w3==0) + { + FtpInit.mode='I'; + return puts("Binary mode enable"); + } + if ( *w3 == 'n') + { + FtpInit.mode='A'; + return puts("Binary mode disable"); + } + } + + if (!strcmp("try",w2)) + return SetLogicalVar(*w3,&trymode,"Try mode"); + if (!strcmp("hash",w2)) + return SetLogicalVar(*w3,&hashmode,"Hash mode"); + if (!strcmp("glass",w2)) + return SetLogicalVar(*w3,&glassmode,"Glass mode"); + if (!strcmp("rest",w2)||!strcmp(w2,"restore")) + return SetLogicalVar(*w3,&restmode,"Restore mode"); + + if (!strcmp("prompt",w2)) + { + strcpy(prompt,w3); + return; + } + + if (!strcmp("port",w2)) + { + if ( isdigit(*w3)) + return FtpSetPort(&FtpInit,atoi(w3)); + puts("Port must be number"); + fflush(stdout); + return; + } + + if (!strcmp("noopinterval",w2)||!strcmp("noop",w2)) + { + if ( isdigit(*w3)) + return noopinterval=(time_t)atoi(w3); + puts("Time must be number"); + fflush(stdout); + return; + } + + if (!strcmp("nooptimeout",w2)) + { + if ( isdigit(*w3)) + return nooptimeout=(time_t)atoi(w3); + puts("Time must be number"); + fflush(stdout); + return; + } + + + + if (!strcmp("user",w2)||!strcmp("login",w2)) + { + strcpy(defaultuser,w3); + return; + } + + if (!strcmp("",w2)) + { + + printf("frime %d\n",frame); + printf("timeout %d secs\n",FtpInit.timeout.tv_sec); + printf("sleep time %d secs\n",sleeptime); + printf("debug %s\n",(FtpInit.debug!=NULL)?"enable":"disable"); + printf("glass mode %s\n",glassmode?"enable":"disable"); + printf("try mode %s\n",trymode?"enable":"disable"); + printf("hash mode %s\n",hashmode?"enable":"disable"); + printf("restore mode %s\n",restmode?"enable":"disable"); + printf("automatic binary mode %s\n",(FtpInit.mode=='I')?"enable":"disable"); + printf("prompt \"%s\"\n",prompt); + printf("port %d\n",FtpInit.port); + printf("noop interval %d\n",noopinterval); + printf("noop timeout %d\n",nooptimeout); + printf("Default login name \"%s\"\n",defaultuser); + fflush(stdout); + return; + } + return puts("arg 2 unknown"); + +} + +jmp_buf getstack; + +Ftp_get_hook(FTP *con,int code, char *msg) +{ + + if ( abs(code)==550 && FtpBadReply550(msg) ) + { + FtpLog(con->title,msg); + log("Transfer cancel"); + longjmp(getstack,2); + } + + if ( code == LQUIT ) + { + log(msg); + log("Transfer leave after I/O error with local file"); + longjmp(getstack,2); + } + + + + FtpLog(con->title,msg); + FtpQuickBye(LINK); + LINK=NULL; + + log("sleeping......"); + sleep(sleeptime); + log("try again..."); + + longjmp(getstack,1); + +} + +void Ftp_get_intr(int sig) +{ + signal(SIGINT,intr); + log("Transfer interupt"); + Ftp_abort(); + longjmp(getstack,3); +} + +Ftp_get(ARGS) +{ + FTP OldInit; + int back=0; + int code; + int status=0; + + OldInit=FtpInit; + + if (strstr(w1,"put")!=NULL) back=1; + + + if (restmode || ((*w1=='r')&&(*(w1+1)=='e')) ) + FtpSetFlag(LINK,FTP_REST); + else + FtpClearFlag(LINK,FTP_REST); + + + + if (trymode) + { + FtpSetErrorHandler(LINK,Ftp_get_hook); + FtpSetIOHandler(LINK,Ftp_get_hook); + FtpInit=*LINK; + FTPCMD(&FtpInit)=FTPCMD(&OldInit); + FTPDATA(&FtpInit)=FTPDATA(&OldInit); + } + + signal(SIGINT,Ftp_get_intr); + FtpSetHashHandler(LINK,NULL); + + + if ((status=setjmp(getstack))==2||status==3) + goto done; + + if ((LINK==NULL)||(LINK->sock==FtpInit.sock)) + { + FtpLogin(&LINK,iftp[frame].host,iftp[frame].user, + iftp[frame].pass,NULL); + FtpChdir(LINK,iftp[frame].pwd); + } + + if (hashmode && isatty(fileno(stdout))) + FtpSetHashHandler(LINK,myhash); + else + FtpSetHashHandler(LINK,NULL); + + myhash(LINK,0); + + if (!back) + FtpGet(LINK,w2,makefilename(w2,w3)); + else + FtpPut(LINK,w2,makefilename(w2,w3)); + + + log("Transfer compliete"); + + +done: + + + FtpSetHashHandler(LINK,NULL); + FtpSetErrorHandler(LINK,my_error); + FtpSetIOHandler(LINK,my_error); + FtpClearFlag(LINK,FTP_REST); + FtpInit=OldInit; +} + +Ftp_mget(ARGS) +{ + FILE *list; + char mode=LINK->mode; + + sprintf(tmp,"/tmp/uftplist-%s.XXXXXX",getpwuid(getuid())->pw_name); + mktemp(tmp); + + if ( LINK->mode != 'A' ) FtpAscii(LINK); + + if (*w2==0) + FtpRetr(LINK,"NLST","",tmp); + else + FtpRetr(LINK,"NLST %s",w2,tmp); + + if ( LINK->mode != mode ) FtpType(LINK,mode); + + if ((list=fopen(tmp,"r"))==NULL) + return FtpLog(tmp,sys_errlist[errno]); + + while ( fgets(tmp,sizeof tmp,list)!=NULL) + { + tmp[strlen(tmp)-1]=0; + Ftp_get("get",tmp,w3,"","",""); + } + + fclose(list); +} + +Ftp_mput(ARGS) +{ + glob_t gl; + + glob(w2,GLOB_BRACE|GLOB_TILDE|GLOB_QUOTE, + Ftp_mput_handler, &gl); + + while(gl.gl_matchc--) + { + Ftp_get("put",*gl.gl_pathv,"","","",""); + gl.gl_pathv++; + } +} + + +Ftp_bget(ARGS) +{ + + String fn,lfn; + char *p; + + newframe(0); + + if (!FtpFullSyntax(w2,iftp[frame].host,iftp[frame].user, + iftp[frame].pass,fn)) + return puts("Filename syntax error"); + + strcpy(iftp[frame].pwd,"/"); + + if ((p=strrchr(fn,'/'))!=NULL) + strcpy(lfn,p+1); + else + strcpy(lfn,fn); + + FtpQuickBye(LINK); + LINK=FtpCreateObject(); + LINK->sock=NULL; + + Ftp_get("get",fn,(*w3==0)?lfn:w3,"","",""); +} + +Ftp_bput(ARGS) +{ + + String fn,lfn; + char *p; + + if (!FtpFullSyntax((*w3==0)?w2:w3,iftp[frame].host,iftp[frame].user, + iftp[frame].pass,fn)) + return puts("Filename syntax error"); + + strcpy(iftp[frame].pwd,"/"); + + if ((p=strrchr(fn,'/'))!=NULL) + strcpy(lfn,p+1); + else + strcpy(lfn,fn); + + FtpQuickBye(LINK); + LINK=FtpCreateObject(); + LINK->sock=NULL; + + Ftp_get("put",(*w3==0)?lfn:w2,fn,"","",""); +} + +Ftp_copy(ARGS) +{ + char *p; + int in,out; + + if ( !*w2 || !*w3 ) return puts("Must pass two args"); + + if ((p=strchr(w2,'!'))!=NULL) + { + *p=0; + in=atoi(w2); + w2=p+1; + } + else + in=frame; + + if ((p=strchr(w3,'!'))!=NULL) + { + *p=0; + out=atoi(w3); + w3=p+1; + } + else + in=frame; + + if (in==out) return puts("Files must been from different frames"); + + FtpCopy(ftp[in],ftp[out],w2,w3); +} + +Ftp_ccopy(ARGS) +{ + char *p; + int in,out; + + if ( !*w2 || !*w3 ) return puts("Must pass two args"); + + if ((p=strchr(w2,'!'))!=NULL) + { + *p=0; + in=atoi(w2); + w2=p+1; + } + else + in=frame; + + if ((p=strchr(w3,'!'))!=NULL) + { + *p=0; + out=atoi(w3); + w3=p+1; + } + else + in=frame; + + if (in==out) return puts("Files must been from different frames"); + + FtpPassiveTransfer(ftp[in],ftp[out],w2,w3); +} + +Ftp_bin(ARGS) +{ + FtpBinary(LINK); +} + +Ftp_ascii(ARGS) +{ + FtpAscii(LINK); +} + +Ftp_cd(ARGS) +{ + FtpChdir(LINK,w2); + strcpy(iftp[frame].pwd,FtpPwd(LINK)); + if (ifalias("autocd")) execute("autocd"); +} + + +Ftp_dup(ARGS) +{ + LINKINFO oldinfo; + FTP oldftp; + + oldinfo=iftp[frame]; + oldftp=*LINK; + + newframe(0); + puts("Make alternative connection..."); + Ftp_open("",oldinfo.host,oldinfo.user,oldinfo.pass,"",""); + if (strcmp(oldinfo.pwd,iftp[frame].pwd)) + Ftp_cd("",oldinfo.pwd,"","","",""); + if (LINK->mode!=oldftp.mode) + FtpType(LINK,oldftp.mode); + LINK -> timeout = oldftp.timeout; + LINK -> flags = oldftp.flags; + FtpSetDebugHandler(LINK,oldftp.debug); + FtpSetErrorHandler(LINK,oldftp.error); + FtpSetIOHandler(LINK,oldftp.IO); + FtpSetHashHandler(LINK,oldftp.hash); +} + + + +Ftp_bg(ARGS) +{ + if (fork()) + { + + log("Backgrounding..."); + return; + } + else + { + int i=frame; + + lastcmd=1; + + /* Ignoring keypad */ + + alarm (0); + signal(SIGALRM,SIG_IGN); + signal(SIGURG,SIG_IGN); + signal(SIGPIPE,SIG_IGN); + signal(SIGTSTP,SIG_IGN); + signal(SIGINT,SIG_IGN); + signal(SIGQUIT,SIG_IGN); + signal(SIGCHLD,SIG_IGN); + signal(SIGIO,SIG_IGN); + + /* Droping output */ + + + sprintf(tmp,"/tmp/uftp-%s.XXXXXX",getpwuid(getuid())->pw_name); + mktemp(tmp); + close(0);close(1);close(2); + open(tmp,O_RDWR|O_TRUNC|O_CREAT,0600); + dup(0);dup(0); + + if (LINK!=NULL) + { + Ftp_dup("","","","","",""); + free(ftp[i]); + ftp[i]=NULL; + } + + return executev(w2,w3,w4,w5,w6,""); + } +} + + +Ftp_list() +{ + register int i; + +#define _FMT "%-5s %-15s %-10s %-25s %-7s %-4s\n" +#define FMT "%-5d %-15s %-10s %-25s %-7d %-4d\n" + + printf(_FMT,"Frame","Host name","User's name","Working directory","Timeout","Port"); + + for ( i = 0 ; i < NFRAMES ; i++ ) + if (ftp[i]!=NULL) + printf(FMT,i,iftp[i].host,iftp[i].user,iftp[i].pwd, + ftp[i]->timeout.tv_sec,ftp[i]->port); + fflush(stdout); + return; +} + +Ftp_abort(ARGS) +{ + time_t save; + + if (LINK!=NULL) + { + save = LINK ->timeout.tv_sec; + LINK->timeout.tv_sec = nooptimeout; + FtpAbort(LINK); + LINK->timeout.tv_sec = save; + } +} + +Ftp_type(ARGS) +{ + FtpGet(LINK,w2,"*STDOUT*"); +} + + +Ftp_page(ARGS) +{ + register char *pager; + String out={'|',0}; + + if ((pager=(char *)getenv("PAGER"))==NULL) + pager="more"; + + strcat(out,pager); + FtpGet(LINK,w2,out); +} + + +Ftp_mkdir(ARGS) +{ + FtpMkdir(LINK,w2); +} + +Ftp_rm(ARGS) +{ + FILE *list; + + sprintf(tmp,"/tmp/uftplist-%s.XXXXXX",getpwuid(getuid())->pw_name); + mktemp(tmp); + + if (*w2==0) + { + log("Filename specification must present"); + return; + } + + FtpRetr(LINK,"NLST %s",w2,tmp); + + if ((list=fopen(tmp,"r"))==NULL) + return FtpLog(tmp,sys_errlist[errno]); + + while ( fgets(tmp,sizeof tmp,list)!=NULL) + { + tmp[strlen(tmp)-1]=0; + FtpCommand(LINK,"DELE %s",tmp,0,EOF); + } + + fclose(list); +} + + + + +Ftp_move(ARGS) +{ + FtpMove(LINK,w2,w3); +} + +Ftp_help(ARGS) +{ + register int i,ii; + + if ( !*w2 ) + { + puts("Warrning!!!! \nPlease read general information using command \"help etc\"\n\n"); + + for ( i = 0 ;1; i++) + { + for ( ii = 0 ; ii < 5 ; ii++) + { + if (cmds[ii+i*5].cmd==NULL) return putchar('\n'); + printf("%-16s",cmds[ii+i*5].cmd); + } + putchar ('\n'); + } + } + + + for ( i = 0 ; 1; i++) + { + + if (cmds[i].cmd==NULL) return puts("Command not found"); + if (!strcmp(cmds[i].cmd,w2)) + break; + } + + puts(cmds[i].help); + +} + +Ftp_quote(ARGS) +{ + String new; + + new[0]=0; + + if (*w2!=0) strcpy(new,w2); + if (*w3!=0) strcat(new," "),strcat(new,w3); + if (*w4!=0) strcat(new," "),strcat(new,w4); + if (*w5!=0) strcat(new," "),strcat(new,w5); + if (*w6!=0) strcat(new," "),strcat(new,w6); + + FtpCommand(LINK,new,"",0,EOF); +} + +Ftp_alias(ARGS) +{ + ALIAS *a=firstalias; + + + if ( *w2==0 ) + { + while (a!=NULL) + { + printf("%s=%s\n",a->name,a->str); + a=a->next; + } + return; + } + + + while (1) + { + + if ( a == NULL ) + { + firstalias = a = (ALIAS *) malloc(sizeof(ALIAS)); + memset(a,0,sizeof(ALIAS)); + a -> next = NULL; + break; + } + + if (!strcmp(a->name,w2)) + break; + + if ( a->next == NULL) + { + a -> next = (ALIAS *) malloc(sizeof(ALIAS)); + a = a->next; + memset(a,0,sizeof(ALIAS)); + a -> next = NULL; + break; + } + a=a->next; + } + + strcpy(a -> name,w2); + strcpy(a -> str,makestr(w3,w4,w5,w6,NULL)); +} + +Ftp_mkalias(ARGS) +{ + String new; + + if (!*w2) return puts("Arg must present\n"); + + sprintf(new,"open \"%s\" \"%s\" \"%s\" \"%s\"", + iftp[frame].host,iftp[frame].user, + iftp[frame].pass,iftp[frame].pwd); + + Ftp_alias("alias",w2,new,"","",""); +} + +Ftp_unalias(ARGS) +{ + ALIAS *cur,*prev; + + cur=prev=firstalias; + + while ( cur != NULL ) + { + if (!strcmp(cur->name,w2)) + { + if ( cur == firstalias ) + { + firstalias = cur->next; + free(cur); + return; + } + prev -> next = cur -> next; + free(cur); + } + prev=cur; + cur=cur->next; + } +} + + +Ftp_save(ARGS) +{ + ALIAS *a=firstalias; + String fn; + FILE *out; + + if ((out=fopen (getaliasrcname(),"w"))==NULL) + { + perror(getaliasrcname()); + return; + } + + while (a!=NULL) + { + fprintf(out,"alias %s '%s'\n",a->name,a->str); + a=a->next; + } + fclose(out); + chmod ( getaliasrcname(), 0600); + puts("Aliases saved"); +} + +#define ARCHIE_MAX_TARGETS 20 + +Ftp_acd(ARGS) +{ + static int targets=0; + static String what={0}; + static ARCHIE result[ARCHIE_MAX_TARGETS]; + + int i, selected_target; + String tmp; + char *p; + + + if ( (what[0] == 0 || strcmp(w2,what) != 0) && *w2!=0 ) + { + if ((targets=FtpArchie(w2,result,ARCHIE_MAX_TARGETS))<1) + return puts("Archie failure or target not found"); + strcpy(what,w2); + } + + for (i=0;i<targets;i++) + printf("%2d %s:%s\n",i,result[i].host,result[i].file); + + if (strcmp(w1,"archie")==0) + return; + + + p = readline("Your selection? "); + if (p==NULL) return; + + selected_target = atoi(p); + + if ( result[selected_target].file[strlen(result[selected_target].file)-1] + == '/' ) + { + Ftp_ftp("ftp",result[selected_target].host,result[selected_target].file, + "","",""); + return; + } + else + { + sprintf(tmp,"%s:%s", + result[selected_target].host,result[selected_target].file); + Ftp_bget("bget",tmp,"","","",""); + } +} + + +CMDS cmds[]={ + + "connect", Ftp_connect, 0, + "connect <hostname> - make new ftp connection", + + "open", Ftp_open, 0, + "open <hostname> <user> <pass> <directory> - login to server", + + "reopen", Ftp_reopen, 1, + "Open again connection with existing frame information", + + "ftp", Ftp_ftp, 0, + "ftp <hostname> - anonymously login to server", + + "close", Ftp_close, 1, + "Close connection", + + "quit", Ftp_quit, 0, + "Exit from uftp", + + "set", Ftp_set, 0, +"Set variables: (Without args print current settings)\n\ + frame <number> - select another session(frame)\n\ + timeout <secs> - Set network timeout\n\ + nooptimeout <secs>- Set network timeout with clearing timeout\n\ + noop <secs> - Set time interval for sending NOOP operator\n\ + to server for erased delay\n\ + sleep <secs> - Set pause beetween transfer attempt\n\ + debug <y|n> - Set debuging ftp's protocol (Default no)\n\ + try <y|n> - Set retransfer mode with broken network (Default yes)\n\ + hash <y|n> - Set hashing transfer (Default no)\n\ + restore <y|n> - Set retransfer mode (reget/reput) (Default yes!!!!)\n\ + bin <y|n> - Set automatic turn on binary mode (Default no) \n\ + glass <y|n> - Set glass mode (bad commands interprets as commands for FTPD)\n\ + prompt <string> - Set prompt (See help prompt)\n\ + port <number> - Set ftpd's port for next sessions\n\ + user <name> - Set default user name (default you name)", + + "prompt", NULL, 0, + "\ +prompt is a string, which may be contains %<char> +or ^<char> combitanion, which have next interprets: + +%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 ^ +", + + "list", Ftp_list, 0, +"List session's information", + + "user", Ftp_user, 1, +"user <user> - send user's name", + + "pass", Ftp_pass, 1, +"pass <pass> - send user's password", + + "bin", Ftp_bin, 1, +"Set binary mode for current frame", + + "ascii", Ftp_ascii, 1, +"Set ASCII mode for current frame", + + "cd", Ftp_cd, 1, +"cd <directory> - change current remote directory ", + + "acd", Ftp_acd, 0, +"acd <file_or_directory> - search pointed directory using archie, and setup connection to it", + + "lcd", Ftp_lcd, 0, +"Change local directory", + + "abort", Ftp_abort, 1, +"abort last operation", + + "mkdir", Ftp_mkdir, 1, +"mkdir <dirname> - create new directory", + + "rm", Ftp_rm, 1, +"rm <filename_spec> - remove file(s)", + + "mv", Ftp_move, 1, +"mv <old> <new> - rename file", + + "dir", Ftp_dir, 1, +"dir <argslist> ... - print list of files", + + "ls", Ftp_dir, 1, +"ls <arglist> ... - print short list of files", + + "get", Ftp_get, 1, +"get <remote_file> [<local_file>] - receive file from server", + + "mget", Ftp_mget, 1, +"mget <remote_file(s)> [<local_directory>] - receive file(s) from server", + + "reget", Ftp_get, 1, +"reget <remote_file> <local_file> - receive file restarting at end of local file", + + "aget", Ftp_acd, 0, +"aget <file> - search pointed file using archie, and retrive it", + + "put", Ftp_get, 1, +"put <local_file> [<remote_file>] - send server to file", + + "mput", Ftp_mput, 1, +"mput <local_file(s)> - send file(s) from server", + + "reput", Ftp_get, 1, +"reput <local_file> [<remote_file>] - send file restarting at end of remote file", + + "bget", Ftp_bget, 0, +"bget <libftp_file> [<localfile>] - full session procedure (See \"help etc\")", + + "bput", Ftp_bput, 0, +"bput [<localfile>] <libftp_file> - full session procedure (See \"help etc\")", + + "copy", Ftp_copy, 1, +"copy [<frame>!]file [<frame>!]file - copy file via client cache", + + "ccopy", Ftp_ccopy, 1, +"ccopy [<frame>!]file [<frame>!]file - copy file directly beetween servers", + + "cat", Ftp_type, 1, +"cat <file> - print body of remote file to screen", + + "page", Ftp_page, 1, +"page <file> - print body of remote file to screen via pager", + + "bg", Ftp_bg, 0, +"bg <any_command> - run command(s) backgroundly (output redirect to file),\n\ +You can also add &-char to back of line without \"bg\"", + + "archie", Ftp_acd, 0, +"Find file using archie service and display to screen", + + "dup", Ftp_dup, 1, +"Make new analogous frame", + + "quote", Ftp_quote, 1, +"quote <some_string> - send command directly to server", + + "help", Ftp_help, 0, +"help <command> - print list of commands or command description", + + "alias", Ftp_alias, 0, +"\ +alias aliasname <list> .... - make new alias, use $X for taking \n\ + X's argument from command string, and $* for taking\n\ + all arguments. If $<anything> on alias not present,\n\ + the arguments appending to end of command string", + + "unalias", Ftp_unalias, 0, +"unalias <aliasname> - remove alias", + + "mkalias", Ftp_mkalias, 0, +"make alias for create this frame, use savealias for saving it to file", + + "savealias", Ftp_save, 0, + "Save aliases to file", + + "etc", NULL, 0, + "\ +1. In any command you may use constructions <file and >file for\n\ + redirect input output.\n\ +\n\ +2. All local files files interprets as libftp file(s), \n\ + this support next specification:\n\ +\n\ + |string - interprets string as shell command, which must be\n\ + execute and input or output take from/to it.\n\ + \n\ + hostname:filename - interprets as file, witch must be take \n\ + using ftp protocol with anonymously access\n\ + \n\ + user@hostname:filename - interprets as file accesses via ftp\n\ + with password yourname@your_host.your_domain\n\ +\n\ + user/pass@hostname:filename - also ftp file.\n\ +\n\ + *STDIN*, *STDOUT*, *STDERR* - opened streams.\n\ +\n\ + anything - local file name.\n\ +\n\ +3. Command started with '!' passed to shell.\n +\n\ +4. If string beetween two \" or \', its interprets as one word.\n\ +\n\ +5. Any string may be devide to few commands using ';'.", + + + + NULL + +}; + + + + + + + |