荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标 题: 递归编历FTP目录的程序 ysqcn (转寄)[转载]
发信站: 荔园晨风BBS站 (Thu Apr 25 10:25:39 2002), 转信
【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@apue.dhs.org 所发表 】
发信人: ysqcn (岁月无声), 信区: UNP
标 题: 递归编历FTP目录的程序
发信站: UNIX编程 (Tue Sep 18 23:29:46 2001) , 转信
下面的程序的目的是获取FTP上的目录列表,整理成树状结构。大部分是拷贝
netkit-ftp-0.17中的代码,自己到没有写什么。难保运行时不出什么错误,
网络通畅的时候,匿名从根目录递归ftp://csun.hust.edu.cn至底下五层子目
录还没有出什么问题。不知fion做的怎么样了,贴出来起个抛转引玉的作用。
原理就不多说了,就是对子目录递归CD然后LIST。程序中一个-b参数是为了编
历结果生成的文件方便的贴在BBS。
/*
buildftpfilelist.c:递归编历FTP目录,形成目录树
gcc -O6 -Wall -o buildftpfilelist buildftpfilelist.c
注:大部分代码来自于netkit-ftp-0.17,自己又剽窃了一回
实在对不住作者,这里只能对他们表示感谢,呵呵
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/ftp.h>
#include <netdb.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <getopt.h>
#define UC(b) (((int)b)&0xff)
#define ESC 0X1B
#define YELLOW "[1;33;40m"
#define GREEN "[1;36;40m"
#define WHITE "[1;37;40m"
void process_argument(int argc,char **argv);
void connectftp(char *host);
void loginftp(char *user,char *passwd);
void init_recurse(char * localfile);
void recurseftpdir(char * dirname,int level);
void finish_recurse(void);
int cd(char *dir);
int command(const char *fmt,...);
int getreply(int expecteof);
int recvrequest(const char *cmd,char *remote);
int initconn(void);
FILE * dataconn(const char *lmode);
void prnvertline(int );
void gotoneitem(int level,int dir,int begin,char *name);
void usage(char * prgname);
char host[128],user[64],passwd[64],startdir[128],localfile[64];
int level,bbs=0;
FILE *cin,*cout,*din,*fout;
FILE *lfp; /*file to store the recursing result*/
int code;
struct sockaddr_in localaddr;
int datasock;
int verbose=1;
#define FTPDIR struct ftpdir
FTPDIR
{
char dirname[256];
FTPDIR *nextdir;
};
char buffline[1024];
int main(int argc,char *argv[])
{
process_argument( argc,argv );
connectftp( host );
loginftp(user,passwd);
init_recurse( localfile );
recurseftpdir( startdir,1 );
finish_recurse();
return 0;
}
void process_argument(int argc,char **argv)
{
char c,*prgname;
strcpy(user,"anonymous");
strcpy(passwd,"ysqcn@263.net");
strcpy(startdir,"/");
strcpy(localfile,"-");
level = 5;
prgname=*argv;
opterr = 0;
while ( ( c = getopt(argc,argv,"h:u:p:d:f:l:?b") ) != EOF )
{
switch ( c )
{
case 'u':
strncpy( user,optarg,sizeof( user ) );
break;
case 'p':
strncpy( passwd,optarg,sizeof( passwd ) );
break;
case 'd':
strncpy( startdir,optarg,sizeof( startdir ) );
break;
case 'f':
strncpy( localfile,optarg,sizeof( localfile ) );
break;
case 'l':
level = atoi ( optarg );
break;
case 'b':
bbs = 1;
break;
case ':':
case '?':
case 'h':
usage(argv[0]);
exit(0);
}
}
argc -= optind;
argv += optind;
if ( argc == 0 )
{
usage(prgname);
exit(-1);
}
strncpy(host,*argv,sizeof(host));
return;
}
void init_recurse(char * localfile)
{
if ( strcmp(localfile,"-") == 0 )
lfp = stdout ;
else
if ( ( lfp = fopen( localfile,"w+" ) ) == NULL )
{
fprintf(stderr,"Open local file failed,output to stdout.\n");
lfp = stdout;
}
if ( cd( startdir ) )
{
fprintf(stderr,"Can't cd directory %s.\n",startdir);
exit(-1);
}
if ( command ("TYPE %s","A") != COMPLETE )
fprintf(stderr,"Set ascii mode failed.\n");
if ( bbs )
{
fprintf(lfp,"%c%c",ESC,ESC);
fprintf(lfp,"%s",WHITE);
}
verbose = 0;
fprintf(stdout,"\nBegin recursing ftp directory\n");
return;
}
void connectftp(char *host)
{
struct servent *sp;
register struct hostent *hp = 0;
struct sockaddr_in servaddr;
int s,len;
bzero( &servaddr,sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
if ( inet_pton( AF_INET,host, &servaddr.sin_addr ) != 1 )
{
hp = gethostbyname(host);
if (hp == NULL)
{
fprintf(stderr,"Get ftp ip address failed,exit.\n");
exit(-1);
}
servaddr.sin_family = hp->h_addrtype;
if ( hp->h_length > (int)sizeof(servaddr.sin_addr) )
hp->h_length = sizeof(servaddr.sin_addr);
memcpy(&servaddr.sin_addr,hp->h_addr,hp->h_length);
}
sp = getservbyname("ftp", "tcp");
if (sp == 0)
{
fprintf(stderr,"Get ftp service failed,exit.\n");
exit(-1);
}
servaddr.sin_port=sp->s_port;
if ( ( s = socket(AF_INET,SOCK_STREAM,0) ) == -1)
{
fprintf(stderr,"Create control socket faild,exit.\n");
exit(-1);
}
if ( connect(s, (struct sockaddr *)&servaddr, sizeof (servaddr)) < 0)
{
fprintf(stderr,"Connect ftp server faild,exit.\n");
exit(-1);
}
len = sizeof(localaddr);
if ( getsockname( s,(struct sockaddr *)&localaddr,&len ) < 0 )
{
fprintf(stderr,"Get control socket name faild,exit.\n");
exit(-1);
}
cin = fdopen(s, "r");
cout = fdopen(s, "w");
if (cin == NULL || cout == NULL)
{
fprintf(stderr,"Control socket fdopen faild,exit.\n");
if (cin)
(void) fclose(cin);
if (cout)
(void) fclose(cout);
exit(-1);
}
/* read startup message from server */
if (getreply(0) > 2)
{
if (cin)
(void) fclose(cin);
if (cout)
(void) fclose(cout);
fprintf(stderr,"Ftp server reply incorrectly,exit.\n");
exit(-1);
}
return;
}
void loginftp(char *user,char *passwd)
{
int n;
n = command("USER %s", user);
if (n == CONTINUE)
n = command("PASS %s", passwd);
if (n != COMPLETE)
{
fprintf(stderr, "Login ftp server failed,exit.\n");
exit(0);
}
return;
}
void recurseftpdir(char * dirname,int level0)
{
char mode[16],name[256],*pname,*tmpdir;
FTPDIR *dirhd=NULL,*current=NULL,*tmp;
if ( level0 > level )
return;
if ( lfp != stdout )
fprintf(stdout,".");
if ( ( fout = tmpfile() ) == NULL )
{
fprintf(stderr,"Open temp file failed,exit\n");
exit(-1);
}
if ( recvrequest("LIST",".") )
return;
(void)fflush(fout);
rewind(fout);
while ( fgets(buffline,1024,fout) != NULL )
{
sscanf(buffline,"%s%*s%*s%*s%*s%*s%*s%*s%s",mode,name);
if ( ( mode[0] != 'd' && mode[0] != '-' ) || !strcmp(name,".") || !strcmp(
name,"..") )
continue;
/* handle the name which includes space*/
buffline[strlen(buffline)-1]='\0';
pname = strstr(buffline,name);
strncpy( name,pname,sizeof(name) );
if ( mode[0] == 'd' )
{
tmp=(FTPDIR *) malloc( sizeof(FTPDIR) );
strncpy( tmp->dirname,name,sizeof(tmp->dirname) );
tmp->nextdir = NULL;
if ( dirhd == NULL )
dirhd = tmp;
else
current->nextdir = tmp;
current = tmp ;
continue;
}
gotoneitem(level0,0,0,name);
}
fclose(fout);
current = dirhd;
while ( current != NULL )
{
tmpdir = current->dirname;
gotoneitem(level0,1,1,tmpdir);
if ( cd( tmpdir ) == 0 )
{
recurseftpdir(current->dirname,level0+1);
if ( cd("..") )
{
fprintf(stderr,"Can't goto parent directory,exit.\n");
exit(-1);
}
}
gotoneitem(level0,1,0,tmpdir);
dirhd = current->nextdir;
free(current);
current = dirhd;
}
}
void finish_recurse(void)
{
fprintf(stdout,"\nFinish recursing ftp directory\n\n");
verbose=1;
command("QUIT");
}
int command(const char *fmt,...)
{
va_list ap;
int r;
va_start(ap, fmt);
vfprintf(cout, fmt, ap);
va_end(ap);
fprintf(cout, "\r\n");
(void) fflush(cout);
r=getreply( !strcmp(fmt, "QUIT") );
return r;
}
int getreply(int expecteof)
{
register int c, n;
register int dig;
int originalcode = 0, continuation = 0;
char reply_string[BUFSIZ];
char *cp;
cp = reply_string;
for (;;)
{
dig = n = code = 0;
while ( ( c = getc( cin ) ) != '\n')
{
dig++;
if ( c == EOF )
{
if (expecteof)
{
code = 221;
return (0);
}
fprintf(stderr,"ftp server closed abnormally,exit.\n");
exit(-1);
}
if ( verbose && c != '\r' )
(void) putchar(c);
if ( dig < 4 && isdigit(c) )
code = code * 10 + (c - '0');
if ( dig == 4 && c == '-' )
{
if (continuation)
code = 0;
continuation++;
}
if ( cp < &reply_string[sizeof(reply_string)-1] )
*cp++=c;
if (n == 0)
n = c;
}/*end while*/
if ( verbose )
(void) putchar(c);
(void) fflush (stdout);
if ( continuation && code != originalcode )
{
if (originalcode == 0)
originalcode = code;
continue;
}
*cp='\0';
return (n - '0');
}/*end for*/
}
int recvrequest(const char *cmd,char *remote)
{
int c,d,bytes=0,result;
char buf[1024];
if ( initconn() )
{
code=-1;
return(-1);
}
if (remote)
result = command("%s %s", cmd, remote);
else
result = command("%s", cmd);
if ( result != PRELIM )
return -1 ;
if ( ( din = dataconn("r") )== NULL )
{
fprintf(stderr,"\nData connection failed,exit.\n");
exit(-1);
}
loopin:
while ( ( c = getc(din) ) != EOF )
{
while ( c == '\r' )
{
bytes++;
if ( ( c = getc(din) ) != '\n' )
{
if ( ferror(fout) )
goto loopout;
(void) putc('\r', fout);
if (c == '\0')
{
bytes++;
goto loopin;
}
if (c == EOF)
goto loopin;
}
}
(void) putc(c, fout);
bytes++;
}
loopout:
if ( din )
fclose(din);
if ( datasock >= 0 )
{
close(datasock);
datasock = -1;
}
(void)getreply(0);
return(0);
}
int initconn(void)
{
register char * a ,* p;
socklen_t len;
int on = 1,result;
struct sockaddr_in dataaddr;
if ( ( datasock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
fprintf(stderr,"Data socket create faild,return.\n");
return (-1);
}
if ( setsockopt( datasock,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on) ) < 0
)
fprintf(stderr,"Data socket reuse failed.\n");
dataaddr = localaddr;
dataaddr.sin_port = 0;
if (bind(datasock, (struct sockaddr *)&dataaddr, sizeof (dataaddr)) < 0)
{
fprintf(stderr,"Data socket bind faild,return.\n");
return(-1);
}
len = sizeof (dataaddr);
if (getsockname(datasock, (struct sockaddr *)&dataaddr, &len) < 0)
{
fprintf(stderr,"Data socket getsockname faild,return.\n");
return(-1);
}
if (listen(datasock, 1) < 0)
{
fprintf(stderr,"Data socket listen faild,return.\n");
return(-1);
}
a = (char *)&dataaddr.sin_addr;
p = (char *)&dataaddr.sin_port;
result = command("PORT %d,%d,%d,%d,%d,%d",UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3
]),UC(p[0]), UC(p[1]));
if ( result == ERROR )
{
fprintf(stderr,"Send PORT command faild,return.\n");
return(-1);
}
return(0);
}
FILE * dataconn(const char *lmode)
{
struct sockaddr_in from;
int s;
socklen_t fromlen = sizeof(from);
s = accept(datasock, (struct sockaddr *) &from, &fromlen);
if (s < 0)
{
fprintf(stderr,"Data socket accept failed,exit.\n");
(void) close(datasock), datasock = -1;
return (NULL);
}
(void) close(datasock);
datasock = s;
return (fdopen(datasock, lmode));
}
int cd(char *dir)
{
if ( command("CWD %s", dir) == ERROR )
{
fprintf(stderr,"\nCan't cd directory %s\n",dir);
return -1;
}
return 0;
}
void gotoneitem(int level,int dir,int begin,char *name)
{
prnvertline(level);
fprintf(lfp,"%s","--[");
if ( bbs )
fprintf(lfp,"%c%c",ESC,ESC);
if ( dir )
{
if ( bbs )
fprintf(lfp,"%s",YELLOW);
if ( begin )
fprintf(lfp,"%s","目录开始");
else
fprintf(lfp,"%s","目录结束");
}
else
{
if ( bbs )
fprintf(lfp,"%s",GREEN);
fprintf(lfp,"%s","文件");
}
if ( bbs )
{
fprintf(lfp,"%c%c",ESC,ESC);
fprintf(lfp,"%s",WHITE);
}
fprintf(lfp,"%c%s\n",']',name);
}
void prnvertline(int level)
{
int i;
for ( i=1;i<=level;i++ )
fprintf(lfp,"%*c",i==1?1:3,'|');
}
void usage(char *prgname)
{
fprintf(stderr,"Usage:\t%s [-hupdflb] <host>\n",prgname);
fprintf(stderr,"\t-h print this help infomation\n");
fprintf(stderr,"\t-u ftp user name (default anonymous)\n");
fprintf(stderr,"\t-p ftp passwd (default ysqcn@263.net)\n");
fprintf(stderr,"\t-d start directory (default /)\n");
fprintf(stderr,"\t-f file name to save the result (default -)\n");
fprintf(stderr,"\t-l the depth of Subdirectory (default 5)\n");
fprintf(stderr,"\t-b output file will be pasted on bbs ? (default no)\n");
fprintf(stderr,"\thost ftp server name\n");
}
--
※ 修改:·ysqcn 於 09月18日23:31:13 修改本文·[FROM: 211.69.197.81]
※ 来源:.UNIX编程WWW apue.dhs.org. [FROM: 211.69.197.81]
--
※ 修改:·ysqcn 於 09月18日23:38:23 修改本文·[FROM: 211.69.197.81]
※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 211.69.197.81]
--
※ 转寄:·UNIX编程 apue.dhs.org·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店