2011年2月7日月曜日

テキストブラウザ at Linux

リナックスのHTML向けテキストブラウザをCで作りました。意外と情報がなく、結構苦労したので、そのソースを載せておきます。
なお、以下のソースはHTML以外にも対応できるように改造中のものです。また、インクルードするべきファイルは

stdio.h
string.h
stdlib.h
sys/types.h
sys/socket.h
netdb.h
netinet/in.h
sys/param.h
sys/uio.h
unistd.h

で、Linux向けです。

#define BUF_LEN 256

int main(int argc, char *argv[]){
  int s,sw,i;
  struct hostent *servhost;
  struct sockaddr_in server;
  struct servent *service;
  FILE *fp,*save;
  char buf[BUF_LEN];
  char host[BUF_LEN]="localhost";
  char path[BUF_LEN]="/";
  unsigned short port=0;
  char output[1024],character,hoge;

  if(argc>1){
    char host_path[BUF_LEN];

    if(strlen(argv[1])>BUF_LEN-1){
      fprintf(stderr,"URL is too long!\n");
      return 1;
    }
    if(strstr(argv[1],"http://")&&
       sscanf(argv[1],"http://%s",host_path)&&
       strcmp(argv[1],"http://")){
      char *p;
      p=strchr(host_path,'/');
      if(p!=NULL){
strcpy(path,p);
*p='\0';
strcpy(host,host_path);
      }else{
strcpy(host,host_path);
      }
      p=strchr(host,':');
      //puts(p);
      if(p!=NULL){
port=atoi(p+1);
*p='\0';
      }
      if(port<=0) port=80;
    }else{
      fprintf(stderr,"please input http://host/path... to URL\n");
      return 1;
    }
  }
  printf("get http://%s%s\n\n",host,path);
  servhost=gethostbyname(host);
  if(servhost==NULL){
    fprintf(stderr,"failed to get IP address from [%s]\n",host);
    return 0;
  }

  bzero((char *)&server,sizeof(server));
  server.sin_family=AF_INET;
  bcopy(servhost->h_addr,(char *)&server.sin_addr,servhost->h_length);

  if(port!=0){
    server.sin_port=htons(port);
  }else{
    service=getservbyname("http","tcp");
    if(service!=NULL){
      server.sin_port=service->s_port;
    }else{
      server.sin_port=htons(80);
    }
  }

  if((s=socket(AF_INET,SOCK_STREAM,0))<0){
    fprintf(stderr,"failed to make socket.\n");
    return 1;
  }

  if(connect(s,(struct sockaddr *)&server,sizeof(server))==-1){
    fprintf(stderr,"failed to connect.\n");
    return 1;
  }

  if((fp=fdopen(s,"r+"))==NULL){
    fprintf(stderr,"failed to fopen.\n");
    return 1;
  }

  setvbuf(fp,NULL,_IONBF,0);
  if(port==0) port=80;

  //fprintf(fp,"GET %s HTTP/1.0\r\nHost:%s:%d\r\n\r\n",path,host,port);
  /*
  //fprintf(fp,"testing");
  fprintf(fp,"GET %s HTTP/1.0\r\n\r\n",path);
  fprintf(fp,"User-Agent:MC_test\r\n\r\n");
  */
  //fprintf(fp,"Accept:*/*\r\n\r\n");
  //fprintf(fp,"Host:%s\r\n",host);
  /*  fprintf(fp,"Host:%s:%d\r\n\r\n",host,port);
  fprintf(fp,"Connection:Keep-Alive\r\n\r\n");
  //fprintf(fp,"\r\n");
*/
  sprintf(output,"GET %s HTTP/1.0\r\n",path);
  sprintf(buf,"User-Agent:MC_test\r\n");
  strcat(output,buf);
  sprintf(buf,"Accept:*/*\r\n");
  strcat(output,buf);
  //fprintf(fp,"Host:%s\r\n",host);
  sprintf(buf,"Host:%s:%d\r\n",host,port);
  strcat(output,buf);
  sprintf(buf,"Connection:Keep-Alive\r\n\r\n");
  strcat(output,buf);
  fprintf(fp,output);
  //fprintf(fp,"\r\n");

  fprintf(stdout,"Save File? :");
  scanf("%c%c",&character,&hoge);
  if(character=='y'){
    fprintf(stdout,"Please input save file name :");
    fgets(buf,sizeof(buf)/sizeof(char),stdin);
    buf[strlen(buf)-1]='\0';
    if((save=fopen(buf,"w"))==NULL){
      fprintf(stderr,"Save file cannot open\n");
      return -1;
    }
  }else{
    save=stdout;
  }
  fprintf(stdout,"html mode? :");
  scanf("%c",&hoge);
  scanf("%c",&character);
  sw=(character=='y')?0:1;
  if(sw==1){
    for(i=0;i<10;i++) fgets(buf,sizeof(buf),fp);
    while(1){
      if(fgets(buf,sizeof(buf),fp)==NULL) break;
      fprintf(save,"%s",buf);//Binary reading!
    }
  }else{
     while(1){
      if(fgets(buf,sizeof(buf),fp)==NULL) break;
      if(strncmp(buf,"<",1)==0) sw=1;
      if(sw!=1) continue;
      fprintf(save,"%s",buf);
      if(!(strncmp(buf+1,"/html",5))) break;
    }
  }



  fclose(fp);
  fclose(save);
  close(s);
  putchar('\n');

  return 0;
}

0 件のコメント: