/*
*========================================================================
*
*   SYSTEM   : AZN_PLAZA_LANE LIBRARY
*   FILE     : lb_proc.c
*   Progrmer : JBY (baarong@neighbor21.co.kr)
*   Date     : 2018.09.05
*   Modified :
*   Remark   :
 *              
 *========================================================================
*/

/*
 *========================================================================== 
 * Head  정의                                                                
 *==========================================================================
*/ 

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h> 
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h> 
#include <strings.h>

#include "dir_path.h"
#if 0
#include "ipc_def.h"
#else
#include "lb_func_list.h"
#endif
#include "file_lb.h"  /* 공통 Library Prototypes */
#if 1
#include "taglnk_frame.h"
#endif

/*
 *========================================================================
 *
 *   Function : lb_get_pid()
 *   Progrmer : JBY (baarong@neighbor21.co.kr)
 *   Date     : 2018.09.05
 *   Modified :
 *   Remark   : File Queue존재 및 Size로 유효한 Queue인지 check.
 *              실행중인 PROCESS ID가 CALL한 PROCESS는 제외.
 *              ARGS :  char *pname;           PROCESS NAME 
 *                      char *args1;           1st ARGUMENT  
 *                      char *args2;           2nd ARGUMENT    
 *
 *========================================================================
*/

int   lb_get_pid(pid_name, args1, args2)
char    *pid_name;
char    *args1, *args2;
{
    FILE    *chkf;
    char    log_f[100]; memset(log_f, 0x00, sizeof(log_f));
    char    command[128];
    char    line_b[128];
    char    ign_b[64], pid_b[16];
    char    arg_p[8][64];
    char    *nam_b;
    int     arg_n = 1, cmp_i;
    int     pid;
    unsigned int ii;

    sprintf(command, "Tx%d", getpid());

#if 1
    strcpy(log_f,tempnam(P_tmpdir, command));
#else
    strcpy(log_f,mkstemp(command)); //mkstemp 인자가 int형...
#endif

    if (!strlen(log_f)) return (-1);
    sprintf(command, "/bin/ps -ef | /bin/grep %s | /bin/grep -v grep > %s 2>&1", pid_name, log_f);
    system(command);

    pid  = -1;
    chkf = fopen(log_f, "r");
    while(fgets(line_b, sizeof(line_b), chkf) == line_b)
    {
        pid_b[0] = '\0';
        for (ii = 0; ii < 8; ii++)
            arg_p[ii][0] = '\0';

        sscanf(line_b, "%s %s %s %s %s %s %s %s %s %s %s %s",
                ign_b, pid_b, ign_b, ign_b, 
                arg_p[0], arg_p[1], arg_p[2], arg_p[3],
                arg_p[4], arg_p[5], arg_p[6], arg_p[7]);

        for (ii = 0; ii < 8; ii++)
        {
            if (strlen(arg_p[ii])) arg_n = ii+1;
        }

        cmp_i = arg_n - 1;
        if (args2 != NULL && strlen(args2))
        {
            if (strcmp(arg_p[cmp_i], args2) != 0)
                continue;
            cmp_i--;
        }

        if (args1 != NULL && strlen(args1))
        {
            if (strcmp(arg_p[cmp_i], args1) != 0)
                continue;
            cmp_i--;
        }
    
        nam_b = arg_p[cmp_i];    
        for (ii = 0; ii < strlen(arg_p[cmp_i]); ii++)
        {
            if (arg_p[cmp_i][ii] == '/')
                nam_b = &arg_p[cmp_i][ii+1];
        }

        if (strcmp(nam_b, pid_name) != 0) continue;

        pid = atoi(pid_b);
        if (pid == getpid())
        {
            pid = -1;
            continue;
        }
        break;
    }
    fclose(chkf);

    unlink(log_f);

    return (pid);
}

/*
 *========================================================================
 *
 *   Function : lb_user_chg()
 *   Progrmer : JBY (baarong@neighbor21.co.kr)
 *   Date     : 2018.09.05
 *   Modified :
 *   Remark   : user ID를 바꿔준다. 
 *
 *========================================================================
*/

int lb_user_chg()
{
    uid_t     user_id;
    struct    passwd     *passwd;

    passwd = (struct passwd *)getpwnam("tcs");
    if (passwd == NULL) return (-1);
    user_id = getuid();

    if (user_id == 0)
    {
        setgid(passwd->pw_gid);
        setuid(passwd->pw_uid);
    }
    else if (user_id != passwd->pw_uid) return (-1);

    user_id = getuid();
    if (user_id != passwd->pw_uid) return (-1);
    else                           return (0);
}

/*
 *========================================================================
 *
 *   Function : lb_proc_ctrl()
 *   Progrmer : JBY (baarong@neighbor21.co.kr)
 *   Date     : 2018.09.05
 *   Modified :
 *   Remark   : TCS 프로세스 관리, 제어
 *
 *========================================================================
*/

