/*
 * Copyright 2001 pilot <pilot@monkey.org>
 * All rights reserved.
 *
 * 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. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "arirang.h"

void
timeout(int sig)
{
int sock;
close(sock);
}

void
sigchld(int sig)
{
int status;
wait(&status);
signal(SIGCHLD,sigchld);
}

int
main(int argc, char *argv[])
{
       int pcount=0;

        unsigned short int MAX_PROCESSES=30;
        unsigned short int RULE_PROCESSES=0;
        unsigned int http_port=80;  
        unsigned long start=0,end=0,count;
	unsigned short int statuscode=1;

        int ch; 
        char *server;
        char *filename;
	FILE *scanlist;
        char list[50]; 

	char *rulefile;
	int gflags=0;
	int oflags=0;
	int hflags=0;
	int fflags=0;
	int rflags=0;

        if (argc < 3)
	usage();
	
	scrview();

    opterr=0;
    

 while((ch=getopt(argc,argv,"GOp:f:h:s:e:r:vP:"))!=-1){
      switch(ch)
	{
		case 'G':
		gflags=1;
		break;
		case 'O':
		oflags=1;
		break;
		case 'p':
		http_port=atoi(optarg);
		break;
         	case 'f':
                fflags=1;
                filename=optarg;
                break;
                case 'h':
		hflags=1;
		server=optarg;
		break;
                case 's':
                start=inet_addr(optarg);
                break;
                case 'e':
                end=inet_addr(optarg);
		break;
		case 'r':
                rflags=1;
                rulefile=optarg;
		break;
                case 'v':
                statuscode=2;
                break;
                case 'P':
                MAX_PROCESSES=atoi(optarg);
                RULE_PROCESSES=atoi(optarg);
                break;
		default:
		usage();
     }
  }

fprintf(stdout,"\n  Starting arirang %s    http://www.monkey.org/~pilot \n\n",VERSION);
if (gflags&&hflags)
 grabhead(server,http_port);     		

if (oflags&&hflags)
 osdetect(server);
      
 if (fflags==1&&rflags==0){
        
        if ((scanlist=fopen(filename,"rt")) == NULL){
        fprintf(stderr,"File %s open error\n",filename);
        exit(0);
        }

       signal(SIGALRM,timeout);
       pcount=0; 
        

       while(!feof(scanlist)){
                  fscanf(scanlist,"%s\n",list);
                  if ( pcount> MAX_PROCESSES) wait(NULL);
                 
                  switch(fork()) {
                  case 0: 
                  alarm(2);
                  if (gflags) grabhead(list,http_port);
                  if (oflags) osdetect(list);
                  exit(0);
                  case -1:
                         perror("fork err");
                         exit(-1);
                  default:
                   pcount++;
                   break;
                                 }
                     }
      
      fclose(scanlist);
       while(pcount--) wait(NULL);
 
    }
 
 if (start&&end&&rflags==0){
     signal(SIGALRM,timeout);
     pcount=0;
     for (count=ntohl(start); count<=ntohl(end);count++){
         
         if(pcount > MAX_PROCESSES) wait(NULL); 
        
          switch(fork()) {
          case 0:
         if ((count & 0xff) == 0 || (count & 0xff) == 255) continue;
         alarm(2);
         grabheadW(count,http_port);
         exit(0);
          case -1:
                perror("fork");
                exit(-1);
          default:
            pcount++;
            break;
                      }
            }
         while(pcount--) wait(NULL); 
         
	} 
 if (rflags&&statuscode&&hflags){
         if (RULE_PROCESSES==0)
         scanrule(server,http_port,rulefile,statuscode);
         if (RULE_PROCESSES!=0)
         scanruleP(server,http_port,rulefile,statuscode,RULE_PROCESSES);
         }


 if (rflags&&statuscode&&fflags){
     if ((scanlist=fopen(filename,"rt")) == NULL){
        fprintf(stderr,"File %s open error\n",filename);
        exit(1);
        }
       while(!feof(scanlist)){
       fscanf(scanlist,"%s\n",list);

       if (gflags)
       grabhead(list,http_port);
      
       if (oflags)   
       osdetect(list);
       if (RULE_PROCESSES==0)
       scanrule(list,http_port,rulefile,statuscode);
 
       if (RULE_PROCESSES!=0)
       scanruleP(list,http_port,rulefile,statuscode,RULE_PROCESSES);
       }
      fclose(scanlist);
    } 
  

  if (rflags&&start&&end){
     for (count=ntohl(start); count<=ntohl(end);count++){
         if ((count & 0xff) == 0 || (count & 0xff) == 255) continue;
         scanruleWP(count,http_port,rulefile,statuscode,MAX_PROCESSES);
           }  
       }
return 0;
}

