ithewei преди 6 години
родител
ревизия
fb61a63613
променени са 6 файла, в които са добавени 377 реда и са изтрити 147 реда
  1. 0 4
      h.h
  2. 11 0
      hdef.h
  3. 296 0
      hmain.cpp.tmpl
  4. 43 0
      hmain.h
  5. 27 16
      hplatform.h
  6. 0 127
      main.cpp.tmpl

+ 0 - 4
h.h

@@ -8,15 +8,12 @@
 // platform
 #include "hplatform.h"
 
-// c
 #include "hversion.h"
 #include "hdef.h"
 #include "herr.h"
 #include "hlog.h"
 #include "htime.h"
 
-// cpp
-#ifdef __cplusplus
 #include "hstring.h"
 #include "hbuf.h"
 #include "hfile.h"
@@ -34,7 +31,6 @@
 
 #include "singleton.h"
 #include "iniparser.h"
-#endif
 
 #endif  // HW_H_
 

+ 11 - 0
hdef.h

@@ -2,6 +2,11 @@
 #define HW_DEF_H_
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <string>
+#include <map>
 
 typedef unsigned char       uint8;
 typedef unsigned short      uint16;
@@ -25,6 +30,8 @@ typedef void*               handle;
 typedef int (*method_t)(void* userdata);
 typedef void (*procedure_t)(void* userdata);
 
+typedef std::map<std::string, std::string> keyval_t;
+
 #ifndef MAX_PATH
 #define MAX_PATH          260
 #endif
@@ -65,6 +72,10 @@ typedef void (*procedure_t)(void* userdata);
 #define REPEATED
 #endif
 
+#ifndef ABS
+#define ABS(n) ((n) < 0 ? -(n) : (n))
+#endif
+
 #ifndef MAX
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 #endif

+ 296 - 0
hmain.cpp.tmpl