int   lb_proc_ctrl(srch_admin, reply_admin)
struct    srch_admin    *srch_admin;     /* 제어 명령 구조체 */
struct    reply_admin   *reply_admin;     /* 반환전문 구조체  */
{
    int       sock, len;
    fd_set    rfds;
    char      read_b[sizeof(struct reply_admin)+128];
    unsigned int  read_l;

    memset(reply_admin, 0, sizeof(struct reply_admin));
    reply_admin->req_cd = srch_admin->req_code;
    reply_admin->req_cd = -1;

    sock = lb_low_connect(0, (unsigned char *)"", 0);
    if (sock < 0)
    {
        sprintf(reply_admin->err_msg, "시스템 관리자와 연결되지 않습니다.");
        return (0);
    }
    
    len = write(sock, srch_admin, sizeof(struct srch_admin));
    if (len != sizeof(struct srch_admin))
    {
        close(sock);
        sprintf(reply_admin->err_msg, "시스템 관리자로 처리요청을 할 수 없습니다.");
        return (0);
    }
    
    read_l = 0;
    for (;;)
    {
        FD_ZERO(&rfds);
        FD_SET(sock, &rfds);
        
        if (select(sock+1, &rfds, NULL, NULL, NULL) <= 0)
            break;
        len = read(sock, &read_b[read_l], sizeof(read_b)-read_l);
        if (len <= 0)
            break;
        read_l += len;
        if (read_l >= sizeof(struct reply_admin))
            break;
    }
    close(sock);
    
    if (read_l < sizeof(struct reply_admin))
        sprintf(reply_admin->err_msg,"시스템 관리자로 부터 응답이 없습니다.");
    else
        memcpy(reply_admin, read_b, sizeof(struct reply_admin));

    return (0);
}

/*
 *========================================================================
 *
 *   Function : lb_low_proc_reply()
 *   Progrmer : JBY (baarong@neighbor21.co.kr)
 *   Date     : 2018.09.05
 *   Modified :
 *   Remark   : 하위통신 차로 I/F 프로그램으로 응답시간 단축
 *              1. TABLE DUMP - 1.1 기초사항    1.2 근무자    1.3 요금    1.4 무효신용    1.5 무효면제
 *              2. 회선 TEST                                                                          
 *              3. 재송요구                                                                           
 *              4. 보증전송연번                                                                       
 *              5. 명령어를 전달, 처리결과를 반환 한다.     
 *                                          
 *========================================================================
*/

int   lb_low_proc_reply(wf, lc_cmd, lc_reply)
struct    write_info    *wf;            /* 처리정보        */
struct    lo_lane_ctrl_cmd    *lc_cmd;        /* 제어 요청 전문     */
struct    lo_lane_ctrl_reply    *lc_reply;        /* 결과 반환 전문    */
{
    struct    srch_admin    srch_admin;
    struct    reply_admin   reply_admin;
    fd_set    rfds;
    int       sock, len;
    char      read_b[128];
    unsigned int read_l = 0;
    struct    timeval   timeval;


    memset(lc_reply, 0, sizeof(struct lo_lane_ctrl_reply));
    lc_reply->cmd = lc_cmd->cmd;
    lc_reply->rsp = 1;        

    switch (lc_cmd->cmd)
    {
    case LW_PROC_STRT:
        srch_admin.req_code = REQ_EXEC;
    case LW_PROC_END:
        if (lc_cmd->cmd == LW_PROC_END)
            srch_admin.req_code = REQ_KILL;
        sprintf(srch_admin.app_nm, "tcslcp");
        srch_admin.hnd_lane_no = atoi((const char *)wf->lane_no);
        read_l = lb_proc_ctrl(&srch_admin, &reply_admin);
        if (reply_admin.rsp_cd == 0)
        {
            lc_reply->rsp = 0;
            lc_reply->fin = 1;
        }                                                 
        memcpy(lc_reply->msg, reply_admin.err_msg, sizeof(lc_reply->msg));
        return (0);
    default:
        break;
    }

    sock = lb_low_connect(1, wf->plz_id, atoi((const char *)wf->lane_no));
    if (sock < 0)
    {
        sprintf(lc_reply->msg, "차로 프로세스와 연결되지 않습니다.");
        return (0);
    }
    len = write(sock, lc_cmd, sizeof(struct lo_lane_ctrl_cmd));
    if (len != sizeof(struct lo_lane_ctrl_cmd))
    {
        close(sock);
        sprintf(lc_reply->msg, "차로 프로세스로 처리요청을 할 수 없습니다.");
        return (0);
    }
    read_l = 0;
    for (;;)
    {
        FD_ZERO(&rfds);
        FD_SET(sock, &rfds);

           timeval.tv_sec  = 30;
           timeval.tv_usec = 0;
        
        if (select(sock+1, &rfds, NULL, NULL, &timeval) <= 0) break;

        len = read(sock, &read_b[read_l], sizeof(read_b)-read_l);
        if (len <= 0) break;
        read_l += len;
        if (read_l >= sizeof(struct lo_lane_ctrl_reply)) break;
    }
    close(sock);
    
