

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.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;
#ifdef KEEP_MALLOC
extern private_data_t * gpd;
#endif
extern pthread_mutex_t fd_mutex;
extern pthread_mutex_t mail_mutex;
extern pthread_mutex_t name_mutex;
extern pthread_mutex_t fdstat_mutex;
extern pthread_mutex_t break_mutex;
extern pthread_mutex_t thread_mutex;


//  scan_block はポート、コマンドのスレッド分岐先の関数になります
void * scan_block(int count)
{
int co, stat, errcount, testcount, mucount, mutexid, middleid, interval, instat, dstat, thread_co;
char mid_stat, midret;

interval = (gd.bf.life_int + gd.bf.life_los + INT_PLUS);

instat = 0;
mucount = 0;
mutexid = -1;
middleid = -1;
mid_stat = 0;
errcount = 0;
testcount = 0;
stat = 0;
dstat = 0;
thread_co = 0;
midret = -3;

// Pthread detachd このスレッドをデタッチします。
// 元スレッドはこの関数の終わりを待ちません
pthread_detach(pthread_self());

private_data_t *pd;

// すでにスレッド用バッファーを用意している場合
#ifdef KEEP_MALLOC
pd = &gpd[count];
// スレッド分岐する度にバッファーを用意する場合
#else
if((pd = (private_data_t *)malloc(sizeof(private_data_t)))==NULL){exit(1);}
scan_malloc_set(pd);
#endif


#ifdef SCAN_BUG
printf("THREAD: scan_block(): 監視ブロックに入りました。 no<%d>\n", count);
#endif

pd->sb.fdno = count;

for(co = 0; co < gd.td.tbufmax; co++){

   if(sa.swap_data[pd->sb.fdno][co][0] != 0x00){

      if(mutexid <= 0){

         pd->sb.swap_2 = safe_memcpy(pd->sb.swap_2, sa.swap_data[pd->sb.fdno][co], BUF_MAX);

         if(13 == char_count(pd->sb.swap_2,',') && 13 <= strlen(pd->sb.swap_2) && '#' != pd->sb.swap_2[0]){ 

            pd->sb.ch_tool = delim_get(pd->sb.swap_2, pd->sb.ch_tool, ',', &dstat, 0);
            pd->sb.ch_stat = delim_get(pd->sb.swap_2, pd->sb.ch_stat, ',', &dstat, 1);
            pd->sb.ch_prot = delim_get(pd->sb.swap_2, pd->sb.ch_prot, ',', &dstat, 2);
            pd->sb.ch_com = delim_get(pd->sb.swap_2, pd->sb.ch_com, ',', &dstat, 3);
            pd->sb.ch_host = delim_get(pd->sb.swap_2, pd->sb.ch_host, ',', &dstat, 4);
            pd->sb.ch_port = delim_get(pd->sb.swap_2, pd->sb.ch_port, ',', &dstat, 5);
            pd->sb.ch_timeout = delim_get(pd->sb.swap_2, pd->sb.ch_timeout, ',', &dstat, 6);
            pd->sb.ch_data = delim_get(pd->sb.swap_2, pd->sb.ch_data, ',', &dstat, 7);
            pd->sb.ch_plai = delim_get(pd->sb.swap_2, pd->sb.ch_plai, ',', &dstat, 8);
            pd->sb.ch_free1 = delim_get(pd->sb.swap_2, pd->sb.ch_free1, ',', &dstat, 9);
            pd->sb.ch_free2 = delim_get(pd->sb.swap_2, pd->sb.ch_free2, ',', &dstat, 10);
            pd->sb.ch_free3 = delim_get(pd->sb.swap_2, pd->sb.ch_free3, ',', &dstat, 11);
            pd->sb.ch_free4 = delim_get(pd->sb.swap_2, pd->sb.ch_free4, ',', &dstat, 12);


            #ifdef SCAN_BUG
            printf("THREAD: scan_block(): <%s>, <%d>, %s\n",
               pd->sb.ch_free4, count, pd->sb.swap_2);
            #endif


            if(1 <= strlen(pd->sb.ch_stat) && 1 <= strlen(pd->sb.ch_prot) &&
               1 <= strlen(pd->sb.ch_host) && 1 <= strlen(pd->sb.ch_port) &&
               1 <= strlen(pd->sb.ch_timeout) && 1 <= strlen(pd->sb.ch_data) &&
               1 <= strlen(pd->sb.ch_tool) && 1 <= strlen(pd->sb.ch_com) &&
               1 <= strlen(pd->sb.ch_plai) && 1 <= strlen(pd->sb.ch_free1)){ 

               rm_crlf(pd->sb.ch_stat, strlen(pd->sb.ch_stat));
               rm_crlf(pd->sb.ch_prot, strlen(pd->sb.ch_prot));
               rm_crlf(pd->sb.ch_host, strlen(pd->sb.ch_host));
               rm_crlf(pd->sb.ch_port, strlen(pd->sb.ch_port));
               rm_crlf(pd->sb.ch_timeout, strlen(pd->sb.ch_timeout));
               rm_crlf(pd->sb.ch_data, strlen(pd->sb.ch_data));
               rm_crlf(pd->sb.ch_tool, strlen(pd->sb.ch_tool)); 
               rm_crlf(pd->sb.ch_com, strlen(pd->sb.ch_com)); 
               rm_crlf(pd->sb.ch_plai, strlen(pd->sb.ch_plai)); 
               rm_crlf(pd->sb.ch_free1, strlen(pd->sb.ch_free1));
               rm_crlf(pd->sb.ch_free2, strlen(pd->sb.ch_free2));
               rm_crlf(pd->sb.ch_free3, strlen(pd->sb.ch_free3));
               rm_crlf(pd->sb.ch_free4, strlen(pd->sb.ch_free4));


               // 一からむ目がSETでない場合はtimeoutを数字に変換
               if(0 == self_memcmp(pd->sb.ch_tool, "SET")){
                  #ifdef MONITOR_BUG
                  fprintf(stderr,"scan_block(): SET sb.ch_tool = %s\n", pd->sb.ch_tool);
                  #endif 
                  }
               else{
                  #ifdef MONITOR_BUG
                  fprintf(stderr,"scan_block(): sb.ch_tool = %s\n", pd->sb.ch_tool);
                  #endif 

                  pd->sb.port = strtol(pd->sb.ch_port, (char **)NULL, 10);
                  pd->sb.timeout = strtol(pd->sb.ch_timeout, (char **)NULL, 10);

                  if(pd->sb.timeout > TIME_OUT || pd->sb.timeout < 0){
                     if(pd->sb.timeout > TIME_OUT){
                        pd->sb.timeout = 4;
                        }
                     else{
                        pd->sb.timeout = 0;
                        }
                     }
                  }


               // SET は最初の行に限定される条件なので、最初に以下の監視条件を満たすことは無いです。
               pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, "\n", BUF_MAX);

               if(0 == self_memcmp(pd->sb.ch_tool, "PORT")){
                  #ifdef MONITOR_BUG
                  printf("MONITOR: %s: %s: %s: %s:\n",
                    pd->sb.ch_tool, pd->sb.ch_prot, pd->sb.ch_free1, pd->sb.ch_free4);
                  #endif 
                  scan_port(pd);
                  }
               else if(0 == self_memcmp(pd->sb.ch_tool, "COMAND")){
                  #ifdef MONITOR_BUG
                  printf("MONITOR: %s: %s: %s: %s:\n",
                    pd->sb.ch_tool, pd->sb.ch_com, pd->sb.ch_free1, pd->sb.ch_free4);
                  #endif 
                  scan_comand(pd);
                  }
               else if(0 == self_memcmp(pd->sb.ch_tool, "SNMP")){
                  #ifdef MONITOR_BUG
                  printf("MONITOR: %s: %s: %s: %s:\n",
                    pd->sb.ch_tool, pd->sb.ch_prot, pd->sb.ch_free1, pd->sb.ch_free4);
                  #endif 
                  scan_snmp(&pd->sb);
                  }
               else if(0 == self_memcmp(pd->sb.ch_tool, "SET")){
                  #ifdef MONITOR_BUG
                  printf("MONITOR: %s: %s: %s: %s:\n",
                    pd->sb.ch_tool, pd->sb.ch_prot, pd->sb.ch_free1, pd->sb.ch_free4);
                  #endif 
                  pd->sb.check_stat = 2;
                  }
               else{
                  #ifdef MONITOR_BUG
                  printf("scan_block(): 存在しない監視属性が設定されています %s: %s: %s: %s:\n",
                    pd->sb.ch_tool, pd->sb.ch_prot, pd->sb.ch_free1, pd->sb.ch_free4);
                  #endif 

                  pd->sb.ch_info = safe_sprintf(pd->sb.ch_info, BUF_MAX,"%s : %s : %s : %s : %s\n",
                    MONITOR_ERR_1, pd->sb.ch_tool, pd->sb.ch_prot, pd->sb.ch_free1, pd->sb.ch_free4);
                  pd->sb.check_stat = 1;
                  pd->sb.ch_plai = safe_memcpy(pd->sb.ch_plai, "6", BUF_MAX); 

                  }


               // SET 行の場合の処理になります
               if(pd->sb.check_stat == 2 ){

                  swap_mem(pd->sb.ch_prot, ';', ' ');
                  swap_mem(pd->sb.ch_free1, ';', ' ');
                  swap_mem(pd->sb.ch_free2, ';', ' ');
                  swap_mem(pd->sb.ch_free3, ';', ' ');
                  swap_mem(pd->sb.ch_free4, ';', ' ');


                  if(0 < (int)strlen(pd->sb.ch_free4)){ 

                     if(0 == self_memcmp(pd->sb.ch_free1, "MID")){
                        mid_stat = 1;
                        }
                     else if(0 == self_memcmp(pd->sb.ch_free1, "MIX")){
                        mid_stat = 2;
                        }
                     else{
                        mid_stat = 0;
                        }


                     // mail 属性がmiddleな場合に、ブロック名をDBに登録します
                     // middleでない場合はブロック名の登録がある場合は消します。
                     safe_pthread_mutex_lock(&mail_mutex);

                     if(mid_stat > 0){   // MID か MIX な場合
                        // ------- A -------
                        // zither サーバ側にMIDのアカウントが登録済みかを確認する
                        // 無かった場合は -1, 対応していないバージョンは -2を、通常は現状のカウント数 0<* を返す。
                        //  -1 無い場合は新規で作る(0)、新規の場合はチェック
                        //  -2 Zitherが対応していない場合は変数にチェック
                        #ifdef MID_BUG
                        printf("MID_BUG: scan_block(1): 鯖に確認にいってみる %s <%d>\n", pd->sb.ch_free1, mid_stat);
                        #endif
                        midret = mid_chserver(pd->sb.ch_free4, interval);




                        for(mucount = 0; mucount < gd.td.midcount; mucount++){
                           if(0 == self_memcmp(gd.td.middle_name[mucount], pd->sb.ch_free4)){
                              middleid = mucount;
                              /* MIDかMIXで名前が登録されているので、そのIDを返す */
                              #ifdef MID_BUG
                              printf("MID_BUG: scan_block(2): MID同じ名前のブロックが既に登録済みです <%s> mucount<%d><%s>count<%d><%d>\n",
                                gd.td.middle_name[mucount], mucount, pd->sb.ch_free4, gd.td.middle_id[mucount], pd->sb.fdno);
                              #endif

                              /* ------ A ------ */
                              /* 新規の場合に限り、ローカルDBにある数を、Zitherがわに登録する。*/
                              /* 通常このケースは無い */
                              if(midret == -1){
                                 #ifdef MID_BUG
                                 printf("MID_BUG: scan_block(2,1): 鯖に登録なく、鯖を同期します <%s> mucount<%d><%s>count<%d><%d>\n",
                                   gd.td.middle_name[mucount], mucount, pd->sb.ch_free4, gd.td.middle_id[mucount], pd->sb.fdno);
                                 #endif
                                 if( -1 == (mid_setserver(pd->sb.ch_free4, gd.td.middle_id[mucount], interval))){
                                    fprintf(stderr,"MID_BUG: scan_block(): mid_setserver(): サーバ側MID設定に失敗しています\n");
                                    }
                                 }

                              break;
                              }
                           } /* for() */


                        if(middleid == -1){   /* MIDやMIXだがIDが存在しなかった */
                           for(mucount = 0; mucount < gd.td.midcount; mucount++){
                              if(gd.td.middle_name[mucount][0] == (char)0x00){ 
                                 gd.td.middle_name[mucount] = safe_memcpy(gd.td.middle_name[mucount], pd->sb.ch_free4, BUF_MAX);
                                 gd.td.middle_id[mucount] = 0;
                                 /* 開いている場所を探して登録する */
                                 #ifdef MID_BUG
                                 printf("MID_BUG: scan_block(3): MIDブロック新規に登録しました <%s> mucount<%d><%s>count<%d><%d>\n",
                                    gd.td.middle_name[mucount], mucount, pd->sb.ch_free4, gd.td.middle_id[mucount], pd->sb.fdno);
                                 #endif

                                 middleid = mucount;

                                 break;
                                 }
                              } /* for() */
                           if(mucount > gd.td.midcount){   /* 開いている場所がないのでこれはエラー、普通ない、死ぬだろな？w */
                              fprintf(stderr,"scan_block(): MID上限%dを越えたためブロックが登録出来ません mucount<%d> <%s>\n",
                                 gd.td.midcount, mucount, pd->sb.ch_free4);
                              }
                           }

                        }


                     else{   // MID や MIX でない場合
                        for(mucount = 0; mucount < gd.td.midcount; mucount++){
                           if(0 == self_memcmp(gd.td.middle_name[mucount], pd->sb.ch_free4)){
                              // MIDやMIXでないのにIDが登録されているので消す
                              #ifdef MID_BUG
                              printf("MID_BUG: scan_block(): MID でないのに同じ名前のブロックが既に登録済なので消します <%s> mucount<%d> <%s> count<%d>\n",
                                gd.td.middle_name[mucount], mucount, pd->sb.ch_free4, gd.td.middle_id[mucount]);
                              #endif

                              gd.td.middle_name[mucount] = null_free(gd.td.middle_name[mucount]);
                              gd.td.middle_id[mucount] = 0;

                              // ------- B -------
                              // Zitheサーバ側にもMIDアカウントを削除依頼する。
                              #ifdef MID_BUG
                              printf("MID_BUG: scan_block(): 鯖側の設定を消します <%s> mucount<%d> <%s> count<%d>\n",
                                gd.td.middle_name[mucount], mucount, pd->sb.ch_free4, gd.td.middle_id[mucount]);
                              #endif
                              if( -1 == (mid_remserver(pd->sb.ch_free4, interval))){
                                 fprintf(stderr,"MID_BUG: scan_block(): mid_remserver(): サーバ側MIDのID削除に失敗しています\n");
                                 }


                              break;
                              }
                           } // for()
                        }
                     pthread_mutex_unlock(&mail_mutex);



                     // ------- A2 -------
                     // もしもMID,MIXで、
                     // Zitherが対応している場合で
                     // Zither側にアカウントがあった場合で。(0 < * )
                     // Zitherに問い合わせたカウントにローカルDBのカウントをあわせてしまう。
                     // Zitherにアカウントが無いか、未対応のバージョンの場合は何もしない。
                     if(midret > -1){
                        gd.td.middle_id[mucount] = midret;
                        #ifdef MID_BUG
                        printf("MID_BUG: can_block(): ローカル側のカウントを鯖側のカウントで上書きしました\n");
                        #endif
                        }



                     // スレッドの排他処理についての
                     // 同じ監視ブロックが動いている場合はfor()から抜けます、スレッド排他処理しています 

                     safe_pthread_mutex_lock(&name_mutex);
                     for(mucount = 0; mucount < gd.td.tcount; mucount++){
                        if(0 == self_memcmp(gd.td.mutex_name[mucount], pd->sb.ch_free4)){
                           #ifdef MUTEX_BUG
                           printf("MUTEX: scan_block(thread): 同じ名前の監視グループが起動中ですこの監視グループは無視します <%s> mucount<%d> <%s>\n",
                             gd.td.mutex_name[mucount], mucount, pd->sb.ch_free4);
                           #endif 
                           mutexid = 1;
                           break;
                           }
                        mutexid = 0;
                        } // for()

                     if(mutexid == 0){
                        for(mucount = 0; mucount < gd.td.tcount; mucount++){
                           if(gd.td.mutex_name[mucount][0] == (char)0x00){
                              gd.td.mutex_name[mucount] = safe_memcpy(gd.td.mutex_name[mucount],
                                                                      pd->sb.ch_free4, BUF_MAX);
                              #ifdef MUTEX_BUG
                              printf("MUTEX: scan_block(thread): 現在同じ監視グループは動いていないので排他処理に登録します <%s> mucount<%d>\n",
                                gd.td.mutex_name[mucount], mucount);
                              #endif
                              mutexid = 0;
                              break;
                              }
                           } // for()
                        if(mucount >= gd.td.tcount){
                           fprintf(stderr,"scan_block(thread): 普通到達はしない\n");
                           fprintf(stderr,"scan_block(thread): %s\n", MUTEX_1);
                           mutexid = 1;
                           }
                        }
                     pthread_mutex_unlock(&name_mutex);






                     // 同じ名前の環視ブロック（スレッド）が動いていないのでいっちゃいます
                     // 排他処理に登録された場合の時間指定の確認
                     if(mutexid == 0){

                        int ye_1, mo_1, da_1, ha_1, mi_1;
                        int ye_2, mo_2, da_2, ha_2, mi_2;
                        ye_1 = 0; mo_1 = 0; da_1 = 0; ha_1 = 0; mi_1 = 0;
                        ye_2 = 0; mo_2 = 0; da_2 = 0; ha_2 = 0; mi_2 = 0;

                        // 時間指定（JUST)
                        if(0 == self_memcmp(pd->sb.ch_prot, "JUST")){
                           if(time_format(pd->sb.ch_timeout, &ye_1, &mo_1, &da_1, &ha_1, &mi_1) < 0){
                              fprintf(stderr,"MUTEX: scan_block(): JUST時間単位で指定値の変換が正しく出来ませんでした <%s>\n",
                                pd->sb.ch_timeout);
                              ye_1 = 2008; mo_1 = 1; da_1 = 1; ha_1 = 0; mi_1 = 0;
                              goto forloopout;
                              }
                           else{
                              #ifdef MUTEX_BUG
                              printf("MUTEX: scan_block(): JUST時間単位で一回実行の設定がされました <%s>\n",
                                pd->sb.ch_prot);
                              #endif
                              // JUST 指定関数 hloop()
                              if(0 > hloop(ye_1, mo_1, da_1, ha_1, mi_1, gd.bf.bat2_int)){ 
                                 #ifdef MUTEX_BUG
                                 printf("MUTEX: scan_block(): JUSTで条件を満たしていないのでループを抜けます\n");
                                 #endif 
                                 goto forloopout;
                                 }
                              else{
                                 #ifdef MUTEX_BUG
                                 printf("MUTEX: scan_block(): JUSTで条件を満たしたので監視を開始します。\n");
                                 #endif 
                                 }
                              ye_1 = 0; mo_1 = 0; da_1 = 0; ha_1 = 0; mi_1 = 0;
                              }
                           }   // JUST



                        // 時間指定RES(以外)
                        else if(0 == self_memcmp(pd->sb.ch_prot, "RES")){
                           if(time_format(pd->sb.ch_port, &ye_1, &mo_1, &da_1, &ha_1, &mi_1) < 0){
                              fprintf(stderr,"MUTEX: scan_block(): RES STOP時間指定値の変換が正しく出来ませんでした <%s>\n",
                                pd->sb.ch_port);
                              ye_1 = 0; mo_1 = 0; da_1 = 0; ha_1 = 0; mi_1 = 0;
                              goto forloopout;
                              }
                           else{
                              if(time_format(pd->sb.ch_timeout, &ye_2, &mo_2, &da_2, &ha_2, &mi_2) < 0){
                                 fprintf(stderr,"MUTEX: scan_block(): RES START時間指定値の変換が正しく出来ませんでした <%s>\n",
                                   pd->sb.ch_timeout);
                                 ye_2 = 0; mo_2 = 0; da_2 = 0; ha_2 = 0; mi_2 = 0;
                                 goto forloopout;
                                 }
                              else{
                                 #ifdef MUTEX_BUG
                                 printf("MUTEX: scan_block(): RES 時間指定実行停止の設定がされました<%s>\n",
                                   pd->sb.ch_prot);
                                 #endif 
                                 // RES 指定関数 floop()
                                 if(0 <= floop(ye_1, mo_1, da_1, ha_1, mi_1,
                                               ye_2, mo_2, da_2, ha_2, mi_2)){
                                    #ifdef MUTEX_BUG
                                    printf("MUTEX: scan_block(): RESで条件を満たしたので監視を行いません <%d>から<%d>\n",
                                      ha_1, mi_1);
                                    #endif
                                    goto forloopout;
                                    }
                                 else{
                                    #ifdef MUTEX_BUG
                                    printf("MUTEX: scan_block(): RESで条件を満たしていないので監視を再開します。\n");
                                    #endif 
                                    }
                                 ye_1 = 0; mo_1 = 0; da_1 = 0; ha_1 = 0; mi_1 = 0;
                                 ye_2 = 0; mo_2 = 0; da_2 = 0; ha_2 = 0; mi_2 = 0;
                                 }
                              }
                           }   // RES


                        // 時間指定FOR(条件を満たしている間) スーパーネスト！w そのうちきれいになおしまふ
                        else if(0 == self_memcmp(pd->sb.ch_prot, "FOR")){
                           if(time_format(pd->sb.ch_port, &ye_1, &mo_1, &da_1, &ha_1, &mi_1) < 0){
                              fprintf(stderr,"MUTEX: scan_block(): FOR START時間指定値の変換が正しく出来ませんでした <%s>\n",
                                pd->sb.ch_port);
                              ye_1 = 0; mo_1 = 0; da_1 = 0; ha_1 = 0; mi_1 = 0;
                              goto forloopout;
                              }
                           else{
                              if(time_format(pd->sb.ch_timeout, &ye_2, &mo_2, &da_2, &ha_2, &mi_2) < 0){
                                 fprintf(stderr,"MUTEX: scan_block(): FOR STOP時間指定値の変換が正しく出来ませんでした <%s>\n",
                                   pd->sb.ch_timeout);
                                 ye_2 = 0; mo_2 = 0; da_2 = 0; ha_2 = 0; mi_2 = 0;
                                 goto forloopout;
                                 }
                              else{
                                 #ifdef MUTEX_BUG
                                 printf("MUTEX: scan_block(): FOR時間単位で指定時間内実行の設定がされました<%s>\n",
                                   pd->sb.ch_prot);
                                 #endif 
                                 // FOR 指定関数 floop()
                                 if(0 > floop(ye_1, mo_1, da_1, ha_1, mi_1,
                                              ye_2, mo_2, da_2, ha_2, mi_2)){
                                    #ifdef MUTEX_BUG
                                    printf("MUTEX: scan_block(): FORで条件を満たしていないのでループを抜けます <%d>から<%d>\n",
                                      ha_1, mi_1);
                                    #endif
                                    goto forloopout;
                                    }
                                 else{
                                    #ifdef MUTEX_BUG
                                    printf("MUTEX: scan_block(): FORで条件を満たしたので監視を開始します。\n");
                                    #endif 
                                    }
                                 ye_1 = 0; mo_1 = 0; da_1 = 0; ha_1 = 0; mi_1 = 0;
                                 ye_2 = 0; mo_2 = 0; da_2 = 0; ha_2 = 0; mi_2 = 0;
                                 }
                              }
                           }   // FOR



                        // 時間指定 (FOR RES JUST) 以外の場合
                        // 時間指定でないブロック（速攻で動く可能性がある)
                        // 同時起動上限をカウントする。
                        else{
                           #ifdef MUTEX_BUG
                           printf("MUTEX: scan_block(): 時間単位の設定は入っていません\n");
                           #endif 
                           }
                        //  wait 秒待ちます
                        // 遅延設定はここで時間まちする
                        if(0 < (int)strlen(pd->sb.ch_plai)){ 
                           #ifdef MUTEX_BUG
                           printf("MUTEX: scan_block(): 以下の秒だけ待ちます <%s> mucount<%d>\n",
                             pd->sb.ch_plai, mucount);
                           #endif 
                           sleep(strtol(pd->sb.ch_plai, (char **)NULL, 10)); 
                           }
                        }  // mutexid = 0

                     }  // if(free4 " /n")







                  // Zither に送るERRログの先頭に入るSETの内容を作成
                  // mail送信属性を判断し、MIDの場合は ONかOFFに判断する。
                  if(mutexid == 0){

                     safe_pthread_mutex_lock(&mail_mutex);
                     if(mid_stat > 0 && middleid > -1){

                        if(mid_stat == 1){
                           pd->sb.ch_info = safe_sprintf(pd->sb.ch_info, BUF_MAX,"MID%d", gd.td.middle_id[middleid]);
                           }
                        else if(mid_stat == 2){
                           pd->sb.ch_info = safe_sprintf(pd->sb.ch_info, BUF_MAX,"MIX%d", gd.td.middle_id[middleid]);
                           }
                        else{
                           pd->sb.ch_info = safe_sprintf(pd->sb.ch_info, BUF_MAX,"MID%d", gd.td.middle_id[middleid]);
                           }

                        if(gd.td.middle_id[middleid] >= 3){
                           #ifdef MID_BUG
                           printf("MID_BUG: scan_block(): メール属性をOFFに設定しました <%s> middleid<%d> id<%d>\n",
                                       gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid]);
                           #endif
                           pd->sb.ch_free1 = safe_memcpy(pd->sb.ch_free1, "OFF", BUF_MAX);
                           }
                        else{
                           #ifdef MID_BUG
                           printf("MID_BUG: scan_block(): メール属性をONに設定しました <%s> middleid<%d> id<%d>\n",
                                       gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid]);
                           #endif
                           pd->sb.ch_free1 = safe_memcpy(pd->sb.ch_free1, "ON", BUF_MAX);
                           }
                        }
                     pthread_mutex_unlock(&mail_mutex);

                    // 同時環視数 の排他処理（加算）
                    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){
                          gd.td.thread_count++;
                          #ifdef IN_THREAD
                          printf("IN_THREAD: scan_block(): %s %d 加算\n", pd->sb.ch_free4, gd.td.thread_count);
                          #endif
                          break;
                          }
                       #ifdef IN_THREAD
                       printf("IN_THREAD: scan_block(): %s %d 加算待ち\n", pd->sb.ch_free4, gd.td.thread_count);
                       #endif
                       usleep(SLEEP_TIME);
                       }

                     // SET 行の作成
                     pd->sb.swap_2 = safe_sprintf(pd->sb.swap_2, BUF_MAX,
                        "%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s;",
                        pd->sb.ch_tool,
                        (long int)time(NULL),
                        ctime_getr('y'),
                        ctime_getr('m'),
                        ctime_getr('d'),
                        ctime_getr('h'),
                        ctime_getr('i'),
                        ctime_getr('s'),
                        "NOT",
                        "NOT",
                        pd->sb.ch_plai,
                        pd->sb.ch_prot,
                        pd->sb.ch_port,
                        pd->sb.ch_timeout,
                        "NOT",
                        pd->sb.ch_info,
                        pd->sb.ch_data, 
                        pd->sb.ch_free1,
                        pd->sb.ch_free2,
                        pd->sb.ch_free3,
                        pd->sb.ch_free4);

                     pd->sb.scan_all = safe_strncat(pd->sb.scan_all, pd->sb.swap_2, BUF_MAX);
                     }
                  }  

               // ERR が観測された場合の処理。
               if(pd->sb.check_stat == 1){

                  errcount++;
                  swap_mem(pd->sb.ch_stat, ';', ' ');
                  swap_mem(pd->sb.ch_prot, ';', ' ');
                  swap_mem(pd->sb.ch_prot, ';', ' ');
                  swap_mem(pd->sb.ch_com, ';', ' ');
                  swap_mem(pd->sb.ch_host, ';', ' ');
                  swap_mem(pd->sb.ch_timeout, ';', ' ');
                  swap_mem(pd->sb.ch_data, ';', ' ');
                  swap_mem(pd->sb.ch_info, ';', ' ');
                  swap_mem(pd->sb.ch_plai, ';', ' ');
                  swap_mem(pd->sb.ch_free1, ';', ' ');
                  swap_mem(pd->sb.ch_free2, ';', ' ');
                  swap_mem(pd->sb.ch_free3, ';', ' ');
                  swap_mem(pd->sb.ch_free4, ';', ' ');

                  pd->sb.swap_2 = safe_sprintf(pd->sb.swap_2, BUF_MAX,
                     "%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%s,%s,%s,%s,%d,%d,%s,%s,%s,%s,%s,%s,%s;",
                     pd->sb.ch_tool,
                     (long int)time(NULL),
                     ctime_getr('y'),
                     ctime_getr('m'),
                     ctime_getr('d'),
                     ctime_getr('h'),
                     ctime_getr('i'),
                     ctime_getr('s'),
                     pd->sb.ch_stat,
                     pd->sb.ch_prot,
                     pd->sb.ch_com,
                     pd->sb.ch_host,
                     pd->sb.port,
                     pd->sb.timeout,
                     pd->sb.ch_data,
                     pd->sb.ch_info,
                     pd->sb.ch_plai,
                     pd->sb.ch_free1,
                     CL_VAR,
                     pd->sb.ch_free3,
                     pd->sb.ch_free4);


                  if(0 == self_memcmp(pd->sb.ch_plai, "4")){
                     testcount++;
                     }
                  else{ };

                  #ifdef MID_BUG
                  printf("MID_BUG: scan_block(): <%d> <%d> %s\n", errcount, testcount, pd->sb.ch_plai); 
                  #endif

                  pd->sb.scan_all = safe_strncat(pd->sb.scan_all, pd->sb.swap_2, BUF_MAX);

                  #ifdef MID_BUG
                  printf("MID_BUG: %s\n", pd->sb.scan_all);
                  #endif

                  }
               } 
            }

         } // if(mutexid == 0)

      }  // if

   } // for()


