/*
 *========================================================================
 *
 *   시스템명 : AZN_PLAZA_LANE APP
 *   파 일 명 : init_mngt.c
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>
#include <pthread.h>
#include "app_info.h"
#include "path_def.h"
#include "init_info.h"
#include "iis_func.h"

int shmid;
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;

typedef struct nThread
{
    int tid;
    int itval;
}THREAD;

/*
 *========================================================================
 *
 *   함 수 명 : sigAlarm()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

static void sigAlarm(int sig)
{
    proc_log("timeout[%d]", sig);
}

/*
 *========================================================================
 *
 *   함 수 명 : SIG_term()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

void SIG_term(int sig)
{
    int    i;
    signal(SIGCLD,SIG_IGN);
    signal(SIGTERM,SIG_IGN);
    proc_log("--- INIT RECV SIGTERM[%d]", sig);

    for(i=0;i<MAX_TASKS;i++)
    {

        if( system_info->task_info[i].task_id )
        {
             proc_log("Send Signal SIGTERM -> %d(%d)",
                system_info->task_info[i].task_id,
                system_info->task_info[i].proc_id);
             kill(system_info->task_info[i].proc_id,SIGTERM);
         system_info->task_info[i].act = TASK_STOP;
        }
    }
    signal(SIGALRM, sigAlarm);
    alarm(3);
    wait(0);

    remove_msg_que();
    shmctl(shmid,IPC_RMID,0);

    proc_log("--- INIT SHUTDOWN");
    exit(0);
}

/*
 *========================================================================
 *
 *   함 수 명 : read_task_tab()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

void read_task_tab()
{
    FILE *fp;
    int i;
    char sbuf[128];
    fp = fopen(INI_DIR"PROCESS.CFG","r");
    if(fp == NULL)
    {
        proc_log("PROCESS.CFG not found");
        exit(0);
    }
    for(i=1;i<MAX_TASKS;i++)
    {
        system_info->task_info[i].task_id = 0;
        if(!fgets(sbuf,80,fp)) break;

        sscanf(sbuf,"%s %s %s %s",system_info->task_info[i].argv[0],
            system_info->task_info[i].argv[1],
            system_info->task_info[i].argv[2],
            system_info->task_info[i].argv[3]);
            system_info->task_info[i].task_id = i;
    }
    fclose(fp);
}

/*
 *========================================================================
 *
 *   함 수 명 : start_task()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

void start_task()
{
    int i = 0;

    if(make_msg_que() == -1) SIG_term(i);

    for( i = 1; i < MAX_TASKS; i++ )
    {
        proc_log("%d :: %s %s %s %s:: tid %d",
            i,
            system_info->task_info[i].argv[0],
            system_info->task_info[i].argv[1],
            system_info->task_info[i].argv[2],
            system_info->task_info[i].argv[3],
            system_info->task_info[i].task_id);

        if( system_info->task_info[i].task_id )
            system_info->task_info[i].proc_id = system_info->task_info[i].opid = spawn( i, 0 );
    }
}

/*
 *========================================================================
 *
 *   함 수 명 : get_tid()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

int get_tid(int pid)
{
    int        i;

    for( i = 1; i < MAX_TASKS; i++ )
    {
        if( system_info->task_info[i].opid == pid )
            return(i);
    }
    return(-1);
}

/*
 *========================================================================
 *
 *   함 수 명 : proc_thread()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

void *proc_thread(void *data)
{
    int  tid;
    int  itval;
    char sbuf[128];
    char tbuf[128];
    THREAD* pp = (THREAD*)data;
    
    pthread_mutex_lock(&mutex_lock);
    proc_log("THREAD Start\n");
    tid = pp->tid;
    itval = pp->itval;
    
    free(pp);
    
    sleep(itval);
    sprintf(sbuf,"%s%s",BIN_DIR,system_info->task_info[tid].argv[0]);
    sprintf(tbuf,"app_%s",
            system_info->task_info[tid].argv[0]);

    proc_log("%d process(%s) %d start",tid, sbuf, getpid());
    system_info->task_info[tid].act = TASK_RUN;

    if(strlen(system_info->task_info[tid].argv[3])){
        execl( sbuf, tbuf,
            system_info->task_info[tid].argv[1],
            system_info->task_info[tid].argv[2],
            system_info->task_info[tid].argv[3],
            (char *)0 );
    }else if(strlen(system_info->task_info[tid].argv[2])){
        execl( sbuf, tbuf,
            system_info->task_info[tid].argv[1],
            system_info->task_info[tid].argv[2],
            (char *)0 );
    }else if(strlen(system_info->task_info[tid].argv[1])){
        execl( sbuf, tbuf, system_info->task_info[tid].argv[1],(char *)0 );
    }else{
        execl( sbuf, tbuf, (char *)0 );
    }

    pthread_mutex_unlock(&mutex_lock);
    
    return NULL;
}

/*
 *========================================================================
 *
 *   함 수 명 : spawn()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

int spawn(tid, itval)
int tid, itval;
{
    int  pid;

    THREAD *p = (THREAD *) malloc(sizeof(THREAD));
    memset(p, '\0', sizeof(THREAD));
    pthread_t p_thread;
    
    p->itval = itval;
    p->tid = tid;

    pthread_mutex_init(&mutex_lock, NULL);
    pid = pthread_create(&p_thread, 0, proc_thread, (void *)&p);
    
    if( pid < 0 )
    {
        perror( "thread :" );
        kill(getppid(),SIGTERM);
        return 0;
    }
    
    usleep( 100000 );
    return(pid);
}

/*
 *========================================================================
 *
 *   함 수 명 : SIG_cld()
 *   작 성 자 : JBY
 *   작 성 일 : 2018.07.13
 *   수 정 일 :
 *   설    명 :
 *
 *========================================================================
*/

