

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<pthread.h>

#include"sitar.h"
#include"sitar_com.h"
#include<almemsys/almemsys.h>
#include"jpreturn.h"
#include<file_comp/file_comp.h>

extern global_data_t gd;
extern swap_array_t sa;

extern pthread_mutex_t file1_mutex;
extern pthread_mutex_t fdstat_mutex;
extern pthread_mutex_t thread_mutex;




// ポートスキャンとコマンド監視用のスレッド関数
int sitar_scan(void)
{
FILE * fp;
long int fdcount;
int stat, bstat, ren, count, delmi, fdclean, fdcountstat, sleepcount, tret, thread_co, fileget_time, filestop_time;
time_t fileget_start, fileget_stop;

stat = 0;
bstat = 0;
ren = 0;
count = 0;
delmi = 1;
thread_co = 0;

tret = 0;
errno = 0;

fileget_time = 0;
fileget_start = 0;
fileget_stop = 0;
filestop_time = 0;



for(;;){

   #ifdef SCAN_BUG
   printf("SCAN_BUG: sitar_scan(): ループの開始またはループの先頭に戻りました fdcount<%ld>\n", fdcount);
   #endif

   // スレッド生成の時間計測開始
   fileget_start = time(NULL);
   #ifdef BAT_DEBUG
   printf("BAT_DEBUG: sitar_scan(): スレッド生成の時間計測開始 (%d):\n", fileget_start);
   #endif


   if((fp = fopen(gd.fi.bat2_filename_2, "r+"))!=NULL){
      #ifdef SCAN_BUG
      printf("SCAN_BUG: sitar_scan(): 二次ファイルを開きました。\n");
      #endif

      while(1){
         // 二次ファイルのポインターから一行読み込み
         gd.sd.swap = safe_fpcat(fp, gd.sd.swap, &stat, BUF_MAX);

         //  先頭に＊＊＊のある場合はdelmiに目印
         delmi = memcmp(gd.sd.swap, "*****", 5);

         if(stat == 0 && delmi != 0 && 0x00 != gd.sd.swap[0]){
            gd.sd.swap = check_strtol(gd.sd.swap);
            if('#' != gd.sd.swap[0]){

               if(ren < (gd.td.tbufmax - 1)){
                  sa.tmp_data[ren] = safe_memcpy(sa.tmp_data[ren], gd.sd.swap, BUF_MAX);
                  #ifdef FREE_BUG
                  printf("FREE: single sitar_scan(1): gd.sd.swap %s\n", gd.sd.swap);
                  #endif
                  gd.sd.swap = null_free(gd.sd.swap);
                  ren++;
                  }
               else{
                  fprintf(stderr ,"sitar_scan(): バッファの上限値を越えています。 <%d> : gd.td.tbufmax<%d>\n",
                    ren, gd.td.tbufmax);
                  ren = ren - 1;
                  sa.main_buf_err = 1;
                  }
               }
            else{
               #ifdef FREE_BUG
               printf("FREE: single sitar_scan(2): gd.sd.swap %s\n", gd.sd.swap);
               #endif
               gd.sd.swap = null_free(gd.sd.swap);
               }
            }



         /*  ---- **** Block ------ */
         if(ren < gd.td.tbufmax && stat == 0 && delmi == 0){

            for(fdcountstat = 0;fdcountstat == 0;){

               safe_pthread_mutex_lock(&fdstat_mutex);
               for(fdcount = 0; fdcount < gd.td.tcount; fdcount++){
                  #ifdef SCAN_BUG
                  printf("SCAN_BUG: sitar_scan(***block): fdcount<%ld>fdstat<%d>\n",
                    fdcount, gd.td.fdstat[fdcount]);
                  #endif
                  if(gd.td.fdstat[fdcount] != 1){
                     gd.td.fdstat[fdcount] = 1;
                     #ifdef FREE_BUG
                     printf("FREE: sitar_scan(***block): safree(%ld) fdcount\n", fdcount);
                     #endif
                     sanull(fdcount);
                     break;
                     }
                  }
               pthread_mutex_unlock(&fdstat_mutex);


               // 上限値よりもfdcountが小さい 
               if(fdcount < gd.td.tcount){
                  for(count = 0; count < ren; count++){

                     sa.swap_data[fdcount][count] = safe_memcpy(
                         sa.swap_data[fdcount][count], sa.tmp_data[count], BUF_MAX); 

                     #ifdef SCAN_BUG
                     printf("SCAN_BUG: sitar_scan(***block): Thread No = %ld\n", fdcount);
                     #endif
                     }

                  if(sa.main_buf_err == 1){
                     sa.buf_err[fdcount] = 1;
                     sa.main_buf_err = 0;
                     }
                  else{
                     sa.buf_err[fdcount] = 0;
                     }
                  // pthread_create
                  #ifdef SCAN_BUG
                  printf("SCAN_BUG: sitar_scan(***block): あたらしいスレッド Thread No = %ld\n", fdcount);
                  #endif
                  // 次のfor loopで抜ける設定
                  fdcountstat = 1;


                  // スレッドの上限を確認して、多い場合はまち
                  while(1){
                     safe_pthread_mutex_lock(&thread_mutex);
                     thread_co = gd.td.thread_count;
                     pthread_mutex_unlock(&thread_mutex);
                     if(thread_co < gd.td.thread_max){
                        #ifdef IN_THREAD
                        printf("IN_THREAD: sitar_scan(1): %d スレッド作成\n", gd.td.thread_count);
                        #endif
                        break;
                        }
                     #ifdef IN_THREAD
                     printf("IN_THREAD: sitar_scan(1): %d スレッド作成待ち\n", gd.td.thread_count);
                     #endif
                     usleep(SLEEP_TIME);
                     }

                  if((tret = pthread_create(&sa.pt[fdcount], NULL, (void *)scan_block, (int *)fdcount)) != 0){
                     fprintf(stderr,"sitar_scan.c: pthread_create(0): %d %d\n",tret, errno);
                     }
                  }

               // 上限値よりもfdcountが大きい
               else{
                  fprintf(stderr,"sitar_scan(****block): スレッドが作れませんでした (1). %ld\n", fdcount);
                  fdcountstat = 0;
                  fprintf(stderr,"sitar_scan(***block): 2秒待ってみます。 (2sec)(1). %ld\n", fdcount);
                  for(sleepcount = 0; sleepcount < 2; sleepcount++){
                     sleep(1);
                     }
                  }
               } // for()

            ren = 0;
            count = 0;
            } // if()

         /* ---- END Block ---- */
         if(ren >= gd.td.tbufmax || stat != 0){

            for(fdcountstat = 0;fdcountstat == 0;){

               safe_pthread_mutex_lock(&fdstat_mutex);
               for(fdcount = 0; fdcount < gd.td.tcount; fdcount++){
                  #ifdef SCAN_BUG
                  printf("SCAN_BUG: sitar_scan(END block 1): fdcount<%ld>fdstat<%d>\n",
                  fdcount, gd.td.fdstat[fdcount]);
                  #endif
                  if(gd.td.fdstat[fdcount] != 1){
                     gd.td.fdstat[fdcount] = 1;
                     #ifdef FREE_BUG
                     printf("FREE: sitar_scan(END block 2): safree(%ld) fdcount\n", fdcount);
                     #endif
                     sanull(fdcount);
                     break;
                     }
                  }
               pthread_mutex_unlock(&fdstat_mutex);

               // 上限値よりもfdcountが小さい 
               if(fdcount < gd.td.tcount){
                  for(count = 0; count < ren; count++){

                     sa.swap_data[fdcount][count] = safe_memcpy(
                         sa.swap_data[fdcount][count], sa.tmp_data[count], BUF_MAX); 

                     #ifdef SCAN_BUG
                     printf("SCAN_BUG: sitar_scan(END block 3): Thread No = %ld\n", fdcount);
                     #endif
                     }

                  ren = 0;
                  count = 0;

                  if(sa.main_buf_err == 1){
                     sa.buf_err[fdcount] = 1;
                     sa.main_buf_err = 0;
                     }
                  else{
                     sa.buf_err[fdcount] = 0;
                     }
                  // pthread_create

                  // 次のfor loopで抜ける設定
                  fdcountstat = 1;
                  #ifdef SCAN_BUG
                  printf("SCAN_BUG: sitar_scan(END block): あたらしいスレッド Thread No = %ld\n", fdcount);
                  #endif

                  // スレッドの上限を確認して、多い場合はまち
                  while(1){
                     safe_pthread_mutex_lock(&thread_mutex);
                     thread_co = gd.td.thread_count;
                     pthread_mutex_unlock(&thread_mutex);
                     if(thread_co < gd.td.thread_max){
                        #ifdef IN_THREAD
                        printf("IN_THREAD: sitar_scan(2): %d スレッド作成\n", gd.td.thread_count);
                        #endif
                        break;
                        }
                     #ifdef IN_THREAD
                     printf("IN_THREAD: sitar_scan(2): %d スレッド作成待ち\n", gd.td.thread_count);
                     #endif
                     usleep(SLEEP_TIME);
                     }

                  if((tret = pthread_create(&sa.pt[fdcount], NULL, (void *)scan_block, (int *)fdcount)) != 0 ){
                     fprintf(stderr,"sitar_scan.c pthread_create(0): %d %d\n",tret, errno);
                     }
                  }
               else {
                  fprintf(stderr,"sitar_scan(END block): スレッドが作れませんでした (2). %ld\n", fdcount);
                  fdcountstat = 0;
                  fprintf(stderr,"sitar_scan(END block): 2秒待ってみます。 (2sec)(2). %ld\n", fdcount);
                  for(sleepcount = 0; sleepcount < 2; sleepcount++){
                     sleep(1);
                     }
                  }
               }

            ren = 0;
            count = 0;
            #ifdef FILE_DEBUG
            printf("FILE: sitar_scan(): ファイルの終端、または読み込めませんでした\n");
            #endif
            break;
            } // if()




         } // while()


      stat = 0;
      #ifdef SCAN_BUG
      printf("SCAN_BUG: sitar_scan(): 二次ファイルを閉じました。 fdcount<%ld>\n",
         fdcount);
      #endif
      fclose( fp );
      } // fopen()


   #ifdef SCAN_BUG
   printf("SCAN_BUG: sitar_scan(): 次のバッファを初期化します。 satmpnull()\n");
   #endif 
   satmpnull();




   // スレッド生成時間計測終了 
   fileget_stop = time(NULL);
   #ifdef BAT_DEBUG
   printf("BAT_DEBUG: sitar_scan(): スレッド生成の時間計測終了 (%d):\n", fileget_stop);
   #endif
   fileget_time = fileget_stop - fileget_start;
   #ifdef BAT_DEBUG
   printf("BAT_DEBUG: sitar_scan(): スレッド生成にかかった時間 <%d>:\n", fileget_time);
   #endif
   filestop_time = (int)((gd.bf.bat2_int / 3) * 2) - fileget_time;

   if(filestop_time >= 0){
      // 最初のすりーぷじっこう
      #ifdef BAT_DEBUG
      printf("BAT_DEBUG: sitar_scan(): 最初のお休みを頂きます (%d):\n", filestop_time);
      #endif
      sleep(filestop_time);
      }
   else{
      fprintf(stderr,"sitar_scan():  BAT2_INT value is a little. (%d):\n", gd.bf.bat2_int);
      }

   fileget_time = 0;
   fileget_start = 0;
   fileget_stop = 0;
   filestop_time = 0;

   #ifdef BAT_DEBUG
   printf("SCAN_BUG: sitar_scan():  最初のお休みが終わりました\n");
   #endif








   // ファイル処理の時間計測開始
   fileget_start = time(NULL);
   #ifdef BAT_DEBUG
   printf("BAT_DEBUG: sitar_scan(): リストファイル読み込み時間計測開始 (%d):\n", fileget_start);
   #endif

   // リストに変更があった場合の処理
   if(gd.fi.list_stat == 1){
      #ifdef BAT_DEBUG
      printf("BAT_DEBUG: sitar_scan(): リストファイルに変更がありました\n");
      #endif

      get_alget(gd.fi.bat2_filename, "PORT");

      safe_pthread_mutex_lock(&file1_mutex);
      gd.fi.list_stat = 0;
      pthread_mutex_unlock(&file1_mutex);

      #ifdef BAT_DEBUG
      printf("BAT_DEBUG: sitar_scan(): リストファイルの読み込みが終わりました\n");
      #endif
      }

   // 一次リストファイルから二次リストファイルにコピー

   gd.fi.bat2_filestat = stat_check(gd.fi.bat2_filestat, gd.fi.bat2_filename, &bstat);
   if(0 > bstat){
      #ifdef SCAN_BUG
      printf("SCAN_BUG: sitar_scan(): 編集があったので一次ファイルから二次ファイルにコピーします %s , %s , %d \n",
        gd.fi.bat2_filestat, gd.fi.bat2_filename, &bstat);
      #endif
      file_copy(gd.fi.bat2_filename, gd.fi.bat2_filename_2);
      }


   // ファイル処理時間計測終了
   fileget_stop = time(NULL);
   #ifdef BAT_DEBUG
   printf("BAT_DEBUG: sitar_scan(): リストファイル読み込み時間計測終了 (%d):\n", fileget_stop);
   #endif
   fileget_time = fileget_stop - fileget_start;
   #ifdef BAT_DEBUG
   printf("BAT_DEBUG: sitar_scan(): リストファイルの読み込みにかかった時間です <%d>:\n", fileget_time);
   #endif
   filestop_time = (gd.bf.bat2_int / 3) - fileget_time;

   if(filestop_time >= 0){
      // 二回目すりーぷじっこう
      #ifdef BAT_DEBUG
      printf("BAT_DEBUG: sitar_scan(): 二回目のお休みを頂きます (%d):\n", filestop_time);
      #endif
      sleep(filestop_time);
      }
   else{
      fprintf(stderr,"sitar_scan():  BAT2_INT value is a little. (%d):\n", gd.bf.bat2_int);
      }

   fileget_time = 0;
   fileget_start = 0;
   fileget_stop = 0;
   filestop_time = 0;

   #ifdef SCAN_BUG
   printf("SCAN_BUG: sitar_scan():   2回めのお休みを頂きました \n");
   #endif



   // 大掃除
   safe_pthread_mutex_lock(&fdstat_mutex);

   for(fdclean = 0; fdclean < gd.td.tcount; fdclean++){
      if(gd.td.fdstat[fdclean] != 1){
         #ifdef MALLOC_BUG
         printf("MALLOC: sitar_scan(): No used buffer cleanup. fdclean<%d>fdstat<%d>\n",
           fdclean, gd.td.fdstat[fdclean]);
         #endif
         #ifdef FREE_BUG
         printf("FREE: sitar_scan(): safree(%d) fdclean\n", fdclean);
         #endif
         sanull(fdclean);
         }
      }

   #ifdef SCAN_BUG
   printf("SCAN_BUG: sitar_scan(): ループから抜けます。 fdcount<%ld>fdstat<%d>utime<%ld>\n",
      fdcount, gd.td.fdstat[fdcount], (long int)time(NULL));
   #endif

   pthread_mutex_unlock(&fdstat_mutex);


   } // for(;;)

// Not reachablle (ここに到達することはありません)

return 0;
}