// FOR JUST の条件外になるとここに飛ぶ
forloopout :;




if(mutexid == 0){
   safe_pthread_mutex_lock(&name_mutex);
   #ifdef MUTEX_BUG
   printf("MUTEX: scan_block(2): 登録ブロック名を消しました <%s> mucount<%d>\n",
     gd.td.mutex_name[mucount], mucount);
   #endif
   gd.td.mutex_name[mucount] = null_free(gd.td.mutex_name[mucount]); 
   pthread_mutex_unlock(&name_mutex);
   }


// クライアントのバッファーを上囘った監視が設定された場合の処理
if(sa.buf_err[pd->sb.fdno] == 1){
   errcount++;
   sa.buf_err[pd->sb.fdno] = 0;
   pd->sb.swap_2 = safe_sprintf(pd->sb.swap_2, BUF_MAX,
        "%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%s,%s,%s,%s,%d,%d,%s,%s,%s,%s,%s,%s,%s;",
        "INFO",
        (long int)time(NULL),
        ctime_getr('y'),
        ctime_getr('m'),
        ctime_getr('d'),
        ctime_getr('h'),
        ctime_getr('i'),
        ctime_getr('s'),
        pd->sb.ch_stat,
        "NOT",
        ERR_MAIL_1,
        gd.bf.c_name,
        0,
        0,
        gd.bf.c_info,
        ERR_MAIL_2,
        "2",
        ERR_MAIL_3,
        CL_VAR,
        pd->sb.ch_free3,
        pd->sb.ch_free4);

   #ifdef DATA_BUG
   printf("DATA: scan_block(): バッファーの上限を越えています  %s\n", pd->sb.swap_2);
   #endif

   pd->sb.scan_all = safe_strncat(pd->sb.scan_all, pd->sb.swap_2, BUF_MAX);
   }



