From 8f39550cea77eef1054b1febe7e647f96ac523c2 Mon Sep 17 00:00:00 2001
From: victor <taehoon@falinux.com>
Date: Thu, 22 Jun 2017 17:27:41 +0900
Subject: [PATCH] =?UTF-8?q?superdaemon=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/superdaemon/Makefile        |  15 ++
 app/superdaemon/main.c          | 392 ++++++++++++++++++++++++++++++++++++++++
 app/superdaemon/main.h          |  27 +++
 app/superdaemon/projectinc.c    |  33 ++++
 app/superdaemon/projectinc.h    |  21 +++
 app/superdaemon/readme.txt      |  29 +++
 app/superdaemon/superdaemon.ini |  30 +++
 7 files changed, 547 insertions(+)
 create mode 100644 app/superdaemon/Makefile
 create mode 100644 app/superdaemon/main.c
 create mode 100644 app/superdaemon/main.h
 create mode 100644 app/superdaemon/projectinc.c
 create mode 100644 app/superdaemon/projectinc.h
 create mode 100644 app/superdaemon/readme.txt
 create mode 100644 app/superdaemon/superdaemon.ini

diff --git a/app/superdaemon/Makefile b/app/superdaemon/Makefile
new file mode 100644
index 0000000..dee6914
--- /dev/null
+++ b/app/superdaemon/Makefile
@@ -0,0 +1,15 @@
+CC = arm-buildroot-linux-gnueabihf-gcc 
+OBJS = main.o projectinc.o
+TARGET = superdaemon
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+	$(CC) -lm -o $@ $^
+          
+%.o:%.c
+	@echo "Compiling $< ..."
+	$(CC) -c $<
+        
+clean:
+	rm $(OBJS) $(TARGET) 
diff --git a/app/superdaemon/main.c b/app/superdaemon/main.c
new file mode 100644
index 0000000..c3d0ffb
--- /dev/null
+++ b/app/superdaemon/main.c
@@ -0,0 +1,392 @@
+/*********************************************************************
+ ��  �� :   superdaemon - ��ϵ� ���α׷��� ���� �� ����
+ ��  �� :   1.0.2
+                  -  get_execinfo() �Լ� �߰�
+                  -  read_task_list() �Լ����� task_t ������ ��� �����ϵ��� ����
+            1.0.1
+                  -  �ڽ� ���μ������� ���α׷��� �����ϱ� ����
+                     �θ� ���μ����� Ÿ��ũ ������ ������ ���μ����� ID��
+                     �����ϴ� �ð��� ���� �ֱ� ���� sleep()�Լ��� ȣ��
+            1.0.0
+*********************************************************************/
+#include  <stdio.h>
+#include  <stdlib.h>
+#include  <signal.h>
+#include  <string.h>
+#include  <sys/types.h>
+#include  <sys/wait.h>
+#include  <unistd.h>
+#include  "main.h"
+#include  "projectinc.h"
+
+#define  PATH_SIZE         255
+#define  TASK_ARRAY_SIZE   20
+
+task_t   ary_task[TASK_ARRAY_SIZE];                                     // Ÿ��ũ �迭
+int      cnt_task;                                                      // ������ Ÿ��ũ�� ����
+
+//--------------------------------------------------------------------
+// desc   ���ϵ� ���μ����� ����Ǹ� �߻��ϴ� �̺�Ʈ �ڵ鷯
+// params sig
+// ref    ����� ���ϵ� ���μ����� �ش��ϴ� ary_task �� ������ ����
+//        �����Ѵ�.
+//
+//        ary_task ������ ���� �����ϸ�, main() ���� check_task_list()
+//        �� ȣ�������ν� �ٽ� �����ϰ� �ȴ�.
+//--------------------------------------------------------------------
+void on_check_child( int sig)
+{
+   pid_t    pid;
+   int      result;
+   int      ndx;
+
+                                 // ����� ���ϵ� ���μ����� �ش��ϴ� ary_task �������� ã�´�.
+                                 // task_t �������� pid �� 0 ���� �����ϸ� check_task_lisk() ����
+                                 // count_down ���� �����ϰ�, 0 �̵Ǹ� �ٽ� �����ϰ� �ȴ�.
+
+   while( 0 < ( pid = waitpid( -1, &result, WNOHANG)))
+   {                                                                    dp( "killed child pid=%d", pid);
+      for ( ndx= 0; ndx < cnt_task; ndx++)
+      {                                                                 dp( "checked child pid=%d %s", ary_task[ndx].pid, ary_task[ndx].full_filename);
+         if ( pid == ary_task[ndx].pid)
+         {
+            ary_task[ndx].count_down   = ary_task[ndx].interval;        // �ٽ� �����ϱ� ������ ��� �ð�(��)
+            ary_task[ndx].pid          = 0;                             // check_task_list() �� ����� �ǵ��� 0 ���� �ʱ�ȭ
+         }
+      }
+   }
+}
+
+//--------------------------------------------------------------------
+// desc   _str ���� ù��° ���� ���� ������
+//             �Ǵ� ���� ���ڰ� ���� ������ ���ڿ� �������� _rst
+//             �� �����Ѵ�.
+// params _str ���� ���ڿ��� ������ �ִ� ����
+//        _rst ���ڿ��� ���� ���� ����
+// ret    ���� ���ڿ� ������ ���� ��ġ�� ������
+//--------------------------------------------------------------------
+char *str_spc( char *_str, char *_rst)
+{
+   char *pos;
+
+   *_rst = '\0';                                                        // NULL �� ����
+   pos = index(_str, ' ');
+   if ( !pos)                                                           // ���� �����ڰ� ���ٸ� ���� ������
+   {
+      strcpy(_rst, _str);
+   }
+   else
+   {
+      strncpy(_rst, _str, pos-_str);
+      _rst[pos-_str]  = '\0';
+      while ( ' ' == *pos)                                              // �տ� �ִ� ���� ����
+         pos++;
+   }
+   return( pos);
+}
+
+//--------------------------------------------------------------------
+// desc   _task �� ���뿡 ���� �� ���μ����� ���� �����Ѵ�.
+// params _task : ���� ���Ͽ� ���� ����
+// ref    1.
+//          _task �� task �κ��� �������ϰ� �μ��� ���Ѵ�.
+//          �����̳� �μ����� ������ �ִٸ� ������ ����ϰ�,
+//          _task �� error �� �����ڵ带 �־� ���� ȣ�⿡�� ������
+//          ���� �ʵ��� �Ѵ�.
+//        2.
+//          �μ��� 20������ ó���Ѵ�.
+//
+//        3.
+//          �μ��� ������ ���α׷��� ���� �ٸ��Ƿ�,
+//          *[] �� ����ϴ� execv() �� ����Ѵ�.
+//--------------------------------------------------------------------
+void exec_task( task_t *_task)
+{
+   pid_t    pid;
+
+   if ( ERR_NONE != _task->error)
+   {
+      return;
+   }
+
+   pid = fork();
+   if ( 0 == pid)                                                       // �ڽ� ���μ��� ���
+   {                                                                    dp( "1 sec wait and exec %s", _task->full_filename);
+      sleep( 1);                                                        // ����  ���μ������� _task->pid = pid �� ������ �ǵ��� sleep
+      execv(_task->full_filename, _task->params);                       // ���α׷��� �����Ѵ�.
+   }
+   else if ( 0 < pid)                                                   // fork ���࿡ �̻��� �����ٸ�
+   {                                                                    dp( "********** task= %s New Pid= %d", _task->full_filename, pid);
+      _task->pid = pid;
+   }
+   else                                                                 // ���� fork() ���࿡ �����ߴٸ�
+   {                                                                    dp( "Reset Counter %d", _task->interval);
+      _task->count_down   = _task->interval;
+   }
+}
+
+//--------------------------------------------------------------------
+// desc   ary_task ����� Ȯ���ؼ� ����� ���ϵ尡 �ִ����� Ȯ���Ѵ�.
+//        ����� ���ϵ尡 �ִٸ� ���࿩��(���� ����)�� Ȯ���ϰ�,
+//        �� ���� ����.
+//--------------------------------------------------------------------
+void check_task_list( void)
+{
+   int     ndx;
+
+                                    // ary_task ��Ͽ��� pid �� 0 �� �׸���
+                                    // ����� ���ϵ� �̴�.
+                                    //
+
+  for ( ndx = 0; ndx < cnt_task; ndx++)
+  {
+      if ( ( !ary_task[ndx].pid)                                        // Ÿ��ũ�� ���� ���̰�
+            && ( ERR_NONE == ary_task[ndx].error))                      // ������ ���ٸ�
+      {
+         if ( 0 < ary_task[ndx].count_down)                             // ���� ī��Ʈ �ٿ� ���̶��
+         {                                                              dp( "count down :%d", ary_task[ndx].count_down);
+            ary_task[ndx].count_down--;
+         }
+         else                                                           // ī��Ʈ �ٿ��� �Ϸ�
+         {
+            exec_task( &ary_task[ndx]);
+         }
+      }
+  }
+  return;
+}
+
+//--------------------------------------------------------------------
+// ������ ���ڿ����� task_t �� ������ ���α׷� �̸��� �μ��� ���Ѵ�.
+//
+// _data : ���Ͽ��� �о� ���� ������ ���丮 ��ġ������ ���ڿ�
+// _task : ���� ���Ͽ� ���� ����
+//
+// typedef struct
+// {
+//   char *full_filename;     <- ���丮 ���� ��ü ���� �̸��� ���Ѵ�.
+//   char *params[20];        <- ���α׷� ������ ���� �μ� �迭�� ���Ѵ�.
+//          :
+//   int   error;             <- ������ ���� �߿� ������ �ִٸ� ���� ����
+//          :
+// } task_t;
+
+
+
+// ref    1.
+//          _task �� task �κ��� �������ϰ� �μ��� ���Ѵ�.
+//          �����̳� �μ����� ������ �ִٸ� ������ ����ϰ�,
+//          _task �� error �� �����ڵ带 �־� ���� ȣ�⿡�� ������
+//          ���� �ʵ��� �Ѵ�.
+//        2.
+//          �μ��� 20������ ó���Ѵ�.
+//
+//        3.
+//          �μ��� ������ ���α׷��� ���� �ٸ��Ƿ�,
+//          *[] �� ����ϴ� execv() �� ����Ѵ�.
+//--------------------------------------------------------------------
+void get_execinfo( char *_data, task_t *_task)
+{
+   char     buf[PACKET_SIZE];
+   char     exe_path[PATH_SIZE+5];                                      // ���� ��� +5
+   char     exe_name[PATH_SIZE+5];                                      // ���� ��� +5
+   int      nparam;
+   int      sz_str;
+   pid_t    pid;
+
+                                 // ��� ���� ���Ѵ�.
+                                 // ��� ���� ���� '/' �� ���ٸ� �߰��Ѵ�.
+
+   _data = str_spc(_data, buf);
+   if ( PATH_SIZE < strlen( buf))                                       // ��θ��� ���̰� �ʹ� ���.
+   {
+      printf( "%s : path is too long!!\n", buf);
+      _task->error  = ERR_PATH_TOO_LONG;
+      return;
+   }
+   strcpy( exe_path, buf);                                              // exe_path <- ��θ�
+
+                                 // ��� ���� ���� '/' �� Ȯ���Ѵ�.
+
+   sz_str  = strlen( exe_path);
+   if ( '/' != exe_path[sz_str-1])                                      // ���� / �� �ݵ�� ����
+   {
+      exe_path[sz_str  ]  = '/';
+      exe_path[sz_str+1]  = '\0';
+   }
+
+                                 // ���� ������ ��ü �̸��� ���Ѵ�.
+
+   _data  = str_spc(_data, buf);
+   if ( PATH_SIZE < strlen( exe_path)+strlen( buf))                     // ��ο� ���������� �̸� ���� ���� �ʹ� ���.
+   {
+      printf( "%s/%s : full name is too long!!\n", exe_path, buf);
+      _task->error  = ERR_PATH_TOO_LONG;
+      return;
+   }
+   strcpy( exe_name, buf);
+   strcat( exe_path, exe_name);                                         // exe_path <- ���/���������̸�
+   _task->full_filename = malloc( strlen( exe_path)+1);
+   strcpy( _task->full_filename, exe_path);
+
+                                 // ���� ������ ���� ������ Ȯ���Ѵ�.
+
+   if ( 0 != access(_task->full_filename, F_OK))
+   {
+      printf( "%s is not exists!!\n",_task->full_filename);
+      _task->error  = ERR_PATH_TOO_LONG;
+      return;
+   }
+
+                                 // ���࿡ �ʿ��� �μ��� �迭�� �����Ѵ�.
+                                 // ù��° �μ��� �������� �̸����� �Ѵ�.
+                                 // ������ �μ��� NULL �� �ǵ��� �Ѵ�.
+
+   _task->params[0] = malloc( strlen( exe_name)+1);
+   strcpy(_task->params[0], exe_name);
+
+                                 // [0] �μ��� ���� ������ �̸��̹Ƿ�,
+                                 // [1] ���� ���α׷��� �μ��� �����Ѵ�.
+                                 // params�� *[20]�� ����Ǿ� �����Ƿ�
+                                 // �μ� ������ 19 ���� ���� ���ϰ� �Ѵ�.
+
+   nparam    = 1;
+   while (_data)
+   {
+      _data = str_spc(_data, buf);                                      // ���� �μ����� ���Ѵ�.
+      _task->params[nparam] = malloc( strlen( buf)+1);                  // param[nparam] <- ���
+      strcpy(_task->params[nparam], buf);
+      nparam++;
+      if ( 19 == nparam)                                                // �μ��� �ʹ� ���ٸ�
+      {
+         printf( "%s has too many params!!\n", exe_name);
+         _task->error  = ERR_TOO_MANY_PARAMS;
+         return;
+      }
+   }
+   _task->params[nparam]   = ( char *)0;                                // ������ �������� NULL
+   _task->error            = ERR_NONE;                                  // ���� ����
+}
+
+//--------------------------------------------------------------------
+// ini ���Ͽ��� ������ ������ ������ �о� ���̰�,
+// ary_task ����� �ۼ��Ѵ�.
+//--------------------------------------------------------------------
+void read_task_list( void)
+{
+   FILE  *fp;
+   char  *tag;
+   char  *pos;
+   char   buf[PACKET_SIZE];
+   char   item[255];
+
+   cnt_task  = 0;                                                       // ������ �۾� ���� �ʱ�ȭ
+
+   fp = fopen( "./superdaemon.ini", "r");                               // ȯ������ open;
+   if ( NULL == fp)
+   {                                                                    // �о� ���� Ÿ��ũ�� ����
+      return;
+   }
+   else
+   {
+      while( NULL != fgets( buf, PACKET_SIZE, fp))
+      {
+         tag = buf;
+         remove_white_char( tag);                                       // ���忡 �����ǵ�� ���� ȭ��Ʈ ���ڸ� ���ش�.
+
+                                 // ���α׷� ���� �� ���� ���۱����� �ð� ������ ���Ѵ�.
+
+         while ( ' ' == *tag)                                           // �տ� �ִ� ���� ����
+         {
+            tag++;
+         }
+
+         if ( ( ' ' > *tag) ||                                          // ������ ���̰ų�
+              ( !strncmp( tag, "//", 2))  )                             // �ּ����̶�� ���� ������
+         {
+            continue;
+         }
+                                 // ���� ù ��° �����ʹ� ��� �ð� �����̴�.
+                                 // ù��° ���ڿ����� �ð� ������ ���Ѵ�.
+
+         tag = str_spc( tag, item);
+         ary_task[cnt_task].interval  = atoi( item);
+
+                                 // ���α׷��� ���� ������ ���Ѵ�.
+                                 // ���� �������� ��ο� ���α׷� ���� �־�� �ϹǷ�
+                                 // �ּ� ���� ���ڰ� �ϳ� �־�� �Ѵ�.
+                                 // �μ��� ���� ���ڰ� ���ٸ� ����Ѵ�.
+
+         if ( ( ' ' > *tag) ||                                          // ������ ���̰ų�
+              ( !strncmp( tag, "//", 2))  )                             // �ּ����̶�� ���� ������
+         {
+            continue;
+         }
+
+         pos = index( tag, ' ');                                        // ���� ���ڰ� ���ٸ� ����Ѵ�.
+         if (!pos)
+         {
+            continue;
+         }
+
+         get_execinfo( tag, &ary_task[cnt_task]);
+
+                                 // task �� �ʱⰪ�� �ʱ�ȭ �Ѵ�.
+
+         ary_task[cnt_task].count_down = 0;
+         ary_task[cnt_task].pid        = 0;
+         cnt_task++;
+         if ( TASK_ARRAY_SIZE == cnt_task)
+         {
+            printf( "***** Task list is over %d. *****\n", TASK_ARRAY_SIZE);
+            break;
+         }
+      }
+   }
+   fclose( fp);
+}
+
+//--------------------------------------------------------------------
+// ���ϵ� ���μ����� ������ Ȯ���ϴ� �ñ׳� ���
+//--------------------------------------------------------------------
+void reg_child_signal( void)
+{
+   struct  sigaction  sig_child;                                        // ���ϵ��� ������ �˱� ���� �ñ���
+
+   sig_child.sa_handler  = on_check_child;
+   sigemptyset( &sig_child.sa_mask);
+   sig_child.sa_flags    = 0;
+   sigaction( SIGCHLD, &sig_child, 0);
+}
+
+//--------------------------------------------------------------------
+// main procedure
+//--------------------------------------------------------------------
+int main( int argc, char **argv)
+{
+#ifdef NDEBUG
+
+   pid_t   pid_daemon;                                                  // release ����� ���� endif ������ ������ ����ȴ�.
+
+   pid_daemon  = fork();
+   if ( 0 > pid_daemon)                                                 // fork() ���࿡ �����ߴٸ�
+   {
+      printf( "ERR: fork() failed\n");                                  // ���� ������ �˸���.
+      exit( 1);
+   }
+   else if( 0 != pid_daemon)                                            // �θ� ���μ��� ���
+   {
+      exit( 0);                                                         // �����Ѵ�.
+   }
+
+#endif
+
+   reg_child_signal();                                                  // child �ñ׳� ���
+   read_task_list();                                                    // ������ ���� ����� �ۼ��Ѵ�.
+
+   while( 1 )
+   {
+      check_task_list();                                                // �۾� ���¸� Ȯ���Ѵ�.
+      sleep( 1);                                                        // 1 �ʸ� ���
+   }
+}
diff --git a/app/superdaemon/main.h b/app/superdaemon/main.h
new file mode 100644
index 0000000..f6ffa97
--- /dev/null
+++ b/app/superdaemon/main.h
@@ -0,0 +1,27 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include  <sys/types.h>
+
+#define   TRUE                1
+#define   FALSE               0
+                              
+#define   ERR_NONE            0
+#define   ERR_PATH_TOO_LONG   -1
+#define   ERR_EXE_TOO_LONG    -2
+#define   ERR_PARAMS_TO0_LONG -3;
+#define   ERR_TOO_MANY_PARAMS -4;
+#define   ERR_EXECUTE         -5;
+
+typedef struct
+{
+  char *full_filename;
+  char *params[20];
+  int   interval;
+  int   count_down;
+  int   error;
+  pid_t pid;
+} task_t;
+
+                                  
+#endif
diff --git a/app/superdaemon/projectinc.c b/app/superdaemon/projectinc.c
new file mode 100644
index 0000000..fc62e09
--- /dev/null
+++ b/app/superdaemon/projectinc.c
@@ -0,0 +1,33 @@
+#include  <stdio.h>
+#include  <stdlib.h>
+#include  <string.h>
+#include  "projectinc.h"
+
+//--------------------------------------------------------------------
+// desc   ���ڿ����� /t /n /f �� ���� ȭ��Ʈ ���ڸ� NULL �ڵ��
+//        �ٲپ� �ش�. 
+//--------------------------------------------------------------------
+void remove_white_char( char *_str)
+{
+  int   ndx;
+  
+  for ( ndx = 0; ndx < strlen(_str); ndx++)
+  {
+    if (' ' > _str[ndx])
+    {
+      _str[ndx] = '\0';
+    }
+  }
+}
+
+//--------------------------------------------------------------------
+// desc   �޽����� �����ϰ� ������ �����Ѵ�.
+//--------------------------------------------------------------------
+void error_handling(char *message)
+{
+  fputs( message, stderr);
+  fputc( '\n', stderr);
+  exit(1);
+}
+
+
diff --git a/app/superdaemon/projectinc.h b/app/superdaemon/projectinc.h
new file mode 100644
index 0000000..85d8fcc
--- /dev/null
+++ b/app/superdaemon/projectinc.h
@@ -0,0 +1,21 @@
+#ifndef _PROJECTINC_
+#define _PROJECTINC_
+
+#define NDEBUG
+
+#ifndef NDEBUG
+#define dp(fmt,args...) printf( fmt, ## args ); putchar( '\n')
+#define dlp(fmt,args...) printf( "[%s %d]" fmt, __FILE__,__LINE__, ## args )
+#else
+#define dp(fmt,args...) 
+#define dlp(fmt,args...) 
+#endif
+
+extern void remove_white_char( char *);
+extern void error_handling(char *message);
+
+//----- SysManager ---------------------------------------------------
+
+#define   PACKET_SIZE          1024
+                                                                            
+#endif
diff --git a/app/superdaemon/readme.txt b/app/superdaemon/readme.txt
new file mode 100644
index 0000000..d3ff7c3
--- /dev/null
+++ b/app/superdaemon/readme.txt
@@ -0,0 +1,29 @@
+prj name  : superdaemon - 등록된 프로그램을 실행 및 관리
+descript  :
+
+          1.  superdaemon.ini 에 등록된 프로그램을 실행하고
+              프로그램 종료를 계속 확인하면서,
+              종료되면 지정된 시간 후 다시 실행하게 한다.
+
+          2.  추후, watch dog 기능을 추가한다.
+
+version :
+          0.0.1   superdaemon.ini 에 등록된 프로그램을 실행
+          0.0.2   execl() 사용하여 구성
+          0.0.3   1. 
+                    execl() 을 execv() 로 재 구성
+                    ref
+                        execl() 은 인수가 ( )
+                  2.
+                    실행파일 정보 문자열에 이상이 없을 때에만
+                    fork() 실행하도록 수정
+          1.0.0   1.
+                    파일을 실행할 때, 파일의 존재 유무를 확인하는
+                    코드를 추가
+                  2.
+                    환경 파일에서 경로명에 '/' 이 없을 때 발생하던
+                    오류를 잡음
+                                      
+
+                                                                      장길석, goguryeo@gmail.com
+    
\ No newline at end of file
diff --git a/app/superdaemon/superdaemon.ini b/app/superdaemon/superdaemon.ini
new file mode 100644
index 0000000..54dcd46
--- /dev/null
+++ b/app/superdaemon/superdaemon.ini
@@ -0,0 +1,30 @@
+// superdaemon 에서 사용되는 환경파일입니다.
+
+// 아래의 리스트는 superdaemon 에서 실행되며,
+// 프로그램이 종료되더라도 지정된 시간(초) 후에 다시
+// 자동으로 실행됩니다.               
+
+// 작성 방법은 공백 문자로 분리가 되며,
+// [시간] [경로] [실행파일 이름] [인수1] [인수2]....
+// 식으로 한개의 행에 하나의 프로그램 실행 정보를 넣어주면 됩니다.
+                                      
+// 실행 경로와 실행파일의 이름을 합쳐서 255자 이내이어야 하며,                                      
+// 인수는 20 개 이상이 될 수 없습니다.
+               
+1 /bin/ ls -al 123 234 456
+3 /bin/ ls -al /tmp 678 90
+5 /bin/ ls -al /usr abc def
+
+//2 ./ tcp2rx /dev/ttyS05 22549
+//2 ./ tcp2rx /dev/ttyS04 22559
+//2 ./ tcp2rx /dev/ttyS03 22569
+
+//2 ./ udp2rx /dev/ttyS06 22539 192.168.10.2
+//2 ./ udp2rx /dev/ttyS05 22549 192.168.10.2
+//2 ./ udp2rx /dev/ttyS04 22559 192.168.10.2
+//2 ./ udp2rx /dev/ttyS03 22569 192.168.10.2
+  
+//5 . child 1
+//5 ./ child 1 2
+//5 ./ child 1 2 3 
+  
-- 
2.1.4