#include "parker.h"
#include "collect.h"
char ReplyCode[4];
char Line[MAX];
char WorkDir[MAX];
union InAddr
{
long addr;
char bytes[SIZEOFINETADDR];
}
myaddr; // @info union类型的地址?
struct filestatist
{
int files;
int rms;
int mp3;
int exefiles;
int linuxfiles;
};
struct ftpsite site; // 这个ftp变量定义在这里,是全局变量。parker不支持对多个ftp的并发操作?
char machine[MAX];
FILE *CtlIn, *CtlOut; // @marble 分别作为输入通道和输出通道,具体什么作用? WaitCon等地方会用到。 这两个文件指针在哪里初始化的?
struct sockaddr_in sa; // @info,是一个Socket连接相关的全局变量,这个是Linux里面的结构体吗?
// 这个Alarm函数有什么作用,退出的代码还是101?
void Alarm (void)
{
printf ("\007'%s' received ALARM !\n", machine);
exit (101);
}
// 创建临时文件,那个.fm文件就是用这个函数产生的吗?
char * TempFile (char *dir, char *prfx)
{
int fd;
static char fn[MAX]; // @concept 这个变量为什么定义为static?
sprintf (fn, "%s/%sXXXXXX", dir, prfx); // 这个文件名中有斜杠? @debug
if ((fd = mkstemp (fn)) == -1) // @linux mkstemp函数,创建临时文件
perror("mkstemp"); // 如果创建文件失败,会报错
close(fd); // @linux 关闭文件描述符,不是使用C中的文件指针?
return (fn);
}
// 获得密码后,等待返回码
// d中存放当前路径
int GetPwd (char *d)
{
char *ptr;
fprintf (CtlOut, "PWD\r\n");
while (1)
{
fgets (Line, MAX, CtlIn); // Line又是前面定义的一个全局数组
if (feof (CtlIn))
return (S_CLOSED);
#ifdef DEBUG
printf ("%s", Line);
#endif /* */
if (Line[3] == '-')
continue;
if (!strncmp (Line, PWD, strlen (PWD)))
{
ptr = Line;
while (ptr++)
if (*ptr == '\"')
break;
else if (*ptr == ':')
{
ptr++;
break;
}
else if (!*ptr)
return (S_ERROR);
strcpy (d, ptr + 1);
if ((ptr = strchr (d, '\"')))
*ptr = '\0';
else if ((ptr = strchr (d, ':')))
*(++ptr) = '\0';
DEB (d);
return (S_OK);
}
else if (*Line == NEGATIVE)
return (S_ERROR);
else if (*Line == PRENEGATIVE)
return (S_ERROR);
}
}
/* wait if success */
int
WaitSucc (void)
{
while (1)
{
fgets (Line, MAX, CtlIn);
if (feof (CtlIn))
return (S_CLOSED);
#ifdef DEBUG
printf ("%s", Line);
#endif /* */
if (Line[3] == '-')
continue;
if (!strncmp (Line, SUCCESS, strlen (SUCCESS)))
return (S_OK);
else if (*Line == PRENEGATIVE)
return (S_ERROR);
else if (*Line == NEGATIVE)
return (S_ERROR);
}
}
// 等待ftp服务器的响应
int WaitReply (void)
{
bzero (ReplyCode, sizeof (ReplyCode)); // ReplyCode是前面定义的数组,bzero是什么函数?
while (1)
{
fgets (Line, MAX, CtlIn);
if (feof (CtlIn))
return (S_CLOSED);
#ifdef DEBUG
printf ("%s", Line);
#endif /* */
if (Line[3] == '-')
continue;
ReplyCode[0] = Line[0];
ReplyCode[1] = Line[1];
ReplyCode[2] = Line[2];
if (*Line == POSITIVE)
return (S_OK); /* POSITIVE = 2 */
if (*Line == PROCEED)
return (S_OK); /* PROCEED = 3 */
if (*Line == PREPOSITIVE)
return (S_PREOK); /* PREPREPOSIVE = 4 */
else if (*Line == NEGATIVE)
return (S_ERROR); /* NEGATIVE = 5 */
}
}
// char* 指向数组的操作,collect.c里用的很多
int GetHostipStr (char *hostdns, char *hostip)
{
int i;
unsigned char IP[4]; // ip4个数字大小正好是0~255
struct hostent *host;
if (!(host = gethostbyname (hostdns))) // gethostbyname是Linux的API,返回hostent结构体。。。通过域名获取ip?
{
printf ("gethostbyname:%s!\n", hostdns);
return (S_ERROR);
}
for (i = 0; i < 4; i++)
IP[i] = (host->h_addr[i]);
// sprintf用来干什么的?
sprintf (hostip, "%d.%d.%d.%d", IP[0], IP[1], IP[2], IP[3]);
return (S_OK);
}
// 连接ftp服务,Connect方法要用到这个方法,传入ftp地址
int WaitCon (char *m)
{
int h, a, port;
struct hostent *host;
struct sockaddr_in own_addr;
socklen_t own_addr_len = sizeof (own_addr);
// @info 打开socket连接,h为获得的端口号。Socket网络通信是很基础的概念。
if ((h = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
perror ("socket");
return (S_ERROR);
}
sa.sin_family = AF_INET;
// sa.sin_port=htons(FTPPORT);
port = atoi (site.ftp_port);
sa.sin_port = htons (port);
if (!(host = gethostbyname (m))) // 又获得host地址,如果获得为空,返回错误代码,
{
return (S_ERROR); // S_ERROR在collect.h中定义为-1.
}
sa.sin_addr.s_addr = ((struct in_addr *) (host->h_addr))->s_addr;
/* memcpy(&sa.sin_addr.s_addr,host->h_addr,SIZEOFINETADDR);*/
if (connect (h, (void *) &sa, sizeof (sa)) < 0)
{
perror ("connect");
return (S_ERROR);
}
if ((a = getsockname (h, (struct sockaddr *) &own_addr, &own_addr_len)))
{
perror ("getsockname");
printf ("error here!return %i\n", a);
return (S_ERROR);
};
myaddr.addr = own_addr.sin_addr.s_addr;
if (CtlIn)
fclose (CtlIn);
if (CtlOut)
fclose (CtlOut);
if (!(CtlIn = fdopen (h, "r"))) // marble h是一个Socket端口号,可以当文件打开,在Windows中怎么做类似操作。也是把Socket作为文件打开吗? 读的方式打开
{
perror ("fdopen(CtlIn)"); // @info 文件打开失败,异常代码102,为什么使用这种异常代码?
exit (102);
}
if (!(CtlOut = fdopen (h, "w"))) // @marble,同一个Socket端口,可以用两个文件指针打开? 不过这个是写操作。。。
{
perror ("fdopen(CtlOut)");
exit (103);
}
setbuf (CtlIn, NULL);
setbuf (CtlOut, NULL);
return (S_OK);
}
// 替换字符串,把\全部替换成/,什么作用?
void ConvertBS (char *p)
{
while (*p)
{
if (*p == '\\')
*p = '/';
p++;
}
}
// 连接ftp服务器,p为ftp域名
int Connect (char *p)
{
if (WaitCon (p) != S_OK)
return (S_ERROR);
if (WaitReply () != S_OK)
return (S_ERROR);
// 往Socket写东西?
fprintf (CtlOut, "USER %s\r\n", site.ftp_user);
if (WaitReply () != S_OK)
return (S_ERROR);
if (!strcmp (ReplyCode, "331"))
{
// 往Socket写密码?
fprintf (CtlOut, "PASS %s\r\n", site.ftp_pass);
// @process 检查ftp服务器的响应
if (WaitReply () != S_OK)
return (S_ERROR);
}
// @process 登录成功
DEB ("Logged in");
return (S_OK);
}
/* judge if the string is month */
int IsMonth (char *p)
{
int i;
static char *m[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec", NULL
}; // 相当于一个二维数组?
for (i = 0; i < 12; i++)
if (!strncasecmp (p, m[i], 3)) // @linux 比较两个字符串的前n个字符,忽略大小写
return (S_OK);
return (S_ERROR);
}
// 替换字符/为\
void ConcStr (char *s, char *r)
{
char *ptr, str[2];
str[1] = 0; // strcat时用到,一个字符一个字符地处理
ptr = r;
while (*ptr)
{
if (*ptr == '/')
strcat (s, "\\");
str[0] = *ptr; // @ques 这里是否需要加一个else啊?这个方法没有被调用到?
strcat (s, str);
ptr++;
}
}
// 处理目录显示格式
int DoFormat (char *topdir, char *infile, char *outfile,
struct filestatist *files)
{
FILE *fin, *fout;
char *ppdate = NULL, *ppsize = NULL, *ppfilename = NULL;
char *ptr, *ppt;
char unifn[MAX];
int i;
int IsDir = 0;
DEB (outfile);
files->exefiles = 0;
files->files = 0;
files->linuxfiles = 0;
files->mp3 = 0;
files->rms = 0;
if (!(fin = fopen (infile, "r")))
{
perror ("fopen in error in DoFormat");
return (S_ERROR);
}
if (!(fout = fopen (outfile, "w")))
{
perror ("fopen out error in DoFormat");
return (S_ERROR);
}
fprintf (fout, "%s\n", topdir);
while (!feof (fin))
{
fgets (Line, MAX, fin);
if ((ptr = strchr (Line, CR)) != NULL)
*ptr = '\0';
if ((ptr = strchr (Line, LF)) != NULL)
*ptr = '\0';
if (!strcmp (Line, ".:"))
continue;
if (!strncmp (Line, "total ", 6))
continue;
ptr = Line;
if (*ptr == '/')
ptr++;
if (!strncmp (ptr, "./", 2))
ptr = ptr + 2;
i = strlen (ptr);
ppt = ptr + i - 1;
if (*ppt == ':')
{
if (*ptr == '.' && *(ptr + 1) == '\\')
ptr = ptr + 2;
*ppt = '/';
*(ppt + 1) = '\0';
ConvertBS (ptr);
i = 0;
while (ptr && i < MAX)
{
if (*ptr == ' ')
{
strcpy (&unifn[i], "%20");
i = i + 3;
ptr++;
}
else
{
unifn[i] = *ptr;
i++;
ptr++;
}
}
unifn[i] = '\0';
fprintf (fout, "%s%s\n", topdir, unifn);
continue;
}
if (Line[0] == 'l' && (strstr (Line, " -> ")) != NULL)
{
/* unix link file handler */
continue;
}
else if (*Line <= '9' && *Line >= '0')
{
/* DOS dir list handler */
/* format :
06-14-00 09:42PM 2394 1.htm
06-14-00 09:42PM <DIR> DESKTOP
*/
ppdate = Line;
ptr = strchr (Line, ' ');
if (!ptr)
continue;
while (*ptr == ' ')
if (*ptr == '\0')
continue;
else
*ptr++ = '_';
ptr = strchr (ptr, ' ');
if (!ptr)
continue;
*ptr++ = '\0';
while (*ptr && *ptr == ' ')
ptr++;
if (*ptr == '\0')
continue;
if (!strncmp (ptr, "<DIR>", 5))
{
IsDir = 1;
ppsize = NULL;
}
else
{
IsDir = 0;
ppsize = ptr;
}
ptr = strchr (ptr + 1, ' ');
if (!ptr)
continue;
*ptr++ = '\0';
while (*ptr && *ptr == ' ')
ptr++;
if (*ptr == '\0')
continue;
ppfilename = ptr;
}
else if (*Line == 'd' || *Line == '-')
{
/* unix dir list handler */
/* format :
-rwxrw-rw- 1 root root 423421 Aug 7 1999 setup.exe
drwxrw-rw- 1 root root 0 Aug 22 15:34 DIR
*/
if (*Line == 'd')
IsDir = 1;
else
IsDir = 0;
ptr = Line;
for (i = 0; i < 4 && ptr; i++)
{
ptr = strchr (ptr, ' ');
if (!ptr)
continue;
while (*ptr == ' ')
*ptr++ = '\0';
}
if (!ptr)
continue;
ppsize = ptr;
ptr = strchr (ptr, ' ');
if (!ptr)
continue;
while (*ptr == ' ')
*ptr++ = '\0';
ppdate = ptr;
for (i = 0; i < 2 && ptr; i++)
{
ptr = strchr (ptr, ' ');
if (!ptr)
continue;
while (*ptr == ' ')
*ptr++ = '_';
}
ptr = strchr (ptr, ' ');
if (!ptr)
continue;
while (*ptr == ' ')
ptr++;
*(ptr - 1) = '\0';
ppfilename = ptr;
if ((ptr = strchr (ppfilename, '*')))
*ptr = '\0';
}
else
continue;
if (strstr (ppfilename, ".RM") || strstr (ppfilename, ".rm")
|| strstr (ppfilename, ".mov")
|| strstr (ppfilename, ".avi")
|| strstr (ppfilename, ".AVI")
|| strstr (ppfilename, ".mpg")
|| strstr (ppfilename, ".wmv") || strstr (ppfilename, ".MOV"))
files->rms++;
else if (strstr (ppfilename, ".MP3")
|| strstr (ppfilename, ".mp3")
|| strstr (ppfilename, ".wma")
|| strstr (ppfilename, ".WMA")
|| strstr (ppfilename, ".mpga") || strstr (ppfilename, ".mid"))
files->mp3++;
else if (strstr (ppfilename, ".EXE")
|| strstr (ppfilename, ".exe")
|| strstr (ppfilename, ".zip")
|| strstr (ppfilename, ".rar") || strstr (ppfilename, ".ZIP"))
files->exefiles++;
else if (strstr (ppfilename, ".rpm")
|| strstr (ppfilename, ".deb")
|| strstr (ppfilename, ".RPM")
|| strstr (ppfilename, ".tar")
|| strstr (ppfilename, ".bz2")
|| strstr (ppfilename, ".tgz") || strstr (ppfilename, ".gz"))
files->linuxfiles++;
files->files++;
i = 0;
ptr = ppfilename;
while (ptr && i < MAX)
{
if (*ptr == ' ')
{
strcpy (&unifn[i], "%20");
i = i + 3;
ptr++;
}
else
{
unifn[i] = *ptr;
i++;
ptr++;
}
if (*ptr == '\0')
break;
}
if (IsDir != 0)
{
unifn[i] = '/';
i++;
}
unifn[i] = '\0';
if (IsDir)
fprintf (fout, "%s 0 %s\n", unifn, ppdate);
else
fprintf (fout, "%s %s %s\n", unifn, ppsize, ppdate);
continue;
}
fclose (fout);
fclose (fin);
return (files->files);
}
// DoLISTlR,DRecursive,DoDownload会调用这个方法
// 打开Socket,接收ftp数据。告诉ftp服务器端口,等待响应
/* = 0 LIST */
/* = 1 LIST -lR */
/* = 2 TYPE I, RETR *fn, to get list file *fn */
// 把数据写到outfile中
int QueryDir (char *outfile, char fetchType, char *outfilename)
{
struct sockaddr_in da;
int foo;
int hh;
int rc;
int i, s, ns;
int Port;
FILE *in, *out;
char *ptr;
da = sa;
da.sin_addr.s_addr = myaddr.addr;
da.sin_port = 0;
s = socket (AF_INET, SOCK_STREAM, 0);
if (s < 0)
{
perror ("socket");
return (S_ERROR);
}
foo = sizeof (da);
while (bind (s, (struct sockaddr *) &da, foo) < 0)
{
perror ("bind");
return (S_ERROR);
}
if (getsockname (s, (struct sockaddr *) &da, &foo) < 0)
{
perror ("ftp: getsockname");
return (S_ERROR);
}
Port = ntohs (da.sin_port);
if (listen (s, 1) < 0)
{
perror ("listen");
return (S_ERROR);
}
fprintf (CtlOut, "PORT %u,%u,%u,%u,%u,%u\r\n",
(unsigned char) myaddr.bytes[0],
(unsigned char) myaddr.bytes[1],
(unsigned char) myaddr.bytes[2],
(unsigned char) myaddr.bytes[3], Port / 256,
Port - (unsigned int) (Port / 256) * 256);
if ((rc = WaitReply ()) == S_OK)
{
switch (fetchType)
{
case 0:
fprintf (CtlOut, "LIST\r\n");
break;
case 1:
fprintf (CtlOut, "LIST -lR\r\n");
break;
case 2:
fprintf (CtlOut, "TYPE I\r\n");
WaitReply ();
fprintf (CtlOut, "RETR %s\r\n", outfilename);
break;
default:
puts ("Wrong kind of `fetchType' argument in QueryDir");
return (S_ERROR);
}
if (WaitReply () != S_PREOK)
return (S_ERROR_INFIMA);
if ((hh = creat (outfile, MODE)) == -1)
return (S_ERROR);
foo = sizeof da;
ns = accept (s, (struct sockaddr *) &da, &foo);
if (ns < 0)
{
perror ("accept");
return (S_ERROR);
}
close (s);
if (fetchType == 2)
while (1)
{
i = read (ns, Line, MAX);
if (!i)
break;
alarm (TIMEOUT);
write (hh, Line, i);
}
else
{
if (!(in = fdopen (ns, "r")))
{
perror ("fdopen in here");
exit (0);
return (S_ERROR);
}
if (!(out = fdopen (hh, "w")))
{
perror ("fdopen out");
return (S_ERROR);
}
while (1)
{
fgets (Line, MAX, in);
if (feof (in))
break;
if ((ptr = strchr (Line, CR)) != NULL)
*ptr = '\0';
if ((ptr = strchr (Line, LF)) != NULL)
*ptr = '\0';
fprintf (out, "%s\n", Line);
alarm (TIMEOUT);
}
fclose (out);
fclose (in);
}
DEB ("Done with fetching the directory");
close (ns);
close (hh);
rc = WaitSucc ();
}
return (rc);
}
/* use QueryDir(use LIST -lR) to get entire dir list */
int DoLISTlR (char *outfile)
{
int rc;
fprintf (CtlOut, "CWD %s\r\n", "/");
rc = WaitReply ();
if (rc == S_CLOSED)
{
DEB ("Connection closed!!!");
return (S_ERROR);
}
rc = QueryDir (outfile, 1, NULL);
DEB ("Done with List-lR");
return (rc);
}
/* use recursive LIST to get the entire directory list */
int DoRecursive (char *topdir, FILE * res)
{
char *ptr;
char tmpfn[MAX], tmpstr[MAX];
FILE *dirf;
int rc, i;
fprintf (CtlOut, "CWD %s\r\n", topdir);
rc = WaitReply ();
if (rc == S_CLOSED)
{
DEB ("Connection closed!!!");
return (S_ERROR);
}
GetPwd (tmpstr);
if (strcmp (topdir, tmpstr))
return (S_ERROR);
ConvertBS (topdir);
strcpy (tmpfn, TempFile (WorkDir, "Dir"));
rc = QueryDir (tmpfn, 0, NULL);
if (rc != S_ERROR_INFIMA)
printf ("%s:%s\n", machine, topdir);
else
{
rc = S_OK;
printf ("%s:%s - Major BBS Bug\n", machine, topdir);
}
if (!(dirf = fopen (tmpfn, "r")))
{
unlink (tmpfn);
return (S_ERROR);
}
if (strcmp (topdir, "/"))
fprintf (res, "%s:\n", topdir);
while (1)
{
fgets (Line, MAX, dirf);
if (feof (dirf))
break;
fputs (Line, res);
}
rewind (dirf);
while (rc == S_OK)
{
fgets (Line, MAX, dirf);
if (feof (dirf))
{
rc = S_OK;
break;
}
if ((ptr = strchr (Line, CR)) != NULL)
*ptr = '\0';
if ((ptr = strchr (Line, LF)) != NULL)
*ptr = '\0';
if (1)
{
DEB (Line);
if (*Line == 'l' && strstr (Line, " -> "))
continue;
if (*Line == 'd')
{
i = 1;
ptr = Line;
while (i < 9 && ptr)
{
ptr = strchr (ptr, ' ');
if (ptr)
{
while (*ptr == ' ' && ptr)
{
ptr++;
}
}
i++;
}
}
else if ((ptr = strstr (Line, "<DIR>")))
{
ptr = ptr + 5;
while (*ptr == ' ' && ptr)
ptr++;
}
else
continue;
strcpy (tmpstr, topdir);
if (tmpstr[strlen (tmpstr) - 1] != '/')
strcat (tmpstr, "/");
strcat (tmpstr, ptr);
DEB (tmpstr);
rc = DoRecursive (tmpstr, res);
if (rc != S_OK)
{
DEB ("DoLookup returned an error");
rc = 0;
}
}
}
fclose (dirf);
unlink (tmpfn);
return (rc);
}
/* use QueryDir(download the list file like list-lR.gz ) to get entire dir list */
int
DoDownload (char *outfile, char *topdir)
{
char newdir[MAX];
int i;
char tmpfn[MAX];
int rc;
char command[MAX];
struct path
{
char *path, *file;
};
struct path Lists[7];
Lists[0] = (struct path)
{
"/", "ls-lR.gz"};
Lists[1] = (struct path)
{
"/", "ls-lR.Z"};
Lists[2] = (struct path)
{
"/", "ls-lR"};
Lists[3] = (struct path)
{
"/pub/", "ls-lR.gz"};
Lists[4] = (struct path)
{
"/pub/", "ls-lR.Z"};
Lists[5] = (struct path)
{
"/pub/", "ls-lR"};
Lists[6] = (struct path)
{
NULL, NULL};
rc = 0;
strcpy (tmpfn, TempFile (WorkDir, "Down"));
for (i = 0; Lists[i].path; i++)
{
fprintf (CtlOut, "CWD %s\r\n", Lists[i].path);
rc = WaitReply ();
if (rc == S_CLOSED)
{
DEB ("Connection closed!!!");
exit (111);
}
else if (rc != S_OK)
continue;
GetPwd (newdir);
ConvertBS (newdir);
if ((rc = QueryDir (tmpfn, 2, Lists[i].file)) == S_OK)
break;
}
if (Lists[i].path)
{
sprintf (command, "%s:%s Fetched %s%s\n", machine, topdir,
Lists[i].path, Lists[i].file);
DEB (command);
if (toupper (Lists[i].file[strlen (Lists[i].file) - 1]) == 'Z')
{
DEB ("Uncompressing");
strcpy (command, MV);
strcat (command, " ");
strcat (command, tmpfn);
strcat (command, " ");
strcat (command, outfile);
strcat (command, ".gz");
system (command);
strcpy (command, GUNZIP);
strcat (command, " ");
strcat (command, outfile);
system (command);
}
else
{
strcpy (command, MV);
strcat (command, " ");
strcat (command, tmpfn);
strcat (command, " ");
strcat (command, outfile);
system (command);
}
}
else
{
DEB ("Giving up remote ls-lR files...");
unlink (tmpfn);
}
return (rc);
}
// 尝试所有方式来获取列表,通过递归方式进行吗?
int Probe (char *outputdir, char TypeOfFetch)
{
int rc; // 返回代码
FILE *res = NULL;
char tempfile[MAX];
char resfile[MAX];
char command[MAX];
char TopDir[MAX]; // ftp顶层目录
char HostIP[MAX];
char URL[MAX];
struct filestatist files; // filestatist定义在collect.c开头
GetHostipStr (machine, HostIP); // 把值写到HostIP数组?通过域名获取IP,然后把IP sprintf到HostIP数组(不用sprintf也可以做到的,直接赋值)
sprintf (resfile, "%s/%s.org", WorkDir, HostIP); // WorkDir又是全局变量
DEB ("Probe"); // DEB是一个宏,定义在collect.h中。
alarm (TIMEOUT);
if (Connect (machine) != S_OK)
{
DEB ("Couldn't connect");
return (S_ERROR);
}
strcpy (TopDir, "/");
if (TypeOfFetch == 'd')
{
rc = DoDownload (resfile, TopDir);
}
else if (TypeOfFetch == 'l')
{
rc = DoLISTlR (resfile);
}
else if (TypeOfFetch == 'r')
{
res = fopen (resfile, "w");
rc = DoRecursive (TopDir, res);
fclose (res);
}
else
if ((rc = DoLISTlR (resfile)) != S_OK
&& ((rc = DoDownload (resfile, TopDir)) != S_OK))
{
DEB ("use Recursive Look up");
res = fopen (resfile, "w");
if ((rc = DoRecursive (TopDir, res)) != S_OK)
return (S_ERROR);
fclose (res);
}
if (rc != S_OK)
return (S_ERROR);
alarm (0);
sprintf (tempfile, "%s/%s.fmt", WorkDir, HostIP);
DoFormat (TopDir, resfile, tempfile, &files);
// For debug usage.
// printf("port: %s\n user: %s\n pass: %s\n name: %s\n hostip: %s\n",site.ftp_port,site.ftp_user,site.ftp_pass,site.ftp_name,
// HostIP);
// exit(0);
//patched by Sunry Chen 2006-02-22
if (strcasecmp(site.ftp_user,"ANONYMOUS"))
{
strcat(URL,site.ftp_user);
strcat(URL,":");
strcat(URL,site.ftp_pass);
strcat(URL,"@");
}
strcat(URL,HostIP);
printf("--- URL: %s\n",URL);
sprintf (command, "%s/%s/%s %s %s/%s -s", PARKER_HOME, BINDIR,
// LZOCOMP, tempfile, outputdir, HostIP);
LZOCOMP, tempfile, outputdir, URL);
system (command);
unlink (resfile);
unlink (tempfile);
sprintf (resfile, "%s/%s/%s.%s", PARKER_HOME, HOSTDATADIR, HostIP,
HOSTINFOEXT);
res = fopen (resfile, "w");
fprintf (res, "%s %s %d %d %d %d %d\n", machine, HostIP,
files.files, files.rms, files.mp3, files.exefiles,
files.linuxfiles);
fclose (res);
DEB ("Done with Probe");
return (rc);
}
// 支持多种ftp列表格式,整个过程实际上就是设置了site的值
void scanline (char line[])
{
char *scan, *at, *colon;
site.ftp_name[0]='\0'; // 初始化site结构体成员变量
site.ftp_port[0]='\0';
site.ftp_user[0]='\0';
site.ftp_pass[0]='\0';
if ((scan = strchr (line, CR)) != NULL) // 是宏,定义在parker.h中,CR是13,LF是10(这两个东西和换行有关系,检查line[]里面的字符,看是否有这种换行符,如果有的话,scan就指向 空地址,这有什么用吗?)
*scan = '\0';
if ((scan = strchr (line, LF)) != NULL) // strchr,如果找不到指定字符,就返回空指针。 LF, CR这两个名称,在ASCII表中就有定义,是比较特殊的两个字符。
*scan = '\0';
scan = strstr (line, "ftp://"); // 检查line,指向第一个ftp://字符串,如果line中没有ftp://字符串,scan为空
if (!scan)
scan = line; // 表明line没有ftp://前缀,scan直接等于line字符串。
else
scan = line + 6; // 或者跳过前面的ftp://前缀,scan里面不能有ftp://前缀
at = strchr (scan, '@'); // line中ftp://前缀已经被去掉,返回出现@的位置
colon = strchr (scan, ':'); // 返回出现:的地方,用于提取用户名@密码:地址?
if (!at)
{
if (colon)
{
*colon = '\0'; // 没有@,表明:后面就是端口号了。为什么把:置为\0呢,之后计算只用到前面的串了吗?
colon++;
strcpy (site.ftp_port, colon); // 获取端口号
}
strcpy (site.ftp_name, scan); // 直接把ftp名称拷贝过来,因为:已经被置为\0
strcpy (machine, site.ftp_name);
}
else if (at != NULL)
{
*at = '\0';
at++;
if (colon && colon < at)
{
*colon = '\0';
colon++;
strcpy (site.ftp_pass, colon);
}
strcpy (site.ftp_user, scan); // 冒号意见那个被设置为\0
colon = strchr (at, ':');
if (colon)
{
*colon = '\0';
colon++;
strcpy (site.ftp_port, colon);
}
strcpy (site.ftp_name, at);
strcpy (machine, site.ftp_name);
}
if (site.ftp_port[0] == '\0')
strcpy (site.ftp_port, "21"); // 默认端口21
if (site.ftp_user[0] == '\0')
{
strcpy (site.ftp_user, ANONYMOUS); // 默认使用匿名登录
strcpy (site.ftp_pass, ANONYPASS);
}
}
int main (int n, char *p[])
{
char LZODir[MAX];
char TypeOfFetch = ' ';
int child;
int hostnum;
FILE *hostListRes;
if (n > 3)
{
printf ("USAGE: collect\n");
printf (" collect [-d|-l|-r] [destination ftp host]\n");
printf (" -d download the list file like ls-lR.tgz \n");
printf (" -l use \"LIST -lR\" \n");
printf (" -r use recursive \"LIST\" to get the entire dir \n");
return (0);
}
nice (PARKER_NICE); // @info 设定进程的优先级?
signal (SIGALRM, (void (*)(int)) Alarm); // @info 前面定义的Alarm函数用到这里,用于发送信号?
sprintf (WorkDir, "%s/%s", PARKER_HOME, WORKDIR);
sprintf (LZODir, "%s/%s", PARKER_HOME, LZOFILEDATADIR);
hostnum = 0;
if (n > 1 && *p[1] == '-')
TypeOfFetch = p[1][1];
if (n == 3 || (n == 2 && *p[1] != '-'))
{
if (n == 3)
strcpy (machine, p[2]);
else
strcpy (machine, p[1]);
strcpy (site.ftp_port, "21");
strcpy (site.ftp_user, ANONYMOUS);
strcpy (site.ftp_pass, ANONYPASS);
if (Probe (LZODir, TypeOfFetch) != S_OK)
printf ("Cannot get the ftp data on host %s.\n", machine);
}
else
{ /* use default collect host list */
strcpy (Line, HOSTLIST);
if (!(hostListRes = fopen (Line, "r")))
{
printf ("Can't open Collect list file: %s\n", Line);
return 0;
}
while (1)
{
fgets (Line, MAX, hostListRes);
if (feof (hostListRes))
break;
while ((child = fork ()) == -1)
sleep (1);
if (!child)
{
// strcpy(machine, Line);
scanline (Line);
Probe (LZODir, TypeOfFetch);
exit (0);
}
else
{
hostnum++;
sleep (5);
if (hostnum >= MAXAGENTS)
{
wait (&child);
hostnum--;
}
}
}
fclose (hostListRes);
while (hostnum--)
wait (&child);
}
return 0;
}
1、怎么只认一个ftp,CollectList是从哪里开始读入的?
2、collect过程中生成了如下文件/var/parker/tmp/xxx.fmt,但是之后又被删除了。
/var/parker/LZOData/xxx 在LZOData目录下又生成了一个文件,但是不大,我看到的大小怎么只有8K,一个很大的ftp站点,难道就这么写内容?居然还显示是个
二进制文件,是压缩过的索引?
3、把数组的前length个字节清零,可以直接用char* for实现,也可以用memset实现,这种函数没咋用过啊。像bzero(不是bezero。。)这种函数,在做嵌入式时,可能需要自己重新实现这些方法?