    if (read_l < sizeof(struct lo_lane_ctrl_reply))
        sprintf(lc_reply->msg, "차로 프로세스로 부터 응답이 없습니다.");
    else{
        sprintf(lc_reply->msg, "정상처리 되었습니다.");
        memcpy(lc_reply, read_b, sizeof(struct lo_lane_ctrl_reply));
        }

    return (0);
}
     
/*
 *========================================================================
 *
 *   Function : lb_low_proc()
 *   Progrmer : JBY (baarong@neighbor21.co.kr)
 *   Date     : 2018.09.05
 *   Modified :
 *   Remark   : 하위통신 차로 I/F 프로그램으로
 *
 *========================================================================
*/

int   lb_low_proc(wf, lc_cmd, lc_reply)
struct    write_info    *wf;            /* 처리정보        */
struct    lo_lane_ctrl_cmd    *lc_cmd;        /* 제어 요청 전문     */
struct    lo_lane_ctrl_reply    *lc_reply;        /* 결과 반환 전문    */
{
    struct    srch_admin    srch_admin;
    struct    reply_admin   reply_admin;
    int       sock, len;
    int       read_l = 0;

    memset(lc_reply, 0, sizeof(struct lo_lane_ctrl_reply));
    lc_reply->cmd = lc_cmd->cmd;
    lc_reply->rsp = 1;        

    switch (lc_cmd->cmd)
    {
    case LW_PROC_STRT:
        srch_admin.req_code = REQ_EXEC;
    case LW_PROC_END:
        if (lc_cmd->cmd == LW_PROC_END)
            srch_admin.req_code = REQ_KILL;
        sprintf(srch_admin.app_nm, "tcslcp");
        srch_admin.hnd_lane_no = atoi((const char *)wf->lane_no);
        read_l = lb_proc_ctrl(&srch_admin, &reply_admin);
        printf("LW_PROC_END [%d]\n", read_l);
        if (reply_admin.rsp_cd == 0)
        {
            lc_reply->rsp = 0;
            lc_reply->fin = 1;
        }
        memcpy(lc_reply->msg, reply_admin.err_msg, sizeof(lc_reply->msg));
        return (0);
    case LW_RQ_SEQ_NO:
    	memcpy(lc_cmd->msg, wf->buf, sizeof(lc_cmd->msg));
    	break;
    default:
        break;
    }

    sock = lb_low_connect(1, wf->plz_id, atoi((const char *)wf->lane_no));

    if (sock < 0)
    {
        sprintf(lc_reply->msg, "차로 프로세스와 연결되지 않습니다.");
        return (0);
    }
    len = write(sock, lc_cmd, sizeof(struct lo_lane_ctrl_cmd));

    if (len != sizeof(struct lo_lane_ctrl_cmd))
    {
        close(sock);
        sprintf(lc_reply->msg,"차로 프로세스로 처리요청을 할 수 없습니다.");
        return (0);
    }

    sprintf(lc_reply->msg, "정상처리 되었습니다.");

    return (0);
}


/*
 *========================================================================
 *
 *   Function : lb_low_connect()
 *   Progrmer : JBY (baarong@neighbor21.co.kr)
 *   Date     : 2018.09.05
 *   Modified :
 *   Remark   : 하위차로 프로그램의 제어를 위한 차로 PROCESS와의 접속처리
 *
 *========================================================================
*/

int   lb_low_connect(caller, plz_id, lane_no)
int           caller;
unsigned char *plz_id;
int           lane_no;
{
    struct    sockaddr_un    sock_lcp;
    char      sock_path[128];
    int       sock;

    signal(SIGPIPE, SIG_IGN);
    if (caller)
        sprintf(sock_path, "%s/%s/tcslcp%.6s%02d", DIR_TCS, DIR_SPOOL, plz_id, lane_no);
    else
        sprintf(sock_path, "%s/%s/%s", DIR_TCS, DIR_SPOOL, PROC_TCS);

    sock = socket(AF_UNIX, SOCK_STREAM, 0);

    if (sock < 0) return (sock);

    bzero(&sock_lcp, sizeof(sock_lcp));
    strcpy(sock_lcp.sun_path, sock_path);
    sock_lcp.sun_family = AF_UNIX;

    if (connect(sock, (struct sockaddr *)&sock_lcp, sizeof(sock_lcp)) < 0)
    {
        close(sock);
        return (-1);
    }

    return (sock);
}