@@ -0,0 +1,296 @@
+#include "h.h"
+
+#include "hmain.h"
+main_ctx_t g_main_ctx;
+
+static int create_pidfile();
+static void delete_pidfile();
+static pid_t getpid_from_pidfile();
+
+int create_pidfile() {
+    FILE* fp = fopen(g_main_ctx.pidfile, "w");
+    if (fp == NULL) {
+        printf("fopen [%s] error: %d\n", g_main_ctx.pidfile, errno);
+        return -10;
+    }
+
+    char pid[16] = {0};
+    snprintf(pid, sizeof(pid), "%d\n", g_main_ctx.pid);
+    fwrite(pid, 1, strlen(pid), fp);
+    fclose(fp);
+
+    atexit(delete_pidfile);
+
+    return 0;
+}
+
+void delete_pidfile() {
+    remove(g_main_ctx.pidfile);
+}
+
+pid_t getpid_from_pidfile() {
+    FILE* fp = fopen(g_main_ctx.pidfile, "r");
+    if (fp == NULL) {
+        //printf("fopen [%s] error: %d\n", g_conf_ctx.pidfile, errno);
+        return -1;
+    }
+    char pid[64];
+    int readbytes = fread(pid, 1, sizeof(pid), fp);
+    if (readbytes <= 0) {
+        printf("fread [%s] bytes=%d\n", g_main_ctx.pidfile, readbytes);
+        return -1;
+    }
+    return atoi(pid);
+}
+
+int main_ctx_init(int argc, char** argv) {
+    g_main_ctx.pid = getpid();
+    char* cwd = getcwd(g_main_ctx.run_path, sizeof(g_main_ctx.run_path));
+    if (cwd == NULL) {
+        printf("getcwd error\n");
+    }
+    //printf("run_path=%s\n", g_main_ctx.run_path);
+    const char* b = argv[0];
+    const char* e = b;
+    while (*e) ++e;
+    --e;
+    while (e >= b) {
+        if (*e == '/' || *e == '\\') {
+            break;
+        }
+        --e;
+    }
+    strncpy(g_main_ctx.program_name, e+1, sizeof(g_main_ctx.program_name));
+    //printf("program_name=%s\n", g_main_ctx.program_name);
+
+    // save arg
+    int i = 0;
+    g_main_ctx.os_argv = argv;
+    g_main_ctx.argc = 0;
+    g_main_ctx.arg_len = 0;
+    for (i = 0; argv[i]; ++i) {
+        g_main_ctx.arg_len += strlen(argv[i]) + 1;
+    }
+    g_main_ctx.argc = i;
+    char* argp = (char*)malloc(g_main_ctx.arg_len);
+    memset(argp, 0, g_main_ctx.arg_len);
+    g_main_ctx.save_argv = (char**)malloc((g_main_ctx.argc+1) * sizeof(char*));
+    for (i = 0; argv[i]; ++i) {
+        g_main_ctx.save_argv[i] = argp;
+        strcpy(g_main_ctx.save_argv[i], argv[i]);
+        argp += strlen(argv[i]) + 1;
+    }
+    g_main_ctx.save_argv[g_main_ctx.argc] = NULL;
+
+    // save env
+    g_main_ctx.os_envp = environ;
+    g_main_ctx.envc = 0;
+    g_main_ctx.env_len = 0;
+    for (i = 0; environ[i]; ++i) {
+        g_main_ctx.env_len += strlen(environ[i]) + 1;
+    }
+    g_main_ctx.envc = i;
+    char* envp = (char*)malloc(g_main_ctx.env_len);
+    memset(envp, 0, g_main_ctx.env_len);
+    g_main_ctx.save_envp = (char**)malloc((g_main_ctx.envc+1) * sizeof(char*));
+    for (i = 0; environ[i]; ++i) {
+        g_main_ctx.save_envp[i] = envp;
+        strcpy(g_main_ctx.save_envp[i], environ[i]);
+        envp += strlen(environ[i]) + 1;
+    }
+    g_main_ctx.save_envp[g_main_ctx.envc] = NULL;
+
+    // parse env
+    for (i = 0; environ[i]; ++i) {
+        char* b = environ[i];
+        char* delim = strchr(b, '=');
+        if (delim == NULL) {
+            continue;
+        }
+        g_main_ctx.env_kv[std::string(b, delim-b)] = std::string(delim+1);
+    }
+
+    /*
+    // print argv and envp
+    printf("---------------arg------------------------------\n");
+    for (auto& pair : g_main_ctx.arg_kv) {
+        printf("%s=%s\n", pair.first.c_str(), pair.second.c_str());
+    }
+    printf("---------------env------------------------------\n");
+    for (auto& pair : g_main_ctx.env_kv) {
+        printf("%s=%s\n", pair.first.c_str(), pair.second.c_str());
+    }
+
+    printf("PWD=%s\n", get_env("PWD"));
+    printf("USER=%s\n", get_env("USER"));
+    printf("HOME=%s\n", get_env("HOME"));
+    printf("LANG=%s\n", get_env("LANG"));
+    printf("TERM=%s\n", get_env("TERM"));
+    printf("SHELL=%s\n", get_env("SHELL"));
+    printf("================================================\n");
+    */
+
+    char logpath[MAX_PATH] = {0};
+    snprintf(logpath, sizeof(logpath), "%s/logs", g_main_ctx.run_path);
+    MKDIR(logpath);
+    snprintf(g_main_ctx.confile, sizeof(g_main_ctx.confile), "%s/etc/%s.conf", g_main_ctx.run_path, g_main_ctx.program_name);
+    snprintf(g_main_ctx.pidfile, sizeof(g_main_ctx.pidfile), "%s/logs/%s.pid", g_main_ctx.run_path, g_main_ctx.program_name);
+    snprintf(g_main_ctx.logfile, sizeof(g_main_ctx.confile), "%s/logs/%s.log", g_main_ctx.run_path, g_main_ctx.program_name);
+    g_main_ctx.confile_parser = NULL;
+
+    g_main_ctx.oldpid = getpid_from_pidfile();
+    create_pidfile();
+
+    return 0;
+}
+
+const char* get_arg(const char* key) {
+    auto iter = g_main_ctx.arg_kv.find(key);
+    if (iter == g_main_ctx.arg_kv.end()) {
+        return NULL;
+    }
+    return iter->second.c_str();
+}
+
+const char* get_env(const char* key) {
+    auto iter = g_main_ctx.env_kv.find(key);
+    if (iter == g_main_ctx.env_kv.end()) {
+        return NULL;
+    }
+    return iter->second.c_str();
+}
+
+#ifdef __unix__
+/*
+ * memory layout
+ * argv[0]\0argv[1]\0argv[n]\0env[0]\0env[1]\0env[n]\0
+ */
+void setproctitle(const char* title) {
+    //printf("proctitle=%s\n", title);
+    memset(g_main_ctx.os_argv[0], 0, g_main_ctx.arg_len + g_main_ctx.env_len);
+    strncpy(g_main_ctx.os_argv[0], title, g_main_ctx.arg_len + g_main_ctx.env_len);
+}
+#endif
+
+// unix short style
+static char options[] = "hvc:td";
+static char detail_options[] = "\
+-h              : print help\n\
+-v              : print version\n\
+-c  confile     : set configure file, default etc/${program}.conf\n\
+-t              : test configure file and exit\n\
+-d              : daemon\n\
+";
+
+void print_version() {
+    printf("%s version %s\n", g_main_ctx.program_name, get_compile_version());
+}
+
+void print_help() {
+    printf("Usage: %s [%s]\n", g_main_ctx.program_name, options);
+    printf("Options:\n%s\n", detail_options);
+}
+
+#define INVALID_OPTION  -1
+#define FLAG_OPTION     1
+#define PARMA_OPTION    2
+int get_option(char opt) {
+    char* p = options;
+    while (*p && *p != opt) ++p;
+    if (*p == '\0')     return INVALID_OPTION;
+    if (*(p+1) == ':')  return PARMA_OPTION;
+    return FLAG_OPTION;
+}
+
+int parse_cmdline(int argc, char** argv) {
+    int i = 1;
+    while (argv[i]) {
+        char* p = argv[i];
+        if (*p != '-') {
+            printf("Invalid argv[%d]: %s\n", i, argv[i]);
+            exit(-10);
+        }
+        while (*++p) {
+            switch (get_option(*p)) {
+            case INVALID_OPTION:
+                printf("Invalid option: '%c'\n", *p);
+                exit(-20);
+            case FLAG_OPTION:
+                g_main_ctx.arg_kv[std::string(p, 1)] = "true";
+                break;
+            case PARMA_OPTION:
+                if (*(p+1) != '\0') {
+                    g_main_ctx.arg_kv[std::string(p, 1)] = p+1;
+                    ++i;
+                    goto next_option;
+                } else if (argv[i+1] != NULL) {
+                    g_main_ctx.arg_kv[std::string(p, 1)] = argv[i+1];
+                    i += 2;
+                    goto next_option;
+                } else {
+                    printf("Option '%c' requires param\n", *p);
+                    exit(-30);
+                }
+            }
+        }
+        ++i;
+next_option:
+        continue;
+    }
+    return 0;
+}
+
+int main(int argc, char** argv) {
+    main_ctx_init(argc, argv);
+
+    parse_cmdline(argc, argv);
+
+/*
+#ifdef __unix__
+    char proctitle[256] = {0};
+    snprintf(proctitle, sizeof(proctitle), "%s: master process", g_main_ctx.program_name);
+    setproctitle(proctitle);
+#endif
+*/
+
+    if (get_arg("h")) {
+        print_help();
+        exit(0);
+    }
+
+    if (get_arg("v")) {
+        print_version();
+        exit(0);
+    }
+
+    const char* confile = get_arg("c");
+    if (confile) {
+        strncpy(g_main_ctx.confile, confile, sizeof(g_main_ctx.confile));
+    }
+
+    //printf("load confile [%s]\n", g_conf_ctx.confile);
+
+    if (get_arg("t")) {
+        exit(0);
+    }
+
+#ifdef __unix__
+    if (get_arg("d")) {
+        // nochdir, noclose
+        int ret = daemon(1, 1);
+        if (ret != 0) {
+            printf("daemon error: %d\n", ret);
+            exit(-10);
+        }
+    }
+#endif
+
+    hlog_set_file(g_main_ctx.logfile);
+    hlog_set_level(LOG_LEVEL_DEBUG);
+    hlogi("version: %s", get_compile_version());
+
+    // add code below
+
+    return 0;
+}
+

