#include "precompile.h" #include "sp_cfg.h" #include "sp_def.h" //#include "sp_sal.h" #include "sp_dir.h" #include "sp_dbg_export.h" #include "sp_env.h" #include "iniutil.h" #include "strutil.h" #include "memutil.h" #include "shm_mem.h" #include "fileutil.h" #include "SpBase.h" #include "CodeSignVerify.h" #include #include #include #include #include #include #include #define MAX_ENTITY_LEN 33 #ifdef _WIN32 #define MOD_LIB_SUFFIX ".dll" #else #define MOD_LIB_SUFFIX ".so" #endif //_WIN32 #define T_MALLOC_T(type, shm) \ shm ? (type*)shm_malloc(sizeof(type)) : (type*)malloc(sizeof(type)) #define T_MALLOC(size, shm) \ shm ? shm_malloc(size) : malloc(size) #define T_FREE(p, shm) \ shm ? shm_free(p) : free(p) #define T_STRDUP(s, shm) \ shm ? shm_strdup(s) : _strdup(s) #define T_ARRAY_MAKE(n, size, shm) \ shm ? shm_array_make(n, size) : array_make(n, size) std::vector g_arrKill; std::vector g_arrStart; std::vector getKillArr() { return g_arrKill; } std::vector getStartArr() { return g_arrStart; } static int verify_entity_name(const char *name) { const char *p = name; int len = 0; while (*p) { if (!isalnum(*p)) { return FALSE; } len++; if (len > MAX_ENTITY_LEN) return FALSE; p++; } return TRUE; } static int parse_install_state(const char *str) { const struct { int ch; int val; } tbl[] = { {'A', Install_Active}, {'I', Install_Pending}, {'S', Install_SetToStart}, {'F', Install_FailRun}, {'R', Install_RollBack}, {'U', Install_Upgraded}, {'C',Install_Cancelled}, {'W',Install_WaitConfirm}, {'D', Install_Installed}, }; int i; for (i = 0; i < array_size(tbl); ++i) { if (tbl[i].ch == str[0]) { return tbl[i].val; } } return -1; // error } int read_ini_install_state(const char *file, const char *section, const char *key) { char *p = inifile_read_str(file, section, key, ""); int ret = parse_install_state(p); toolkit_free(p); return ret; } static __inline int file_write(FILE *fp, const void *buf, int n) { size_t t = fwrite(buf, n, 1, fp); return t == n ? 0 : Error_IO; } static __inline int file_read(FILE *fp, void *buf, int n) { size_t t = fread(buf, n, 1, fp); return t == n ? 0 : Error_IO; } static void destroy_entity(sp_cfg_shell_entity_t *entity) { if (entity) { if (entity->name) shm_free(entity->name); if (entity->argv) shm_free((void*)entity->argv); if (entity->cmdline) shm_free(entity->cmdline); shm_free(entity); } } static void destroy_module(sp_cfg_shell_module_t* mod) { if (mod) { if (mod->name) shm_free(mod->name); if (mod->author) shm_free(mod->author); if (mod->company) shm_free(mod->company); shm_free(mod); } } static void destroy_sysevent(sp_cfg_shell_sysevent_t *sysevent) { if (sysevent) { if (sysevent->name) shm_free(sysevent->name); if (sysevent->arr_owner_entity) shm_array_free(sysevent->arr_owner_entity); shm_free(sysevent); } } static sp_cfg_path_t *find_path(sp_cfg_t *cfg, const char *path_prefix) { int i; for (i = 0; i < cfg->root_ini->arr_path->nelts; ++i) { sp_cfg_path_t *tpath = ARRAY_IDX(cfg->root_ini->arr_path, i, sp_cfg_path_t*); if (strcmp(tpath->name, path_prefix) == 0) { return tpath; } } return NULL; } static sp_cfg_shell_module_t* find_module(sp_cfg_shell_ini_t *shell, const char *mod_name) { int i; sp_cfg_shell_module_t* mod; ARRAY_FOR_EACH_ENTRY(mod, i, shell->arr_module, sp_cfg_shell_module_t*) { if (_stricmp(mod->name, mod_name) == 0) return mod; } return NULL; } static sp_cfg_shell_entity_t *find_entity(sp_cfg_shell_ini_t *shell, const char *entity_name) { int i; sp_cfg_shell_entity_t *entity; ARRAY_FOR_EACH_ENTRY(entity, i, shell->arr_entity, sp_cfg_shell_entity_t*) { if (_stricmp(entity->name, entity_name) == 0) return entity; } return NULL; } static int read_ini_version(const char *file, const char *section, const char *key, int *major, int *minor, int *revision, int *build) { int n; int ret = -1; char *str = inifile_read_str(file, section, key, ""); if (str) { if (strlen(str) == 0) { if (major) *major = 0; if (minor) *minor = 0; if (revision) *revision = 0; if (build) *build = 0; return 0; } toolkit_free(str); } if (build) { n = inifile_format_read(file, section, key, "%d.%d.%d.%d", major, minor, revision, build); if (n == 4) ret = 0; } else if (revision) { n = inifile_format_read(file, section, key, "%d.%d.%d", major, minor, revision); if (n == 3) ret = 0; } else { n = inifile_format_read(file, section, key, "%d.%d", major, minor); if (n == 2) ret = 0; } return ret; } static int read_ini_str(const char *file, const char *section, const char *key, char **pstr, int shm) { int rc = Error_Param; char *str = inifile_read_str(file, section, key, ""); if (str){ if (shm) { *pstr = shm_strdup(str); rc = 0; toolkit_free(str); } else { *pstr = str; rc = 0; } } return rc; } static int read_ini_date(const char *file, const char *section, const char *key, int *year, int *month, int *day, int *hour, int *minute, int *second, int shm) { int ret; if (second) *second = 0; ret = inifile_format_read(file, section, key, "%d-%d-%d %d:%d", year, month, day, hour, minute); return ret == 5 ? 0 : Error_Param; } static int read_ini_position(const char *file, const char *section, const char *key, float *x, float *y, int shm) { int ret; ret = inifile_format_read(file, section, key, "%f,%f", x, y); return ret == 2 ? 0 : Error_Param; } static int read_ini_path(const char *file, const char *section, const char *key, char **path, int shm) { int rc = read_ini_str(file, section, key, path, shm); if (rc == 0) { char *s = *path; int slen = strlen(s); if (s[slen - 1] == SPLIT_SLASH) s[slen - 1] = 0; } return rc; } static int read_terminal(const char *file, sp_cfg_root_ini_t *root, int shm) { int rc; rc = read_ini_str(file, "Terminal", "TerminalNo", &root->terminal_no, shm); if (rc != 0) return rc; rc = read_ini_str(file, "Terminal", "MachineType", &root->machine_type, shm); if (rc != 0) return rc; rc = read_ini_str(file, "Terminal", "MachineModel", &root->machine_model, shm); rc = read_ini_version(file, "Terminal", "MachineVersion", &root->machine_version.major, &root->machine_version.minor, NULL, NULL); if (rc != 0) return rc; rc = read_ini_str(file, "Terminal", "Site", &root->site, shm); if (rc != 0) return rc; root->screen = inifile_read_int(file, "Terminal", "Screen", -1); if (root->screen == -1) { rc = -1; return rc; } rc = read_ini_position(file, "Terminal", "EnrolGPS", &root->enroll_gps_x, &root->enroll_gps_y, shm); if (rc != 0) return rc; rc = read_ini_str(file, "Terminal", "EnrolAddr", &root->enroll_address, shm); if (rc != 0) return rc; return rc; } static int read_path(const char *file, sp_cfg_root_ini_t *root, int shm) { int rc = 0; array_header_t *arr_kvp = NULL; char *pos; int i; arr_kvp = inifile_read_section_key_all(file, "Path"); if (!arr_kvp) return Error_NotExist; root->arr_path = T_ARRAY_MAKE(arr_kvp->nelts, sizeof(sp_cfg_path_t*), shm); ARRAY_FOR_EACH_ENTRY(pos, i, arr_kvp, char*) { sp_cfg_path_t *path = T_MALLOC_T(sp_cfg_path_t, shm); path->name = T_STRDUP(pos, shm); rc = read_ini_path(file, "Path", pos, &path->path, shm); if (rc != 0) return rc; if (shm) { SHM_ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; } else { ARRAY_PUSH(root->arr_path, sp_cfg_path_t*) = path; } if (strcmp(path->name, "SysRoot") == 0) { root->ref_sysroot_path = path->path; } else if (strcmp(path->name, "ADData") == 0) { root->ref_addata_path = path->path; } else if (strcmp(path->name, "SysLog") == 0) { root->ref_syslog_path = path->path; } else if (strcmp(path->name, "InterLog") == 0) { root->ref_intlog_path = path->path; } else if (strcmp(path->name, "UploadVideo") == 0) { root->ref_uploadvideo_path = path->path; } else if (strcmp(path->name, "UploadPhoto") == 0) { root->ref_uploadphoto_path = path->path; } else if (strcmp(path->name, "LocalVideo") == 0) { root->ref_localvideo_path = path->path; } else if (strcmp(path->name, "Downloads") == 0) { root->ref_downloads_path = path->path; } else if (strcmp(path->name, "Upgraded") == 0) { root->ref_upgraded_path = path->path; } else if (strcmp(path->name, "Temp") == 0) { root->ref_tmp_path = path->path; } else if (strcmp(path->name, "CenterSetting") == 0) { root->ref_centersetting_path = path->path; } } toolkit_array_free2(arr_kvp); return rc; } static sp_cfg_pack_info_t *read_pack_info(const char *file, const char *pack, int shm) { sp_cfg_pack_info_t *pack_info = T_MALLOC_T(sp_cfg_pack_info_t, shm); memset(pack_info, 0, sizeof(sp_cfg_pack_info_t)); pack_info->name = T_STRDUP(pack, shm); pack_info->install_time = inifile_read_int(file, pack, "InstalledDate", 0); pack_info->state = read_ini_install_state(file, pack, "PackState"); return pack_info; } static array_header_t *parse_packs(const char *file, const char *str, int shm) { array_header_t *arr = T_ARRAY_MAKE(-1, sizeof(sp_cfg_pack_info_t*), shm); char *packs = _strdup(str); if (packs) { char *token; const char *seps = " \t,"; token = strtok(packs, seps); while (token != NULL) { sp_cfg_pack_info_t *pack_info = read_pack_info(file, token, shm); if (pack_info) { if (shm) { SHM_ARRAY_PUSH(arr, sp_cfg_pack_info_t*) = pack_info; } else { ARRAY_PUSH(arr, sp_cfg_pack_info_t*) = pack_info; } } token = strtok(NULL, seps); } free(packs); } return arr; } static int load_root_ini(sp_dir_t *dir, sp_cfg_root_ini_t *root, const char *file, int shm) { int rc; rc = read_terminal(file, root, shm); if (rc != 0) return rc; rc = read_path(file, root, shm); return rc; } static int unload_root_ini(sp_cfg_root_ini_t *root, int shm) { int i; if (shm) { shm_free(root->terminal_no); shm_free(root->machine_type); shm_free(root->enroll_address); for (i = 0; i < root->arr_path->nelts; ++i) { sp_cfg_path_t *path = ARRAY_IDX(root->arr_path, i, sp_cfg_path_t*); shm_free(path->name); shm_free(path->path); shm_free(path); } shm_array_free(root->arr_path); } else { free(root->terminal_no); free(root->machine_type); free(root->enroll_address); for (i = 0; i < root->arr_path->nelts; ++i) { sp_cfg_path_t *path = ARRAY_IDX(root->arr_path, i, sp_cfg_path_t*); free(path->name); free(path->path); free(path); } array_free(root->arr_path); } memset(root, 0, sizeof(sp_cfg_root_ini_t)); return 0; } static int load_shell_ini(sp_dir_t *dir, sp_cfg_shell_ini_t *shell, sp_cfg_root_ini_t *root,const char *file, const char *fileVar = NULL) { int rc = -1; int i; array_header_t *arr; char *str; shell->software_version.build = 0; if (NULL != fileVar) rc = read_ini_version(fileVar, "Main", "SoftwareVersion", &shell->software_version.major, &shell->software_version.minor, &shell->software_version.revision, NULL); if (rc != 0) rc = read_ini_version(file, "Main", "SoftwareVersion", &shell->software_version.major, &shell->software_version.minor, &shell->software_version.revision, NULL); if (rc != 0) { sp_dbg_warn("read Main::SoftwareVersion failed!"); return rc; } //read Main:EntityGroupNum int entityGroupNum = inifile_read_int(file, "Main", "EntityGroupNum", 0); //#ifdef _DEBUG // bool bVerifySign = false; //#else // bool bVerifySign = true; //#endif //sp_dbg_warn("dir->cfg_path=%s!",dir->cfg_path); CSimpleStringA strCenterSettingFullPath; strCenterSettingFullPath = dir->cfg_path; if ((stricmp(root->site, "CMB.LIB") == 0) // 行内大堂 || (stricmp(root->site, "CMB.SSB") == 0))// 自助网点 { strCenterSettingFullPath += SPLIT_SLASH_STR "CenterSetting.LAN.ini"; } else if ((stricmp(root->site, "CMB.LSS") == 0) // 生活销售机 || (stricmp(root->site, "CMB.FLB") == 0) // 离行机器 || (stricmp(root->site, "CMB.OSB") == 0) // 外拓PAD || (stricmp(root->site, "CMB.SMM") == 0)) // 商户终端 { strCenterSettingFullPath += SPLIT_SLASH_STR "CenterSetting.DMZ.ini"; } else { strCenterSettingFullPath += SPLIT_SLASH_STR "CenterSetting.DMZ.ini"; } //add (const char*) for fixing string print bug. Gifur sp_dbg_info("strCenterSettingFullPath=%s!",(const char*)strCenterSettingFullPath); //add by zl 20170717,从集中配置读取代码签名开关[VerifyCodeSign] //char cCentersettingPath[MAX_PATH]={0}; int nVerifyCodeSign = 0; //rc = sp_dir_get_path_new(dir, SP_DIR_CENTER_SETTING_INI, NULL, cCentersettingPath, MAX_PATH); //if (rc != 0) //{ // sp_dbg_warn("get centersetting ini path failed!"); // //return rc; //} //else //{ // nVerifyCodeSign = inifile_read_int(cCentersettingPath, "SpBase", "VerifyCodeSign", 0); // sp_dbg_info("get VerifyCodeSign=%d from [%s] ini",nVerifyCodeSign,cCentersettingPath); //} nVerifyCodeSign = inifile_read_int(strCenterSettingFullPath.GetData(), "SpBase", "VerifyCodeSign", 0); sp_dbg_info("get VerifyCodeSign=%d from [%s] ini",nVerifyCodeSign,strCenterSettingFullPath.GetData()); bool bVerifySign = false; if (1 == nVerifyCodeSign) { bVerifySign = true; } else { bVerifySign = false; } if (!bVerifySign) Dbg("ignore code signature"); CVersionInfo shellVerInfo; { // SpBase.dll、SpShell.exe、SpHost.exe代码签名校验 char sal_tmp[MAX_PATH] = { 0 }; const char* sal_files[] = { "SpBase.dll", "SpHost.exe", "SpShell.exe" }; int i; #ifdef _WIN32 CCodeSignVerify ver; for (i = 0; i < sizeof(sal_files) / sizeof(sal_files[0]); i++) { sprintf(sal_tmp, "%s\\%s", dir->bin_path, sal_files[i]); if (bVerifySign) { CSignInfo signInfo; if (!ver.VerifySignature(sal_tmp, signInfo)) { sp_dbg_error("file %s sign verify fail, %s", sal_files[i], (const char*)ver.GetErrorMsg()); return Error_FailVerify; } sp_dbg_info("file %s sign verify pass, signer: %s, sign time: %s, cert hash: %s", sal_files[i], (const char*)signInfo.strSignCertSubject, (const char*)signInfo.dtSignTime.ToTimeString(), (const char*)signInfo.strSignCertHash); if (shell->spbase_sign_cert_hash == NULL) { shell->spbase_sign_cert_hash = shm_strdup(signInfo.strSignCertHash); } else if (stricmp(shell->spbase_sign_cert_hash, signInfo.strSignCertHash) != 0) { sp_dbg_error("sign cert hash not equal, last : [%s], current: [%s]", shell->spbase_sign_cert_hash, (const char*)signInfo.strSignCertHash); return Error_FailVerify; } } CVersionInfo verInfo; if (!ver.GetVersionInfo(sal_tmp, verInfo)) { sp_dbg_warn("read file %s version info fail, %s", sal_files[i], (const char*)ver.GetErrorMsg()); // return rc; } else { // sp_dbg_info("file %s version: %s, description: %s", sal_files[i], // (const char*)verInfo.FileVersion.ToString(), // (const char*)verInfo.strDescription); if (i == sizeof(sal_files) / sizeof(sal_files[0]) - 1) shellVerInfo = verInfo; } } #endif } shell->arr_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*)); // BugFix: replace char* with sp_cfg_shell_module_t* [Gifur@2020422] shell->arr_module = shm_array_make(0, sizeof(sp_cfg_shell_module_t*)); // add intrinsic spshell module { sp_cfg_shell_entity_t *ent = NULL; sp_cfg_shell_module_t *mod = NULL; mod = (sp_cfg_shell_module_t *)shm_malloc(sizeof(sp_cfg_shell_module_t)); memset(mod, 0, sizeof(sp_cfg_shell_module_t)); sp_version_copy(&mod->version, &shell->software_version); mod->author = shm_strdup(shellVerInfo.strAuthorName); mod->company = shm_strdup(shellVerInfo.strCompanyName); mod->name = shm_strdup("SpShell"); mod->mem_trace = inifile_read_int(file, "MemTrace", mod->name, 0); mod->idx = shell->arr_module->nelts; //the first mod id is spshell /*increment netls at the same time*/ SHM_ARRAY_PUSH(shell->arr_module, sp_cfg_shell_module_t*) = mod; ent = (sp_cfg_shell_entity_t *)shm_malloc(sizeof(sp_cfg_shell_entity_t)); memset(ent, 0, sizeof(sp_cfg_shell_entity_t)); ent->mod = mod; ent->name = shm_strdup("SpShell"); ent->idx = shell->arr_entity->nelts; ent->privilege = 1; ent->debug_level = inifile_read_int(file, "Debug", ent->name, 0); SHM_ARRAY_PUSH(shell->arr_entity, sp_cfg_shell_entity_t*) = ent; } int curGroup = 0; do { char sectionName[MAX_PATH] = ""; if (0 == curGroup) sprintf_s(sectionName, MAX_PATH, "Entity"); else sprintf_s(sectionName, MAX_PATH, "Group%d", curGroup); arr = inifile_read_section_key_all(file, sectionName); for (i = 0; i < arr->nelts; ++i) { char tmp[MAX_PATH]; int ret; sp_cfg_shell_entity_t *entity = (sp_cfg_shell_entity_t *)shm_malloc(sizeof(sp_cfg_shell_entity_t)); memset(entity, 0, sizeof(sp_cfg_shell_entity_t)); entity->name = shm_strdup(ARRAY_IDX(arr, i, char*)); if (!verify_entity_name(entity->name)) { rc = Error_Unexpect; sp_dbg_warn("verify entity %s name failed!", entity->name); break; } entity->debug_level = inifile_read_int(file, "Debug", entity->name, 0); if (entity->debug_level > 2 || entity->debug_level < 0) entity->debug_level = 0; ret = inifile_format_read(file, sectionName, entity->name, "%d,%[^,],%x", &entity->privilege, tmp, &entity->devel_id); if (ret == 3) { sp_cfg_shell_module_t *mod; if (str_has_suffix(tmp, MOD_LIB_SUFFIX)) { int len = strlen(tmp); tmp[len-strlen(MOD_LIB_SUFFIX)] = 0; } mod = find_module(shell, tmp); if (!mod) { char sal_tmp[MAX_PATH]; int len = (strstr(tmp, "lib") == tmp) ? 3 : 0; mod = (sp_cfg_shell_module_t *)shm_malloc(sizeof(sp_cfg_shell_module_t)); memset(mod, 0, sizeof(sp_cfg_shell_module_t)); mod->name = shm_strdup(tmp + len); tmp[strlen(tmp)] = '.'; sprintf(sal_tmp, "%s" SPLIT_SLASH_STR "%s", dir->mod_path, tmp); mod->group = curGroup; #ifdef _WIN32 CCodeSignVerify ver; if (bVerifySign) { CSignInfo signInfo; if (!ver.VerifySignature(sal_tmp, signInfo)) { sp_dbg_error("file %s sign verify fail, %s", mod->name, (const char*)ver.GetErrorMsg()); return Error_FailVerify; } sp_dbg_info("file %s sign verify pass, signer: %s, sign time: %s, cert hash: %s", mod->name, (const char*)signInfo.strSignCertSubject, (const char*)signInfo.dtSignTime.ToTimeString(), (const char*)signInfo.strSignCertHash); if (stricmp(shell->spbase_sign_cert_hash, signInfo.strSignCertHash) != 0) { sp_dbg_error("entity %s sign cert hash [%s] not equal to spbase sign cert hash [%s]", mod->name, (const char*)signInfo.strSignCertHash, shell->spbase_sign_cert_hash); return Error_FailVerify; } } CVersionInfo verInfo; if (!ver.GetVersionInfo(sal_tmp, verInfo)) sp_dbg_warn("read file %s version info fail, %s", mod->name, (const char*)ver.GetErrorMsg()); #endif if (rc == 0) { #ifdef _WIN32 mod->author = shm_strdup(verInfo.strAuthorName); mod->company = shm_strdup(verInfo.strCompanyName); mod->version.major = verInfo.FileVersion.GetMajor(); mod->version.minor = verInfo.FileVersion.GetMajor(); mod->version.revision = verInfo.FileVersion.GetRevision(); mod->version.build = verInfo.FileVersion.GetBuild(); #endif mod->mem_trace = inifile_read_int(file, "MemTrace", mod->name, 0); mod->idx = shell->arr_module->nelts; SHM_ARRAY_PUSH(shell->arr_module, sp_cfg_shell_module_t*) = mod; } #ifdef _WIN32 else { sp_dbg_warn("sal verify file %s failed!", sal_tmp); destroy_module(mod); destroy_entity(entity); break; } #endif } entity->mod = mod; entity->idx = shell->arr_entity->nelts; SHM_ARRAY_PUSH(shell->arr_entity, sp_cfg_shell_entity_t*) = entity; sp_dbg_info("entity: %s, id: %d", entity->name, entity->idx); } else { sp_dbg_warn("read entity line failed! bad format!"); rc = Error_Param; destroy_entity(entity); break; } } if (rc != 0) return rc; toolkit_array_free2(arr); } while (curGroup++ < entityGroupNum); shell->arr_sysevent = shm_array_make(0, sizeof(sp_cfg_shell_sysevent_t*)); arr = inifile_read_section_key_all(file, "SysEvent"); for (i = 0; i < arr->nelts; ++i) { char tmp[1024], tmp2[1024], initVar[256]; int ret; sp_cfg_shell_sysevent_t *sysevent = (sp_cfg_shell_sysevent_t *) shm_malloc(sizeof(sp_cfg_shell_sysevent_t)); memset(sysevent, 0, sizeof(sp_cfg_shell_sysevent_t)); sysevent->name = shm_strdup(ARRAY_IDX(arr, i, char*)); sysevent->arr_owner_entity = shm_array_make(0, sizeof(sp_cfg_shell_entity_t*)); ret = inifile_format_read(file, "SysEvent", sysevent->name, "%[^,], \"%[^\"]", tmp, sysevent->init_value); auto varRet = inifile_format_read(fileVar, "SysEvent", sysevent->name, "%[^,], \"%[^\"]", tmp2, initVar); if (varRet > 0) { memcpy(tmp, tmp2, sizeof(tmp)); memcpy(sysevent->init_value, initVar, sizeof(sysevent->init_value)); //如果在shellvar.ini中也能找到该数据,则替换该数值 //情况1:shell.ini添加一个长期有效变量,则在write时在shellvar.ini中生成一个相应的副本。下次读取时从shellvar.ini中读取 //情况2:shell.ini中删除一个长期有效变量,shellvar.ini中并不会相应删除.优先从shell.ini中读取相应变量 } // 为安全起见,准入实体状态强制设为初始状态I if (stricmp(sysevent->name, "EntryPermit") == 0) strcpy(sysevent->init_value, "I"); if (ret > 0) { const char *seps = ";\t "; char *tok = strtok(tmp, seps); while (tok) { sp_cfg_shell_entity_t *owner_entity = find_entity(shell, tok); if (owner_entity) { SHM_ARRAY_PUSH(sysevent->arr_owner_entity, sp_cfg_shell_entity_t*) = owner_entity; } else { sp_dbg_warn("cannot find entity %s", tok); return -1; } tok = strtok(NULL, seps); } sysevent->idx = shell->arr_sysevent->nelts; SHM_ARRAY_PUSH(shell->arr_sysevent, sp_cfg_shell_sysevent_t*) = sysevent; } else { sp_dbg_warn("read SysEvent failed! bad format!"); rc = Error_Param; destroy_sysevent(sysevent); break; } } if (rc != 0) return rc; toolkit_array_free2(arr); //// 改成从Startup配置串直接解析 //str = inifile_read_str(file, "Main", "Startup", ""); // //if (str != NULL) //{ // char *delimit = ","; // int count = 0; // char *arr[32] = {0}; // char *p = strtok(str, delimit); // while(p != NULL) // { // arr[count++] = p; // p = strtok(NULL, delimit); // } // shell->arr_startlist = shm_array_make(count, sizeof(char*)); // for (i = 0; i 0) // { // sp_cfg_shell_entity_t *ent = find_entity(shell, s); // if (ent) // { // char *cmdline = strchr(s, ' '); // if (cmdline) // { // int numargs, numchars; // char **argv = NULL; // *cmdline = 0; // cmdline++; // // str_parse_cmdline(cmdline, NULL, NULL, &numargs, &numchars); // p = shm_malloc(numargs*sizeof(char*) + numchars); // argv = (char**)p; // str_parse_cmdline(cmdline, argv, p + numargs * sizeof(char *), &numargs, &numchars); // ent->argc = numargs; // ent->argv = argv; // if (numargs) // { // ent->cmdline = shm_strdup(cmdline); // } // } // SHM_ARRAY_PUSH(shell->arr_startlist, sp_cfg_shell_entity_t*) = ent; // } // else // { // toolkit_free(str); // return Error_Param; // } // } // else // { // sp_dbg_warn("read Startup failed! bad param format!"); // rc = Error_Param; // } // if (rc != 0) // break; // } // toolkit_free(str); //} //else //{ // sp_dbg_warn("read Startup failed! bad param format!"); // rc = Error_Param; //} //if (rc != 0) // return rc; i = inifile_read_int(file, "Startup", "Number", 0); if (i >= 0) { int n = i; shell->arr_startlist = shm_array_make(i, sizeof(char*)); for (i = 1; i <= n; ++i) { char key[512]; char *s; _itoa(i, key, 10); s = inifile_read_str(file, "Startup", key, ""); if (s) { if (strlen(s)) { int numargs, numchars; char **argv = NULL; char *p; sp_cfg_shell_entity_t *ent; char *cmdline = strchr(s, ' '); if (cmdline) { *cmdline = 0; cmdline++; str_parse_cmdline(cmdline, NULL, NULL, &numargs, &numchars); p = (char*)shm_malloc(numargs*sizeof(char*) + numchars); argv = (char**)p; str_parse_cmdline(cmdline, (char **)p, p + numargs * sizeof(char *), &numargs, &numchars); } ent = find_entity(shell, s); if (ent) { if (cmdline) { ent->argc = numargs; ent->argv = argv; if (numargs) { ent->cmdline = shm_strdup(cmdline); } } SHM_ARRAY_PUSH(shell->arr_startlist, sp_cfg_shell_entity_t*) = ent; } else { sp_dbg_warn("read Startup failed! find startup list [%s] defined entity [%s] fail!", key, s); return Error_Param; } } else { sp_dbg_warn("read Startup failed! startup list [%s] define invalid!", key); rc = Error_Param; } toolkit_free(s); } else { sp_dbg_warn("read Startup failed! startup list [%s] define invalid!", key); rc = Error_Param; } if (rc != 0) break; } } else { sp_dbg_warn("read Startup failed! startup number invalid!"); rc = Error_Param; } if (rc != 0) return rc; shell->shell_debug_level = inifile_read_int(file, "Debug", "SpShell", 0); if (shell->shell_debug_level > 2 || shell->shell_debug_level < 0) shell->shell_debug_level = 0; shell->nConsolePort = inifile_read_int(file, "Main", "ConsolePort", 0); auto killNum = inifile_read_int(file, "killProcess", "Number", 0); g_arrKill.clear(); for (int i = 1; i <= killNum; i++) { char key[512]; char* s; _itoa(i, key, 10); s = inifile_read_str(file, "killProcess", key, ""); if (s && strlen(s) > 0) { g_arrKill.push_back(s); toolkit_free(s); } else { sp_dbg_warn("read kill failed! killProcess list [%s] define invalid!", key); rc = Error_Param; break; } } auto startNum = inifile_read_int(file, "RunScript", "Number", 0); g_arrStart.clear(); for (int i = 1; i <= startNum; i++) { char key[512]; char* s; _itoa(i, key, 10); s = inifile_read_str(file, "RunScript", key, ""); if (s && strlen(s) > 0) { std::string fullPath = std::string(dir->bin_path) + "\\spScript\\" + s; g_arrStart.push_back(fullPath); toolkit_free(s); } else { sp_dbg_warn("read start failed! RunScript list [%s] define invalid!", key); rc = Error_Param; break; } } return rc; } static int unload_shell_ini(sp_cfg_shell_ini_t *shell) { int i; if (shell->arr_entity) { for (i = 0; i< shell->arr_entity->nelts; ++i) { sp_cfg_shell_entity_t *entity = ARRAY_IDX(shell->arr_entity, i, sp_cfg_shell_entity_t*); destroy_entity(entity); } shm_array_free(shell->arr_entity); } if (shell->arr_module) { for (i = 0; i < shell->arr_module->nelts; ++i) { sp_cfg_shell_module_t *mod = ARRAY_IDX(shell->arr_module, i, sp_cfg_shell_module_t*); destroy_module(mod); } shm_array_free(shell->arr_module); } if (shell->arr_sysevent) { for (i = 0; i < shell->arr_sysevent->nelts; ++i) { sp_cfg_shell_sysevent_t *sysevent = ARRAY_IDX(shell->arr_sysevent, i, sp_cfg_shell_sysevent_t*); destroy_sysevent(sysevent); } shm_array_free(shell->arr_sysevent); } if (shell->arr_startlist) { shm_array_free(shell->arr_startlist); } return 0; } static int load_install_ini(sp_dir_t *dir, sp_cfg_install_ini_t *inst, const char *file, int shm) { int rc = 0; array_header_t *arr_section = NULL; int nLastStartTime =0; sp_version_t active_version = { 0 }; rc = read_ini_version(file, "Main", "InstallVersion", &inst->install_version.major, &inst->install_version.minor, &inst->install_version.revision, &inst->install_version.build); if (rc != 0) { sp_dbg_warn("read ini file failed, %s Main::InstallVersion failed!", file); return rc; } // 校验版本目录名与软件版本是否一致 sscanf(strrchr(dir->base_path, SPLIT_SLASH) + 1, "%d.%d.%d.%d", &active_version.major, &active_version.minor, &active_version.revision, &active_version.build); if (sp_version_cmp(&active_version, &inst->install_version) != 0) { sp_dbg_warn("version dir %d.%d.%d.%d not equals install version %d.%d.%d.%d", active_version.major, active_version.minor, active_version.revision, active_version.build, inst->install_version.major, inst->install_version.minor, inst->install_version.revision, inst->install_version.build); return -1; } inst->install_time = inifile_read_int(file, "Main", "CreateDate", 0); if (inst->install_time == 0) { sp_dbg_warn("read ini file failed, %s Main::CreateDate failed", file); return -1; } rc = read_ini_version(file, "Main", "LatterInstallVersion", &inst->latter_install_version.major, &inst->latter_install_version.minor, &inst->latter_install_version.revision, &inst->latter_install_version.build); if (rc != 0) { sp_dbg_warn("read ini file failed, %s Main::LatterInstallVersion failed!", file); return rc; } rc = read_ini_str(file, "Main", "LightPack", &inst->light_packs, shm); if (rc != 0 || inst->light_packs == NULL) { sp_dbg_warn("read ini file failed, %s Main::LightPack", file); return rc; } inst->arr_light_pack = parse_packs(file, inst->light_packs, shm); nLastStartTime = inifile_read_int(file, "Main", "CurrentTime", 0); inst->current_startup_time = y2k_time_now(); { char tmp[32]; sprintf(tmp, "0x%08X", inst->current_startup_time); inifile_write_str(file, "Main", "CurrentTime", tmp); } inst->today_run_count = inifile_read_int(file, "Main", "TodayRunCount", 0); if (inst->today_run_count >=0) { if (y2k_time_is_today(nLastStartTime)) inst->today_run_count++; else inst->today_run_count = 1; inifile_write_int(file, "Main", "TodayRunCount", inst->today_run_count); } inst->total_run_count = inifile_read_int(file, "Main", "TotalRunCount", 0); if (inst->total_run_count >=0) { inst->total_run_count++; inifile_write_int(file, "Main", "TotalRunCount", inst->total_run_count); } // read all history version arr_section = inifile_read_section_all(file); if (arr_section) { int i; inst->arr_version = T_ARRAY_MAKE(0, sizeof(sp_cfg_version_info_t*), shm); for (i = 0; i < arr_section->nelts; ++i) { char *sec = ARRAY_IDX(arr_section, i, char*); if (_stricmp(sec, "Main") != 0) { if (isdigit(sec[0]) && ('.' == sec[1] || '.' == sec[2])) // { // skip light pack sp_cfg_version_info_t *ver_info = T_MALLOC_T(sp_cfg_version_info_t, shm); memset(ver_info, 0, sizeof(sp_cfg_version_info_t)); sscanf(sec, "%d.%d.%d.%d", &ver_info->version.major, &ver_info->version.minor, &ver_info->version.revision, &ver_info->version.build); rc = read_ini_version(file, sec, "PreviousInstallVersion", &ver_info->previous_version.major, &ver_info->previous_version.minor, &ver_info->previous_version.revision, &ver_info->previous_version.build); if (rc != 0) break; rc = read_ini_str(file, sec, "InstallPack", &ver_info->install_pack, shm); if (rc != 0) break; // 轻量安装包没有安装历史 //ver_info->arr_pack = parse_packs(file, ver_info->packs, shm); ver_info->switch_time = inifile_read_int(file, sec, "SwitchOverDate", 0); ver_info->install_state = read_ini_install_state(file, sec, "InstallState"); if (ver_info->install_state == -1) break; if (shm) { SHM_ARRAY_PUSH(inst->arr_version, sp_cfg_version_info_t*) = ver_info; } else { ARRAY_PUSH(inst->arr_version, sp_cfg_version_info_t*) = ver_info; } } } } toolkit_array_free2(arr_section); } else { sp_dbg_warn("read ini file failed, %s, section all failed", file); return -1; } ////////////////////////////// return rc; } static void unload_install_ini(sp_cfg_install_ini_t *inst, int shm) { //... } // c:\run\version\0.0.0.1\bin static int is_valid_version_dir(const char *path) { const char* p = strrchr(path, SPLIT_SLASH) + 1; //sp_version_t ver; if (p) { while (isdigit(*p)) p++; if (*p++ != '.') return FALSE; while (isdigit(*p)) p++; if (*p++ != '.') return FALSE; while (isdigit(*p)) p++; if (*p++ != '.') return FALSE; while (isdigit(*p)) p++; if (*p == '\0') return TRUE; } return FALSE; } static int generate_install_ini(sp_dir_t *dir) { char szIniPath[MAX_PATH] = {0}; sp_version_t active_version = {0}; int rc; sp_version_t last_verion = {0}; int l = -1; char *packs = NULL; rc = sp_dir_get_path(dir, SP_DIR_INSTALL_INI, NULL, szIniPath, MAX_PATH); assert(rc == 0); sscanf(strrchr(dir->base_path, SPLIT_SLASH) + 1, "%d.%d.%d.%d", &active_version.major, &active_version.minor, &active_version.revision, &active_version.build); //// copy install.ini //{ // array_header_t *arr = fileutil_get_sub_dirs_a(dir->root_ver_path); // array_header_t *arr1 = array_make(0, sizeof(const char*)); // // if (arr) { // int i; // for (i = 0; i < arr->nelts; ++i) // { // const char *tmp = (const char*)ARRAY_IDX(arr, i, const char*); // if (_stricmp(tmp, dir->base_path) != 0) { // if (is_valid_version_dir(tmp)) { // ARRAY_PUSH(arr1, const char*) = tmp; // } else { // sp_dbg_warn("caution: %s is not a version dir", tmp); // } // } // } // for (i = 0; i < arr1->nelts; ++i) // { // const char *tmp1 = (const char*)ARRAY_IDX(arr, i, const char*); // sp_version_t ver1; // sscanf(strrchr(tmp1, '\\')+1, "%d.%d.%d.%d", &ver1.major, &ver1.minor, &ver1.revision, &ver1.build); // if (sp_version_cmp(&ver1, &last_verion) > 0) { // l = i; // sp_version_copy(&last_verion, &ver1); // } // } // toolkit_array_free2(arr); // array_free(arr1); // } // // 找到除当前版本外最大的版本,拷贝对应版本Install.ini // if (l != -1) { // char tmp[MAX_PATH]; // char *install_version = NULL; // rc = sp_dir_get_path_version(dir, last_verion.major, last_verion.minor, last_verion.revision, last_verion.build, SP_DIR_INSTALL_INI, NULL, tmp, MAX_PATH); // if (rc != 0) { // sp_dbg_warn("get path version failed!"); // return rc; // } // CopyFileA(tmp, szIniPath, TRUE); // // 设置前一版本安装链 // install_version = inifile_read_str(tmp, "Main", "InstallVersion", ""); // inifile_write_str(tmp, "Main", "LatterInstallVersion", strrchr(dir->base_path, '\\')+1); // inifile_write_str(tmp, install_version, "InstallState", "U"); // toolkit_free(install_version); // } //} // write install.ini main section { char szVer[128]; char szNow[128]; y2k_time_t now; sprintf(szVer, "%d.%d.%d.%d", active_version.major, active_version.minor, active_version.revision, active_version.build); inifile_write_str(szIniPath, "Main", "InstallVersion", szVer); now = y2k_time_now(); sprintf(szNow, "0x%08X", now); inifile_write_str(szIniPath, "Main", "CreateDate", szNow); inifile_write_str(szIniPath, "Main", "LatterInstallVersion", ""); packs = inifile_read_str(szIniPath, "Main", "LightPack", ""); inifile_write_str(szIniPath, "Main", "LightPack", ""); inifile_write_str(szIniPath, "Main", "TotalRunCount", "0"); inifile_write_str(szIniPath, "Main", "TodayRunCount", "0"); inifile_write_str(szIniPath, "Main", "CurrentTime", szNow); if (l != -1) { char szPreVer[128]; sprintf(szPreVer, "%d.%d.%d.%d", last_verion.major, last_verion.minor, last_verion.revision, last_verion.build); inifile_write_str(szIniPath, szVer, "PreviousInstallVersion", szPreVer); } inifile_write_str(szIniPath, szVer, "SwitchOverDate", szNow); inifile_write_str(szIniPath, szVer, "InstallPack", ""); inifile_write_str(szIniPath, szVer, "InstallState", "A"); } // 去掉所有历史版本中轻量安装记录 if (packs) { if (strlen(packs) >0) { char *p = NULL; while((p = strrchr(packs, ',')) != NULL) { *p = 0; WritePrivateProfileSectionA(p+1, NULL, szIniPath); } WritePrivateProfileSectionA(packs, NULL, szIniPath); } toolkit_free(packs); } return 0; } int sp_cfg_create(sp_dir_t *dir, sp_cfg_t **p_cfg) { sp_cfg_t *cfg; int rc = Error_Unexpect; char tmp[MAX_PATH], tmp2[MAX_PATH], *shellvarPath = NULL; cfg = (sp_cfg_t *)shm_malloc(sizeof(sp_cfg_t)); memset(cfg, 0, sizeof(sp_cfg_t)); cfg->root_ini = (sp_cfg_root_ini_t *)shm_malloc(sizeof(sp_cfg_root_ini_t)); memset(cfg->root_ini, 0, sizeof(sp_cfg_root_ini_t)); cfg->shell_ini = (sp_cfg_shell_ini_t *)shm_malloc(sizeof(sp_cfg_shell_ini_t)); memset(cfg->shell_ini, 0, sizeof(sp_cfg_shell_ini_t)); cfg->install_ini = (sp_cfg_install_ini_t*)shm_malloc(sizeof(sp_cfg_install_ini_t)); memset(cfg->install_ini, 0, sizeof(sp_cfg_install_ini_t)); cfg->run_info = (sp_cfg_run_info_t*)shm_malloc(sizeof(sp_cfg_run_info_t)); memset(cfg->run_info, 0, sizeof(sp_cfg_run_info_t)); cfg->run_info->startup_time = y2k_time_now(); rc = sp_dir_get_path(dir, SP_DIR_ROOT_INI, NULL, tmp, MAX_PATH); if (rc != 0) { sp_dbg_warn("get root ini path failed!"); return rc; } rc = load_root_ini(dir, cfg->root_ini, tmp, 1); if (rc != 0) { sp_dbg_warn("load root.ini failed!"); return rc; } cfg->root_ini_path = shm_strdup(tmp); rc = sp_dir_get_path(dir, SP_DIR_SHELL_INI, NULL, tmp, MAX_PATH); if (rc != 0) { sp_dbg_warn("get shell.ini path failed!"); return rc; } rc = sp_dir_get_path(dir, SP_DIR_SHELLVAR_INI, NULL, tmp2, MAX_PATH); if (rc != 0) { sp_dbg_warn("get shellvar.ini path failed!"); return rc; } std::fstream shellVarFile; shellVarFile.open(tmp2, std::ios::in); if (!shellVarFile) { /*cannot found shellVar.ini, then create one.*/ std::ofstream file(tmp2, std::fstream::out); } shellvarPath = tmp2; rc = load_shell_ini(dir, cfg->shell_ini, cfg->root_ini,tmp, shellvarPath); if (rc != 0) { sp_dbg_warn("load shell.ini failed!"); return rc; } cfg->shell_ini_path = shm_strdup(tmp); cfg->shellvar_ini_path = shm_strdup(tmp2); rc = sp_dir_get_path(dir, SP_DIR_INSTALL_INI, NULL, tmp, MAX_PATH); if (rc != 0) { sp_dbg_warn("get install.ini path failed!");; return rc; } cfg->install_ini_path = shm_strdup(tmp); if (!ExistsFileA(tmp)) { rc = generate_install_ini(dir); if (rc != 0) { sp_dbg_warn("generate install.ini failed!"); return rc; } } rc = load_install_ini(dir, cfg->install_ini, tmp, 1); if (rc != 0) { sp_dbg_warn("load install.ini failed!"); return rc; } spinlock_init(&cfg->lock); *p_cfg = cfg; sp_dbg_info("create cfg object ok! %08x, lock = %d", cfg, cfg->lock); rc = 0; return rc; } void sp_cfg_destroy(sp_cfg_t *cfg) { unload_root_ini(cfg->root_ini, 1); unload_shell_ini(cfg->shell_ini); unload_install_ini(cfg->install_ini, 1); shm_free(cfg->root_ini); shm_free(cfg->root_ini_path); shm_free(cfg->shell_ini); shm_free(cfg->shell_ini_path); shm_free(cfg->install_ini); shm_free(cfg); } void sp_cfg_lock(sp_cfg_t *cfg) { spinlock_enter(&cfg->lock, 0); } void sp_cfg_unlock(sp_cfg_t *cfg) { spinlock_leave(&cfg->lock); } sp_cfg_shell_entity_t *sp_cfg_get_entity_by_name(sp_cfg_t *cfg, const char *name) { return find_entity(cfg->shell_ini, name); } sp_cfg_shell_entity_t *sp_cfg_get_entity_by_idx(sp_cfg_t *cfg, int idx) { if (idx >= 0 && idx < cfg->shell_ini->arr_entity->nelts) { return ARRAY_IDX(cfg->shell_ini->arr_entity, idx, sp_cfg_shell_entity_t*); } else { return NULL; } } sp_cfg_shell_entity_t *sp_cfg_get_entity_shell(sp_cfg_t *cfg) { return ARRAY_IDX(cfg->shell_ini->arr_entity, 0, sp_cfg_shell_entity_t*); } sp_cfg_shell_module_t *sp_cfg_get_module_by_name(sp_cfg_t *cfg, const char *name) { return find_module(cfg->shell_ini, name); } sp_cfg_shell_module_t *sp_cfg_get_module_by_idx(sp_cfg_t *cfg, int idx) { if (idx >= 0 && idx < cfg->shell_ini->arr_module->nelts) { return ARRAY_IDX(cfg->shell_ini->arr_module, idx, sp_cfg_shell_module_t*); } else { return NULL; } } sp_cfg_shell_module_t *sp_cfg_get_module_shell(sp_cfg_t *cfg) { return ARRAY_IDX(cfg->shell_ini->arr_module, 0, sp_cfg_shell_module_t*); } sp_cfg_shell_sysevent_t*sp_cfg_get_sysevent(sp_cfg_t *cfg, const char *name) { array_header_t *arr_sysevent = cfg->shell_ini->arr_sysevent; int i; for (i = 0; i < arr_sysevent->nelts; ++i) { sp_cfg_shell_sysevent_t *tmp = ARRAY_IDX(arr_sysevent, i, sp_cfg_shell_sysevent_t *); if (_stricmp(tmp->name, name) == 0) return tmp; } return NULL; } char *sp_cfg_get_path(sp_cfg_t *cfg, const char *path_prefix) { sp_cfg_path_t *path = find_path(cfg, path_prefix); if (path) { return path->path; } return NULL; } int sp_cfg_refresh_debug_level(sp_cfg_t *cfg, sp_cfg_shell_entity_t *cfg_ent) { char tmp[32]; _itoa(cfg_ent->debug_level, tmp, 10); return WritePrivateProfileStringA("Debug", cfg_ent->name, tmp, cfg->shell_ini_path) ? 0 : Error_IO; } int sp_cfg_util_read_root_ini_version(sp_cfg_root_ini_t *ini, int major, int minor, int revision, int build) { char tmp[MAX_PATH]; sp_env_t *env = sp_get_env(); sp_dir_get_path_version(env->dir, major, minor, revision, build, SP_DIR_ROOT_INI, NULL, tmp, MAX_PATH); return load_root_ini(env->dir, ini, tmp, 0); } int sp_cfg_util_free_root_ini(sp_cfg_root_ini_t *ini) { unload_root_ini(ini, 0); return 0; } int sp_cfg_get_devel_id(sp_cfg_t *cfg, int idx) { sp_env_t *env = sp_get_env(); sp_cfg_shell_entity_t *cfg_ent = sp_cfg_get_entity_by_idx(env->cfg, idx); return cfg_ent->devel_id; } sp_cfg_version_info_t* sp_cfg_find_previous_version_info(sp_cfg_t *cfg, const sp_version_t *version) { sp_cfg_version_info_t* ver_info = sp_cfg_find_version_info(cfg, version); if (ver_info) { sp_version_t *previous_version = &ver_info->previous_version; return sp_cfg_find_version_info(cfg, previous_version); } return NULL; } sp_cfg_version_info_t* sp_cfg_find_version_info(sp_cfg_t *cfg, const sp_version_t *version) { int i; for (i = 0; i < cfg->install_ini->arr_version->nelts; ++i) { sp_cfg_version_info_t *ver_info = ARRAY_IDX(cfg->install_ini->arr_version, i, sp_cfg_version_info_t*); //if (sp_version_equal_3(&ver_info->version, version)) if (sp_version_equal(&ver_info->version, version)) return ver_info; } return NULL; } int sp_cfg_is_pack_installed(sp_cfg_t *cfg, const char*pack) { // 先查找轻量表历史 int i; for(i =0; iinstall_ini->arr_light_pack->nelts; i++) { sp_cfg_pack_info_t *pack_info = ARRAY_IDX(cfg->install_ini->arr_light_pack, i, sp_cfg_pack_info_t *); if (stricmp(pack_info->name, pack) == 0) return 0; } // 再查找版本安装包 for (i = 0; i < cfg->install_ini->arr_version->nelts; ++i) { sp_cfg_version_info_t *ver_info = ARRAY_IDX(cfg->install_ini->arr_version, i, sp_cfg_version_info_t*); if (stricmp(ver_info->install_pack, pack) ==0) return 0; } return 1; }