void SIG_cld()
{
    int tid, pid, status,h,l;

    pid = wait( &status );
    if( pid < 0 )
        perror( "wait system call error :" );
    else if( pid > 0 )
    {
        h=(status>>8)&0x00ff;
        l=status&0x00ff;
        if(h)
        {
            if(l==0177) proc_log("INIT: child %d STOP by signal %d\n", pid,h);
            if(l==0) proc_log("INIT: child %d EXIT with status %d\n", pid,h);
        } else
            proc_log("INIT: child %d DEAD by signal %d with %s\n", pid,l&0x7f,(l&0x80?"CORE DUMP":"NO CORE"));

        tid = get_tid( pid );

        if( tid > 0 )
        {
            proc_log("INIT: dead process %d :: %s",
            tid, system_info->task_info[tid].argv[0]);
            system_info->task_info[tid].proc_id = system_info->task_info[tid].opid = 0;
            system_info->task_info[tid].act = TASK_STOP;

            pid = spawn( tid , 10);

            system_info->task_info[tid].proc_id = system_info->task_info[tid].opid = pid;
        }
    }

    signal( SIGCLD, SIG_cld );
}
#if 0
int main(int argc, char* argv[])
#else
int main()
#endif
{
    mkdir(LOG_DIR,0755);
    chdir(LOG_DIR);
    shmid= shmget(KEY_INIT(),
        sizeof(SYS_INFO),IPC_PERM);

    proc_log("INIT shmid %d", shmid);
    if(shmid<0)
    {     proc_log("INIT ABORT: CANNOT GET SYS_INFO\n");
        exit(1);
    }
    system_info = (SYS_INFO *)shmat(shmid,(char*)0,IPC_PERM);
    if(system_info == NULL)
    {     proc_log("INIT ABORT: CANNOT ATTACH TO SYS_INFO\n");
        exit(1);
    }

    sigrelse(SIGCLD);
    signal( SIGTERM, SIG_term );
    signal( SIGHUP, SIG_IGN );
    signal( SIGCLD, SIG_cld );

    read_task_tab();
    start_task();

    sigrelse(SIGCLD);
    signal( SIGCLD, SIG_cld );
    for(;;) pause();
}
/*  End of "initd.c"  */