+ 43 - 0
hmain.h

@@ -0,0 +1,43 @@
+#ifndef H_MAIN_H_
+#define H_MAIN_H_
+
+#include "hplatform.h"
+#include "hdef.h"
+
+typedef struct main_ctx_s {
+    pid_t   oldpid; // getpid_from_pidfile
+    pid_t   pid;    // getpid
+    char    run_path[MAX_PATH];
+    char    program_name[MAX_PATH];
+
+    int     argc;
+    int     arg_len;
+    char**  os_argv;
+    char**  save_argv;
+
+    int     envc;
+    int     env_len;
+    char**  os_envp;
+    char**  save_envp;
+
+
+    char    confile[MAX_PATH]; // default etc/${program}.conf
+    char    pidfile[MAX_PATH]; // default logs/${program}.pid
+    char    logfile[MAX_PATH]; // default logs/${program}.log
+
+    keyval_t    arg_kv;
+    keyval_t    env_kv;
+    void*       confile_parser;
+} main_ctx_t;
+
+extern main_ctx_t g_main_ctx;
+
+int main_ctx_init(int argc, char** argv);
+const char* get_arg(const char* key);
+const char* get_env(const char* key);
+
+#ifdef __unix__
+void setproctitle(const char* title);
+#endif
+
+#endif // H_MAIN_H_

+ 27 - 16
hplatform.h

@@ -1,31 +1,33 @@
 #ifndef HW_PLATFORM_H_
 #define HW_PLATFORM_H_
 
-#include <sys/types.h>
-
-#ifndef _MSC_VER
-#include <sys/time.h>  // for gettimeofday
-
-#include <pthread.h>
-
-#include <strings.h>
-#define stricmp     strcasecmp
-#define strnicmp    strncasecmp
-#endif
-
 #ifdef _WIN32
