Algorithm 版 (精华区)

发信人: Lerry (想不开·撞树), 信区: Algorithm
标  题: parker.c
发信站: 哈工大紫丁香 (2002年06月09日21:27:16 星期天), 站内信件

/*
 *    NoseyParker, the search engine for FTP archives
 *    Copyright (C) 1993-96 by Jiri A. Randus
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *    The author can be reached as follows:
 *      Internet:   <Jiri.Randus@vslib.cz>
 *      Phone:      ++42 48 5227374
 *      SnailMail:  Jiri Randus
 *                  KIN HF TU v Liberci
 *                  Halkova 6
 *            46117 Liberec
 *                  Czech Republic
 */
#define PARKER_VERSION   "3.75"
#include "parker.h"
char Line[MAX];
char *wordtbl[MAXWORDS];
int Words;
struct path {char *path, *file; };
struct path Lists[]={
                      "/","ls-lR.gz",
                      "/","ls-lR.Z",
                      "/","ls-lR",
                      "/pub/","ls-lR.gz",
                      "/pub/","ls-lR.Z",
                      "/pub/","ls-lR",
                      NULL, NULL
                    };
union InAddr {long addr; char bytes[SIZEOFINETADDR];} myaddr;
char resfile[MAX];
FILE *res;
char machine[MAX];
char TopDir[MAX];
FILE *CtlIn, *CtlOut;
struct sockaddr_in sa;
void Alarm(void)
{
  printf("\007'%s' received ALARM !\n",machine);
  unlink(resfile);
  exit(101);
}
char *TempFile(char *dir, char *prfx)
{
  static char fn[MAX];
  sprintf(fn,"%s/%sXXXXXX",dir,prfx);
  mktemp(fn);
  return(fn);
}
int WaitPwd(char *d)
{
  char *ptr;
  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,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';
      return(S_OK);
    }
    else if(*Line==NEGATIVE) return(S_ERROR);
    else if(*Line==PRENEGATIVE) return(S_ERROR);
  }
}
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);
  }
}
int WaitReply(void)
{
  while(1)
  {
    fgets(Line,MAX,CtlIn);
    if(feof(CtlIn)) return(S_CLOSED);
#ifdef DEBUG
    printf("%s",Line);
#endif
    if(Line[3]=='-') continue;
    if(*Line==POSITIVE) return(S_OK);
    if(*Line==PROCEED) return(S_OK);
    else if(*Line==NEGATIVE) return(S_ERROR);
  }
}
int WaitReply2(void)
{
  while(1)
  {
    fgets(Line,MAX,CtlIn);
    if(feof(CtlIn)) return(S_CLOSED);
#ifdef DEBUG
    printf("%s",Line);
#endif
    if(Line[3]=='-') continue;
    if(*Line=='2') return(S_OK);
    else if(*Line==PREPOSITIVE) return(S_PREOK);
    else if(*Line==NEGATIVE) return(S_ERROR);
  }
}
int WaitCon(char *m)
{
  int h;
  struct hostent *host;
  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);
  if(!(host=gethostbyname(m))) {perror("gethostbyname");return(S_ERROR);}
  memcpy(&sa.sin_addr.s_addr,host->h_addr,SIZEOFINETADDR);
  if(connect(h,(struct sockaddr *)&sa, sizeof(sa))<0) {
    perror("connect");
    return(S_ERROR);
  }
  if(CtlIn) fclose(CtlIn);
  if(CtlOut) fclose(CtlOut);
  if(!(CtlIn=fdopen(h,"r"))) {perror("fdopen(CtlIn)");exit(102);}
  if(!(CtlOut=fdopen(h,"w"))) {perror("fdopen(CtlOut)");exit(103);}
  setbuf(CtlIn,NULL);
  setbuf(CtlOut,NULL);
  return(S_OK);
}
void ConvertBS(char *p)
{
  while(*p)
  {
    if(*p=='\\') *p='/';
    p++;
  }
}
int Connect(char *p)
{
  if(WaitCon(p)!=S_OK) return(S_ERROR);
  if(WaitReply()!=S_OK) return(S_ERROR);
  fprintf(CtlOut,"USER anonymous\r\n");
  if(WaitReply()!=S_OK) return(S_ERROR);
  fprintf(CtlOut,"PASS %s\r\n",EMAILINFO);
  if(WaitReply()!=S_OK) return(S_ERROR);
  fprintf(CtlOut,"PWD\r\n");
  if(WaitPwd(TopDir)!=S_OK) return(S_ERROR);
  ConvertBS(TopDir);
  DEB("Logged in");
  return(S_OK);
}
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)) return(S_OK);
  return(S_ERROR);
}
char *DumpFile(char *path, FILE *f, int isdir)
{
  if(Words==2) {
    /* skip parent dir */
    if(!strcmp(wordtbl[0],".") || !strcmp(wordtbl[0],"..")) return(NULL);
    /* skip the `total' sum in the Unix listing */
    if(!strcmp(wordtbl[0],"total")) return(NULL);
    fprintf(f,"%s%s%s%s\n", path, (path[strlen(path)-1]=='/')?"":"/",
      wordtbl[0], isdir?"/":"");
    return(wordtbl[0]);
  }
  else {
    /* skip parent dir */
    if(!strcmp(wordtbl[Words-1],".") || !strcmp(wordtbl[Words-1],".."))
      return(NULL);
    fprintf(f,"%s%s%s%s", path, (path[strlen(path)-1]=='/')?"":"/",
      wordtbl[Words-1], isdir?"/":"");
    fprintf(f," %s %s_%s_%s\n",
    wordtbl[Words-5],wordtbl[Words-4],wordtbl[Words-3],wordtbl[Words-2]);
    return(wordtbl[Words-1]);
  }
}
int QueryDir(char *f, char shortlong, char *fn)
{
  struct sockaddr_in da;
  int foo;
  int hh;
  int rc;
  int i,s,ns;
  short Port;
  FILE *in, *out;
  char *ptr;
  da=sa;
  if((hh=creat(f,MODE))==-1) return(S_ERROR);
  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(shortlong) {
      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",fn);
              break;
      default: puts("Wrong kind of `shortlong' argument in QueryDir");
              return(S_ERROR);
    }
    if(WaitReply2()!=S_PREOK) return(S_ERROR_INFIMA);
    foo = sizeof da;
    ns = accept(s, (struct sockaddr *) &da, &foo);
    if (ns < 0)
    {
      perror("accept");
      return(S_ERROR);
    }
    close(s);
    if(shortlong==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"); 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);
}
int IsDir(char *l)
{
  if((Words==2) && !strcmp(wordtbl[1],"<DIR>")) return(S_OK);
  if((Words==5) && !strncmp(wordtbl[1],"DIR ",4)) return(S_OK);
  if((Words>=7) && (*l=='d')) return(S_OK);
  return(S_ERROR);
}
int IsFile(char *l)
{
  if((Words>=7) && (*l=='-')) return(S_OK);
  if((Words==5) && !strncmp(wordtbl[1],"A ",2)) return(S_OK);
  if((Words==2) && strcmp(wordtbl[1],"<DIR>")) return(S_OK);
  return(S_ERROR);
}
int WordCount(char *l)
{
  Words=0;
  while(*l)
  {
    while(l && (*l==' ')) l++;
    if(l && *l) {
      if(Words<MAXWORDS) wordtbl[Words]=l;
      Words++;
      while(*l && (*l!=' ')) l++;
      *l='\0';
      l++;
    }
  }
  if(Words<MAXWORDS) wordtbl[Words]=l;
  return(Words);
}
int DoLookup(char *p)
{
  char newdir[MAX];
  char *ptr;
  char tmpfn[MAX];
  FILE *dirf;
  int rc;
  alarm(TIMEOUT);
  fprintf(CtlOut,"CWD %s\r\n",p);
  if(WaitReply()!=S_OK) return(S_ERROR);
  if(feof(CtlIn)) {
    DEB("Connection failed!");
    exit(111);
  }
  fprintf(CtlOut,"PWD\r\n");
  WaitPwd(newdir);
  ConvertBS(newdir);
  if(strcasecmp(newdir,p)) {
    DEB("Dirs don't match");
    fprintf(stderr,"--- new: %s, expected: %s\n",newdir,p);
    return(S_ERROR);
  }
  strcpy(tmpfn,TempFile(WORKDIR,"Dir"));
  rc=QueryDir(tmpfn,0,NULL);
  if(rc!=S_ERROR_INFIMA) printf("%s:%s\n",machine,p);
  else {
    rc=S_OK;
    printf("%s:%s - Major BBS Bug\n",machine,p);
  }
  if(!(dirf=fopen(tmpfn,"r"))) {unlink(tmpfn);return(S_ERROR);}
  unlink(tmpfn);
  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';
    WordCount(Line);
    if(IsFile(Line)==S_OK) DumpFile(p,res,0);
    else if(IsDir(Line)==S_OK) {
      ptr=DumpFile(p,res,1);
      if(ptr) {
        strcpy(tmpfn,p);
        if(tmpfn[strlen(tmpfn)-1]!='/') strcat(tmpfn,"/");
        strcat(tmpfn,ptr);
      }
      else continue;
      rc=DoLookup(tmpfn);
      if(rc!=S_OK) {DEB("DoLookup returned an error"); rc=0;}
    }
  }
  fclose(dirf);
  return(rc);
}
void ConcStr(char *s, char *r)
{
  char *ptr, str[2];
  str[1]=0;
  ptr=r;
  while(*ptr)
  {if(*ptr=='/') strcat(s,"\\"); str[0]=*ptr; strcat(s,str); ptr++;}
}
void DoAwk(char *root, char *infile, char *outfile)
{
  char command[MAX];
  sprintf(command,"%s 'BEGIN {print \"%s/\";}", NAWK, TopDir);
  strcat(command," NF==1 { sub(\":\",\"/\",$1); ADRESAR=$1; };");
  strcat(command," NF>=7 && $1 ~ /^-/ { print ROOT \"/\" ADRESAR $NF ");
  strcat(command,"\" \" $(NF-4) \" \" $(NF-3) \"_\" $(NF-2) \"_\" $(NF-1);}"
);
  strcat(command," NF>=7 && $1 ~ /^d/ && $NF !~ /^\\..*$/ ");
  strcat(command,"{ print ROOT \"/\" ADRESAR $NF ");
  strcat(command,"\"/ \" $(NF-4) \" \" $(NF-3) \"_\" $(NF-2) \"_\" $(NF-1);}
");
  strcat(command,"' ROOT='");
  strcat(command,root);
  strcat(command,"' ADRESAR= ");
  strcat(command,infile);
  strcat(command," | sed -e 's/^.:\\//\\//' -e 's/\\\\/\\//g' -e 's/\\/\\//\
\//g' ");
  strcat(command,"-e 's/\\/.\\//\\//g' -e 's/^");
  ConcStr(command,root);
  ConcStr(command,root);
  strcat(command,"/");
  ConcStr(command,root);
  strcat(command,"/' | ");
  strcat(command,SORTPATH);
  strcat(command," -u | ");
  strcat(command,GZIP);
  strcat(command," > ");
  strcat(command,outfile);
#ifdef DEBUG
  printf("%s\n",command);
#endif
  system(command);
  DEB("Done DoAwk");
  return;
}
int DoRec(char *p, char *fileres)
{
  char newdir[MAX];
  char tmpfn[MAX];
  int lslRok;
  int rc;
  FILE *fh;
  alarm(TIMEOUT);
  fprintf(CtlOut,"CWD %s\r\n",p);
  if(WaitReply()!=S_OK) return(S_ERROR);
  if(feof(CtlIn)) {
    DEB("Connection failed!");
    exit(111);
  }
  fprintf(CtlOut,"PWD\r\n");
  WaitPwd(newdir);
  ConvertBS(newdir);
  if(strcasecmp(newdir,p)) return(S_ERROR);
  strcpy(tmpfn,TempFile(WORKDIR,"Dir2"));
  rc=QueryDir(tmpfn,1,NULL);
  alarm(0);
  lslRok=0;
  if(rc==S_OK) {
    if((fh=fopen(tmpfn,"r"))!=NULL) {
      while(1) {
        fgets(Line,MAX,fh);
        if(feof(fh)) break;
        if(strlen(Line)<3) {lslRok=1; break;}
      }
      fclose(fh);
      if(lslRok) {
        printf("%s:%s Recursive LIST -lR\n",machine,p);
        DoAwk(p,tmpfn,fileres);
        rc=S_OK;
      }
      else {
        printf("%s:%s I don't think this is a recursive list...\n",machine,p
);
        unlink(tmpfn);
        return(S_ERROR);
      }
    }
  }
  else {DEB("Giving up recursive listing");}
  unlink(tmpfn);
  DEB("Done with DoRec");
  return(rc);
}
int DolslR(char *p, char *fileres)
{
  char newdir[MAX];
  int i;
  char tmpfn[MAX];
  int rc;
  char command[MAX];
  rc=0;
  for(i=0;Lists[i].path;i++)
  {
    alarm(TIMEOUT);
    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;
    fprintf(CtlOut,"PWD\r\n");
    WaitPwd(newdir);
    ConvertBS(newdir);
    strcpy(tmpfn,TempFile(WORKDIR,"Dir3"));
    rc=QueryDir(tmpfn,2,Lists[i].file);
    if(rc!=S_OK) continue;
    break;
  }
  alarm(0);
  if(Lists[i].path) {
    printf("%s:%s Fetched %s%s\n",machine,p,Lists[i].path,Lists[i].file);
    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,tmpfn);
      strcat(command,".gz");
      system(command);
      strcpy(command,GUNZIP);
      strcat(command," ");
      strcat(command,tmpfn);
      system(command);
    }
    DoAwk(Lists[i].path,tmpfn,fileres);
  }
  else {DEB("Giving up remote ls-lR files...");}
  unlink(tmpfn);
  return(rc);
}
int Probe(char *p, char TypeOfFetch)
{
  char host[MAX];
  int rc;
  struct hostent *hoste;
  char command[MAX];
  DEB("Probe");
  gethostname(host,MAX);
  if(!(hoste=gethostbyname(host))) {perror("Probe gethostbyname"); exit(106)
;}
  memcpy(&myaddr.addr,hoste->h_addr,SIZEOFINETADDR);
  unlink(resfile);
  if(Connect(p)!=S_OK) {DEB("Couldn't connect");return(S_ERROR);}
  if(TypeOfFetch=='r') {
    rc=DoRec(TopDir,resfile);
    alarm(0);
    return(rc);
  }
  if(TypeOfFetch=='l') {
    unlink(resfile);
    res=fopen(resfile,"w");
    fprintf(res,"%s\n",TopDir);
    rc=DoLookup(TopDir);
    fclose(res);
    alarm(0);
    sprintf(command,"%s %s",GZIP,resfile);
    system(command);
    sprintf(command,"%s %s.gz %s",MV,resfile,resfile);
    system(command);
    return(rc);
  }
  if(((rc=DolslR(TopDir,resfile))!=S_OK) && (rc=DoRec(TopDir,resfile))!=S_OK
)
  {
    DEB("Lookup");
    unlink(resfile);
    res=fopen(resfile,"w");
    fprintf(res,"%s\n",TopDir);
    rc=DoLookup(TopDir);
    fclose(res);
    sprintf(command,"%s %s",GZIP,resfile);
    system(command);
    sprintf(command,"%s %s.gz %s",MV,resfile,resfile);
    system(command);
  }
  alarm(0);
  DEB("Done with Probe");
  return(rc);
}
void main(int n, char *p[])
{
  int fh;
  int child;
  char command[MAX];
  char *ptr;
  int hostnum;
  FILE *hosts;
  char TypeOfFetch;
  printf("NoseyParker %s, Gatherer V%s by Jiri A. Randus\n",VERSION,PARKER_V
ERSION);
  if(n>3) {
    printf("USAGE: parker\n");
    printf("       parker [-r|-l] <machine>\n");
    return;
  }
  nice(PARKER_NICE);
  signal(SIGALRM,(void (*)(int))Alarm);
  strcpy(resfile,TempFile(WORKDIR,"Res"));
  hostnum=0;
  TypeOfFetch=' ';
  if(n>=2) {
    if(*p[1]=='-') {
      TypeOfFetch=p[1][1];
      strcpy(machine,p[2]);
    }
    else strcpy(machine,p[1]);
    if(Probe(machine,TypeOfFetch)==S_OK) {
      if(!(fh=open(resfile,O_RDONLY)))
      printf("Cannot open the machine file\n");
      else {
        if(lseek(fh,0L,SEEK_END)>0L) {
          unlink(machine);
          strcpy(command,MV);
          strcat(command," ");
          strcat(command,resfile);
          strcat(command," ");
          strcat(command,machine);
          strcat(command,".gz");
          system(command);
        }
        else {DEB("Bad seek - filelen=0");}
        close(fh);
      }
      unlink(resfile);
    }
  }
  else {
    strcpy(Line,PARKER_HOME);
    strcat(Line,HOSTLIST);
    if(!(hosts=fopen(Line,"r"))) {
      printf("No Hosts %s\n",Line);
      return;
    }
    while(1)
    {
      fgets(Line,MAX,hosts);
      if(feof(hosts)) break;
      if((ptr=strchr(Line,CR))!=NULL) *ptr='\0';
      if((ptr=strchr(Line,LF))!=NULL) *ptr='\0';
      printf("Starting %s\n",Line);
      while((child=fork())==-1) sleep(1);
      if(!child) {
        strcpy(resfile,TempFile(WORKDIR,"Res2"));
        strcpy(machine,Line);
        if(Probe(machine,TypeOfFetch)==S_OK) {
          alarm(0);
          fh=open(resfile,O_RDONLY);
          if(lseek(fh,0L,SEEK_END)>0L) {
            unlink(machine);
            strcpy(command,MV);
            strcat(command," ");
            strcat(command,resfile);
            strcat(command," ");
            strcat(command,machine);
            strcat(command,".gz");
            system(command);
          }
          close(fh);
          unlink(resfile);
        }
        fclose(hosts);
        exit(0);
      }
      else {
        hostnum++;
        sleep(5);
        if(hostnum>=MAXAGENTS) {wait(&child);hostnum--;}
      }
    }
    fclose(hosts);
    while(hostnum--) wait(&child);
  }
}

--
当一个女孩儿觉得她不太容易了解那个男人的时候,她会爱他。

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 天外飞仙]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:211.542毫秒