if(mutexid == 0){

   // ERR が観測された場合のプロトコルセット
   safe_pthread_mutex_lock(&break_mutex);
   if(gd.bf.break_count == 0 && (errcount - testcount) > 0){                 // <----- gd???

      if(1 < strlen(pd->sb.scan_all) && (char)0x0a != pd->sb.scan_all[0]){

         if(mid_stat > 0 && middleid > -1){    // MID か MIX　な場合
            safe_pthread_mutex_lock(&mail_mutex);

            if(gd.td.middle_id[middleid] <= 3){
               gd.td.middle_id[middleid]++;
               }
            if(gd.td.middle_id[middleid] == 3){
               gd.td.middle_id[middleid] = 6;
               }
            #ifdef MID_BUG
            printf("MID_BUG: scan_block(): エラーを観測しています <%s> middleid<%d> id<%d> co<%d>fd<%d>\n",
                gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid], co, pd->sb.fdno);
            #endif

            pthread_mutex_unlock(&mail_mutex);
 
           // ------ C -------
            // Zitherが対応している場合で
            // Zither サーバ側に現在のカウントを反映する。
            if(midret > -2){
               #ifdef MID_BUG
               printf("MID_BUG: scan_block(): 鯖側に現在のカウントを登録 <%s> middleid<%d> id<%d> co<%d>fd<%d>\n",
                   gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid], co, pd->sb.fdno);
               #endif
               if( -1 == (mid_setserver(pd->sb.ch_free4, gd.td.middle_id[middleid], interval))){
                  fprintf(stderr,"MID_BUG: scan_block(): mid_setserver(2): サーバ側MID設定に失敗しています\n");
                  }
               } 

            }

         swap_mem(pd->sb.scan_all, '\n', (char)0x01);

         pd->sb.ch_info = safe_sprintf(pd->sb.ch_info ,BUF_MAX,
           "%s :: COM: ERR DATA: %s\n", gd.bf.c_name, pd->sb.scan_all);

         safe_pthread_mutex_lock(&fd_mutex);
         if((stat = socket_send(gd.ip.sk, pd->sb.ch_info, interval)) > 0){
            pd->sb.swap = select_fdcat(gd.ip.sk, pd->sb.swap, &stat, BUF_MAX, interval);
            if(stat <= 0){
               fprintf(stderr,"scan_block(1): exit!! stat=<%d> not recv data\n", stat);
               safe_exit("scan_block(1):  socket err exit send data\n");
               }
            }
         else{
            fprintf(stderr,"scan_block(1): exit!! stat=<%d> send data = <%s>\n", stat, pd->sb.ch_info);
            safe_exit("scan_block(1):  socket err exit send data\n");
            }
         pthread_mutex_unlock(&fd_mutex);

//       pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, "\0", BUF_MAX);
//       pd->sb.swap = safe_memcpy(pd->sb.swap, "\0", BUF_MAX);
         pd->sb.ch_info = null_free(pd->sb.ch_info);
         pd->sb.swap = null_free(pd->sb.swap);

         }
      }


   // ERR が観測されない場合のプロトコルセット
   else{
      if(1 < strlen(pd->sb.scan_all) && (char)0x0a != pd->sb.scan_all[0]){


         safe_pthread_mutex_lock(&mail_mutex);
         if(mid_stat == 1 && middleid > -1){    // MID なばあい
            if(gd.td.middle_id[middleid] > 1){
               gd.td.middle_id[middleid]--;
               }
            if(gd.td.middle_id[middleid] == 3){
               // MIDが正常監視に戻ったのでとりあえず名前を消す。
               gd.td.middle_id[middleid] = 0;
               }

            #ifdef MID_BUG
            printf("MID_BUG: scan_block(): stat 1 エラーを観測しませんでした <%s> middleid<%d> id<%d> co<%d>fd<%d>\n",
               gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid], co, pd->sb.fdno);
            #endif

            // ------ C -------
            // Zitherが対応している場合で
            // Zither サーバ側に現在のカウントを反映する。
            if(midret > -2){
               #ifdef MID_BUG
               printf("MID_BUG: scan_block(): 鯖側に現在のカウントを登録 <%s> middleid<%d> id<%d> co<%d>fd<%d>\n",
                  gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid], co, pd->sb.fdno);
               #endif
               if( -1 == (mid_setserver(pd->sb.ch_free4, gd.td.middle_id[middleid], interval))){
                  fprintf(stderr,"MID_BUG: scan_block(): mid_setserver(3): サーバ側MID設定に失敗しています\n");
                  }
               }

            }
         else if(mid_stat == 2 && middleid > -1){   // MIX な場合
            #ifdef MID_BUG
            printf("MID_BUG: scan_block(): stat 2 エラーを観測しませんでした <%s> middleid<%d> id<%d> co<%d>fd<%d>\n",
               gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid], co, pd->sb.fdno);
            #endif
            // MIXが正常監視に戻ったのでとりあえず名前を消す。
            gd.td.middle_id[middleid] = 0;

            // ------ C -------
            // Zitherが対応している場合で
            // Zither サーバ側に現在のカウントを反映する。
            if(midret > -2){
               #ifdef MID_BUG
               printf("MID_BUG: scan_block(): 鯖側に現在のカウントを登録 <%s> middleid<%d> id<%d> co<%d>fd<%d>\n",
                  gd.td.middle_name[middleid], middleid, gd.td.middle_id[middleid], co, pd->sb.fdno);
               #endif
               if( -1 == (mid_setserver(pd->sb.ch_free4, gd.td.middle_id[middleid], interval))){
                  fprintf(stderr,"MID_BUG: scan_block(): mid_setserver(4): サーバ側MID設定に失敗しています\n");
                  }
               }

            }
         else{                                      // MID,MIDでは無い場合
            }
         pthread_mutex_unlock(&mail_mutex);


         if(testcount > 0){    // ブロック内での観測エラーがすべてTESTモードの場合

            swap_mem(pd->sb.scan_all, '\n', (char)0x01);

            pd->sb.ch_info = safe_sprintf(pd->sb.ch_info ,BUF_MAX,
              "%s :: COM: ERR DATA: %s\n", gd.bf.c_name, pd->sb.scan_all);


            safe_pthread_mutex_lock(&fd_mutex);
            if((stat = socket_send(gd.ip.sk, pd->sb.ch_info, interval)) > 0){
               pd->sb.swap = select_fdcat(gd.ip.sk, pd->sb.swap, &stat, BUF_MAX, interval);
               if(stat <= 0){
                  fprintf(stderr,"scan_block(2): exit!! stat=<%d> not recv data\n", stat);
                  safe_exit("scan_block(2):  socket err exit send data\n");
                  }
               }
            else{
               fprintf(stderr,"scan_block(2): exit!! stat=<%d> send data = <%s>\n", stat, pd->sb.ch_info);
               safe_exit("scan_block(2):  socket err exit send data\n");
               }
            pthread_mutex_unlock(&fd_mutex);



//          pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, "\0", BUF_MAX);
//          pd->sb.swap = safe_memcpy(pd->sb.swap, "\0", BUF_MAX);
            pd->sb.ch_info = null_free(pd->sb.ch_info);
            pd->sb.swap = null_free(pd->sb.swap);

            }

         }
      }

   pthread_mutex_unlock(&break_mutex);


   }