-    #ifndef WIN32_LEAN_AND_MEAN
     #define WIN32_LEAN_AND_MEAN
-    #endif
+    #define _CRT_SECURE_NO_WARNINGS
+    #define _CRT_NONSTDC_NO_DEPRECATE
     #include <winsock2.h>
     #include <windows.h>
+    #include <direct.h> // for mkdir,rmdir,chdir,getcwd
 
     #define strcasecmp stricmp
     #define strncasecmp strnicmp
+#else
+    #include <unistd.h> // for daemon
+    #include <dirent.h> // for mkdir,rmdir,chdir,getcwd
+    #include <sys/time.h>  // for gettimeofday
+
+    #include <pthread.h>
+
+    #include <strings.h>
+
+    #define stricmp     strcasecmp
+    #define strnicmp    strncasecmp
 #endif
 
-#ifdef __unix__
-    #include <unistd.h>
+#ifdef _MSC_VER
+    typedef int pid_t;
+    typedef int gid_t;
+    typedef int uid_t;
 #endif
 
 #ifdef __GNUC__
@@ -34,4 +36,13 @@
     #define GNUC_ALIGN(n)
 #endif
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef __unix__
+#define MKDIR(dir) mkdir(dir, 0x755)
+#else
+#define MKDIR(dir) mkdir(dir)
+#endif
+
 #endif  // HW_PLATFORM_H_

+ 0 - 127
main.cpp.tmpl

@@ -1,127 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "h.h"
-#ifdef _WIN32
-#include "win32_getopt.h"
-#endif
-
-void pexit(int code) {
-    printf("Exit with code %d.\n", code);
-    exit(code);
-}
-
-typedef struct arg_s {
-    string  cmd;
-    string  confile;    // -c
-    string  logfile;
-    int     port;       // -p
-    int     daemon;     // -d
-} arg_t;
-arg_t g_arg;
-
-const char* options = "hvc:p:d";
-const char* options_descr = "\
-Options:\n\
--h                      Print help\n\
--v                      Print version\n\
--c confile              Configure file\n\
--p port                 Listen port\n\
--d                      Daemon\n\
-";
-
-string version() {
-    return asprintf("%s version %s", g_arg.cmd.c_str(), get_compile_version());
-}
-
-string usage() {
-    return asprintf("Usage: %s [%s]", g_arg.cmd.c_str(), options);
-}
-
-void print_help() {
-    puts(usage().c_str());
-    puts(options_descr);
-    puts(version().c_str());
-}
-
-bool parse_command_line(int argc, char** argv) {
-    int opt = -1;
-    while ((opt = getopt(argc, argv, options)) != -1) {
-        switch (opt) {
-            case 'h': {
-                print_help();
-                pexit(0);
-            }
-            break;
-            case 'v': {
-                puts(version().c_str());
-                pexit(0);
-            }
-            break;
-            case 'c': {
-                g_arg.confile = optarg;
-            }
-            break;
-            case 'p': {
-                g_arg.port = atoi(optarg);
-            }
-            break;
-            case 'd': {
-                g_arg.daemon = 1;
-            }
-            break;
-            default: {
-                puts("Unrecognized option!");
-                pexit(-10);
-            }
-            break;
-        }
-    }
-
-    return true;
-}
-
-int main(int argc, char** argv) {
-    string strCmd((const char*)argv[0]);
-    g_arg.cmd = filename(strCmd);
-    //g_arg.confile = g_arg.cmd + ".conf";
-    g_arg.logfile = g_arg.cmd + ".log";
-    g_arg.port = 0;
-    g_arg.daemon = 0;
-
-    hlog_set_file(g_arg.logfile.c_str());
-    hlog_set_level(LOG_LEVEL_INFO);
-    hlogi("%s", version().c_str());
-
-    if (!parse_command_line(argc, argv)) {
-        printf("Parse command line error, please use -h to get help.\n");
-        pexit(-10);
-    }
-
-    IniParser ini;
-    if (!g_arg.confile.empty()) {
-        int iRet = ini.LoadFromFile(g_arg.confile.c_str());
-        if (iRet != 0) {
-            printf("Load confile [%s] failed: %d\n", g_arg.confile.c_str(), iRet);
-            pexit(-20);
-        }
-    }
-
-    if (g_arg.port == 0) {
-        g_arg.port = atoi(ini.GetValue("port").c_str());
-    }
-    if (g_arg.port == 0) {
-        puts("Please config listen port!");
-        pexit(-30);
-    }
-
-#ifdef __unix__
-    if (g_arg.daemon) {
-        daemon(1, 1);
-    }
-#endif
-
-    pexit(0);
-}
-