#ifdef MUTEX_BUG
printf("MUTEX: scan_block(): 監視ブロックから抜けます  <%s> mucount<%d>\n",
  gd.td.mutex_name[mucount], mucount); 
#endif 

#ifdef MALLOC_BUG
printf("MALLOC: scan_block(1): scan_malloc_free(pd): free(pd)\n");
#endif

#ifdef FREE_BUG
printf("FREE: single scan_block(): scan_malloc_free(): pd\n");
#endif

#ifdef MALLOC_BUG
printf("MALLOC: scan_block(2): scan_malloc_free(pd): free(pd)\n");
#endif

safe_pthread_mutex_lock(&fdstat_mutex);
#ifdef SCAN_BUG
printf("THREAD: scan_block(): 監視ブロックから抜けます。 no<%d> data<%d>\n",
  pd->sb.fdno, gd.td.fdstat[pd->sb.fdno]);   
#endif

gd.td.fdstat[pd->sb.fdno] = 0;
pthread_mutex_unlock(&fdstat_mutex);


// 同時環視数の排他処理（減算）
safe_pthread_mutex_lock(&thread_mutex);
if(gd.td.thread_count > 0){
   gd.td.thread_count--;
   #ifdef IN_THREAD
   printf("IN_THREAD: scan_block(): %s %d 減算\n", pd->sb.ch_free4, gd.td.thread_count);
   #endif
   }
pthread_mutex_unlock(&thread_mutex);


#ifdef KEEP_MALLOC
scan_malloc_null(pd);
#else
scan_malloc_free(pd);
free(pd);
#endif

return 0;
}





