// ----------------------------------------- bool IniFile::readNext() { if (fStream.eof()) return false; try { fStream.readLine(currLine,256); }catch(StreamException &) { return false; } // find end of value name and null terminate char *nend = strstr(currLine,"="); if (nend) { *nend = 0; valueStr = trimstr(nend+1); }else valueStr = NULL; nameStr = trimstr(currLine); return true; }
proxy_behavior cproxy_parse_behavior(char *behavior_str, proxy_behavior behavior_default) { // These are the default proxy behaviors. // struct proxy_behavior behavior = behavior_default; if (behavior_str == NULL || strlen(behavior_str) <= 0) { return behavior; } // Parse the key-value behavior_str, to override the defaults. // char *buff = trimstrdup(behavior_str); char *next = buff; while (next != NULL) { char *key_val = trimstr(strsep(&next, ",")); if (key_val != NULL) { cproxy_parse_behavior_key_val_str(key_val, &behavior); } } free(buff); return behavior; }
/* Deletes blanks and whitespaces of a given input line */ int main() { int length; /* length of the current word */ char line[MAXLENGTH]; /* Current line */ while ( (length = trimstr(line, MAXLENGTH)) > 0 ) printf("The line '%s' has length: %d\n", line, length); return 0; }
static void edit_lang(int nn) { int i1; languagerec *n; out->Cls(); bool done = false; int cp = 0; n = &(languages[nn]); out->SetColor(Scheme::NORMAL); Printf("Language name : %s\n", n->name); Printf("Data Directory : %s\n", n->dir); Printf("Menu Directory : %s\n", n->mdir); out->SetColor(Scheme::PROMPT); Puts("\n<ESC> when done.\n\n"); out->SetColor(Scheme::NORMAL); do { out->GotoXY(17, cp); switch (cp) { case 0: editline(n->name, sizeof(n->name) - 1, ALL, &i1, ""); trimstr(n->name); #ifdef WHY ss = strchr(n->name, ' '); if (ss) { *ss = 0; } #endif Puts(n->name); Puts(" "); break; case 1: editline(n->dir, 60, EDITLINE_FILENAME_CASE, &i1, ""); trimstrpath(n->dir); Puts(n->dir); break; case 2: editline(n->mdir, 60, EDITLINE_FILENAME_CASE, &i1, ""); trimstrpath(n->mdir); Puts(n->mdir); break; } cp = GetNextSelectionPosition(0, 2, cp, i1); if (i1 == DONE) { done = true; } } while (!done); }
/** * Authenticate a user's credentials * Return 1 if authenticated, 0 if not */ int ftserve_check_user(char*user, char*pass) { char username[MAXSIZE]; char password[MAXSIZE]; char *pch; char buf[MAXSIZE]; char *line = NULL; size_t num_read; size_t len = 0; FILE* fd; int auth = 0; fd = fopen(".auth", "r"); if (fd == NULL) { perror("file not found"); exit(1); } while ((num_read = getline(&line, &len, fd)) != -1) { memset(buf, 0, MAXSIZE); strcpy(buf, line); pch = strtok (buf," "); strcpy(username, pch); if (pch != NULL) { pch = strtok (NULL, " "); strcpy(password, pch); } // remove end of line and whitespace trimstr(password, (int)strlen(password)); if ((strcmp(user,username)==0) && (strcmp(pass,password)==0)) { auth = 1; break; } } free(line); fclose(fd); return auth; }
/** Note: the key and val param buffers are modified. */ void cproxy_parse_behavior_key_val(char *key, char *val, proxy_behavior *behavior) { uint32_t ms = 0; uint32_t x = 0; bool ok = false; assert(behavior != NULL); if (key != NULL && val != NULL) { key = trimstr(key); val = trimstr(val); if (wordeq(key, "cycle")) { ok = safe_strtoul(val, &behavior->cycle); } else if (wordeq(key, "downstream_max") || wordeq(key, "concurrency")) { ok = safe_strtoul(val, &behavior->downstream_max); } else if (wordeq(key, "downstream_conn_max")) { ok = safe_strtoul(val, &behavior->downstream_conn_max); } else if (wordeq(key, "weight") || wordeq(key, "downstream_weight")) { ok = safe_strtoul(val, &behavior->downstream_weight); } else if (wordeq(key, "retry") || wordeq(key, "downstream_retry")) { ok = safe_strtoul(val, &behavior->downstream_retry); } else if (wordeq(key, "protocol") || wordeq(key, "downstream_protocol")) { if (wordeq(val, "ascii") || wordeq(val, "memcached-ascii") || wordeq(val, "membase-ascii")) { behavior->downstream_protocol = proxy_downstream_ascii_prot; ok = true; } else if (wordeq(val, "binary") || wordeq(val, "memcached-binary") || wordeq(val, "membase-binary")) { behavior->downstream_protocol = proxy_downstream_binary_prot; ok = true; } else { if (settings.verbose > 1) { moxi_log_write("unknown behavior prot: %s\n", val); } } } else if (wordeq(key, "timeout") || wordeq(key, "downstream_timeout") || wordeq(key, "downstream_conn_timeout")) { ok = safe_strtoul(val, &ms); behavior->downstream_timeout.tv_sec = floor(ms / 1000.0); behavior->downstream_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "downstream_conn_queue_timeout")) { ok = safe_strtoul(val, &ms); behavior->downstream_conn_queue_timeout.tv_sec = floor(ms / 1000.0); behavior->downstream_conn_queue_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "wait_queue_timeout")) { ok = safe_strtoul(val, &ms); behavior->wait_queue_timeout.tv_sec = floor(ms / 1000.0); behavior->wait_queue_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "connect_timeout")) { ok = safe_strtoul(val, &ms); behavior->connect_timeout.tv_sec = floor(ms / 1000.0); behavior->connect_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "auth_timeout")) { ok = safe_strtoul(val, &ms); behavior->auth_timeout.tv_sec = floor(ms / 1000.0); behavior->auth_timeout.tv_usec = (ms % 1000) * 1000; } else if (wordeq(key, "time_stats")) { ok = safe_strtoul(val, &x); behavior->time_stats = x; } else if (wordeq(key, "mcs_opts")) { if (strlen(val) < sizeof(behavior->mcs_opts)) { strcpy(behavior->mcs_opts, val); ok = true; } } else if (wordeq(key, "connect_max_errors")) { ok = safe_strtoul(val, &behavior->connect_max_errors); } else if (wordeq(key, "connect_retry_interval")) { ok = safe_strtoul(val, &behavior->connect_retry_interval); } else if (wordeq(key, "front_cache_max")) { ok = safe_strtoul(val, &behavior->front_cache_max); } else if (wordeq(key, "front_cache_lifespan")) { ok = safe_strtoul(val, &behavior->front_cache_lifespan); } else if (wordeq(key, "front_cache_spec")) { if (strlen(val) < sizeof(behavior->front_cache_spec)) { strcpy(behavior->front_cache_spec, val); ok = true; } } else if (wordeq(key, "front_cache_unspec")) { if (strlen(val) < sizeof(behavior->front_cache_unspec)) { strcpy(behavior->front_cache_unspec, val); ok = true; } } else if (wordeq(key, "key_stats_max")) { ok = safe_strtoul(val, &behavior->key_stats_max); } else if (wordeq(key, "key_stats_lifespan")) { ok = safe_strtoul(val, &behavior->key_stats_lifespan); } else if (wordeq(key, "key_stats_spec")) { if (strlen(val) < sizeof(behavior->key_stats_spec)) { strcpy(behavior->key_stats_spec, val); ok = true; } } else if (wordeq(key, "key_stats_unspec")) { if (strlen(val) < sizeof(behavior->key_stats_unspec)) { strcpy(behavior->key_stats_unspec, val); ok = true; } } else if (wordeq(key, "optimize_set")) { if (strlen(val) < sizeof(behavior->optimize_set)) { strcpy(behavior->optimize_set, val); ok = true; } } else if (wordeq(key, "usr")) { if (strlen(val) < sizeof(behavior->usr)) { strcpy(behavior->usr, val); ok = true; } } else if (wordeq(key, "pwd")) { if (strlen(val) < sizeof(behavior->pwd)) { strcpy(behavior->pwd, val); ok = true; } } else if (wordeq(key, "host")) { if (strlen(val) < sizeof(behavior->host)) { strcpy(behavior->host, val); ok = true; } } else if (wordeq(key, "port")) { ok = safe_strtol(val, &behavior->port); } else if (wordeq(key, "bucket")) { if (strlen(val) < sizeof(behavior->bucket)) { strcpy(behavior->bucket, val); ok = true; } } else if (wordeq(key, "port_listen")) { ok = safe_strtol(val, &behavior->port_listen); } else if (wordeq(key, "default_bucket_name")) { if (strlen(val) < sizeof(behavior->default_bucket_name)) { strcpy(behavior->default_bucket_name, val); ok = true; } } else if (key[0] == '#') { // Comment. ok = true; } else { if (settings.verbose > 1) { moxi_log_write("ERROR: unknown behavior key: %s\n", key); } } } if (ok == false) { moxi_log_write("ERROR: config error in key: %s value: %s\n", key, val); } }
int cproxy_init_string(char *cfg_str, proxy_behavior behavior, int nthreads) { /* cfg looks like "local_port=host:port,host:port;local_port=host:port" * like "11222=memcached1.foo.net:11211" This means local port 11222 * will be a proxy to downstream memcached server running at * host memcached1.foo.net on port 11211. */ if (cfg_str== NULL || strlen(cfg_str) <= 0) { return 0; } char *buff; char *next; char *proxy_name = "default"; char *proxy_sect; char *proxy_port_str; int proxy_port; if (settings.verbose > 1) { cproxy_dump_behavior(&behavior, "init_string", 2); } buff = trimstrdup(cfg_str); next = buff; while (next != NULL) { proxy_sect = strsep(&next, ";"); proxy_port_str = trimstr(strsep(&proxy_sect, "=")); if (proxy_sect == NULL) { moxi_log_write("bad moxi config, missing =\n"); exit(EXIT_FAILURE); } proxy_port = atoi(proxy_port_str); if (proxy_port <= 0) { moxi_log_write("missing proxy port\n"); exit(EXIT_FAILURE); } proxy_sect = trimstr(proxy_sect); int behaviors_num = 1; // Number of servers. for (char *x = proxy_sect; *x != '\0'; x++) { if (*x == ',') { behaviors_num++; } } proxy_behavior_pool behavior_pool; memset(&behavior_pool, 0, sizeof(proxy_behavior_pool)); behavior_pool.base = behavior; behavior_pool.num = behaviors_num; behavior_pool.arr = calloc(behaviors_num, sizeof(proxy_behavior)); if (behavior_pool.arr != NULL) { for (int i = 0; i < behaviors_num; i++) { behavior_pool.arr[i] = behavior; } proxy_main *m = cproxy_gen_proxy_main(behavior, nthreads, PROXY_CONF_TYPE_STATIC); if (m == NULL) { moxi_log_write("could not alloc proxy_main\n"); exit(EXIT_FAILURE); } proxy *p = cproxy_create(m, proxy_name, proxy_port, proxy_sect, 0, // config_ver. &behavior_pool, nthreads); if (p != NULL) { pthread_mutex_lock(&m->proxy_main_lock); p->next = m->proxy_head; m->proxy_head = p; pthread_mutex_unlock(&m->proxy_main_lock); int n = cproxy_listen(p); if (n > 0) { if (settings.verbose > 1) { moxi_log_write("moxi listening on %d with %d conns\n", proxy_port, n); } } else { moxi_log_write("moxi error -- port %d unavailable?\n", proxy_port); exit(EXIT_FAILURE); } } else { moxi_log_write("could not alloc proxy\n"); exit(EXIT_FAILURE); } free(behavior_pool.arr); } else { moxi_log_write("could not alloc behaviors\n"); exit(EXIT_FAILURE); } } free(buff); return 0; }
static int tmpl_key(struct _select_def *conf, int key) { int oldmode; switch (key) { case 'a' : tmpl_check_limit(template_num); tmpl_add(); return SHOW_DIRCHANGE; break; case 'd' : { char ans[3]; getdata(t_lines - 1, 0, "确实要删除吗(Y/N)? [N]: ", ans, sizeof(ans), DOECHO, NULL, true); if (ans[0] == 'Y' || ans[0] == 'y') { int i; deepfree(ptemplate + conf->pos - 1, currboard->filename); template_num--; for (i=conf->pos-1; i<template_num; i++) memcpy(ptemplate+i, ptemplate+i+1, sizeof(struct a_template)); ptemplate[template_num].tmpl = NULL; ptemplate[template_num].cont = NULL; tmpl_save(); } if (template_num > 0) return SHOW_DIRCHANGE; else return SHOW_QUIT; } break; case 'c': do { extern bool in_do_sendmsg; extern int super_select_board(char *bname); int ret; char bname[STRLEN] = ""; move(0,0); clrtoeol(); prints("%s","复制到讨论区 [ \033[1;32mSPACE/TAB\033[m - 自动补全, \033[1;32mESC\033[m - 退出 ]"); move(1,0); clrtoeol(); prints("请输入讨论区名称 [\033[1;32m%s\033[m]: ",currboard->filename); make_blist(0, 3); in_do_sendmsg=1; ret = namecomplete(NULL, bname); in_do_sendmsg=0; CreateNameList(); /* free list memory. */ if (ret == KEY_ESC) { /* noop */ } else if (!*bname || !strcmp(bname, currboard->filename)) { /* copy to current board */ tmpl_check_BM(currboard->filename); /* sanity check, how about stick here when deposing? */ tmpl_check_limit(template_num); if (tmpl_copy(conf->pos)) tmplcp_sorry(); else tmplcp_success(); } else { /* copy to another board */ struct a_template *ptemp; int temp_num = tmpl_init_ex(0, bname, &ptemp); if (temp_num >= 0) { tmpl_check_BM(bname); /* sanity check */ tmpl_check_limit(temp_num); if (tmpl_copy_to_board(bname, &ptemp, &temp_num, conf->pos)) tmplcp_sorry(); else tmplcp_success(); tmpl_free_ex(&ptemp, temp_num); } } } while (0); return SHOW_DIRCHANGE; /* etnlegend, 2006.05.19, move templates... */ case 'm': do { struct a_template temp; char ans[4]; int i,pos; getdata(t_lines-1,0,"请输入希望移动到的位置序号: ",ans,4,DOECHO,NULL,true); trimstr(ans); if (!isdigit(ans[0])) break; pos=atoi(ans); pos=((pos<1)?1:((pos>template_num)?template_num:pos)); if (pos==conf->pos) break; memcpy(&temp,&ptemplate[conf->pos-1],sizeof(struct a_template)); if (pos>conf->pos) { for (i=(conf->pos-1); i<(pos-1); i++) memcpy(&ptemplate[i],&ptemplate[i+1],sizeof(struct a_template)); } else { for (i=(conf->pos-1); i>(pos-1); i--) memcpy(&ptemplate[i],&ptemplate[i-1],sizeof(struct a_template)); } memcpy(&ptemplate[pos-1],&temp,sizeof(struct a_template)); tmpl_save(); } while (0); return SHOW_DIRCHANGE; /* END - etnlegend, 2006.05.19, move templates ... */ case 't' : { char newtitle[60]; strcpy(newtitle, ptemplate[conf->pos-1].tmpl->title); getdata(t_lines - 1, 0, "新名称: ", newtitle, 50, DOECHO, NULL, false); if (newtitle[0] == '\0' || newtitle[0]=='\n' || ! strcmp(newtitle,ptemplate[conf->pos-1].tmpl->title)) return SHOW_REFRESH; strncpy(ptemplate[conf->pos-1].tmpl->title, newtitle, 50); ptemplate[conf->pos-1].tmpl->title[49]='\0'; tmpl_save(); return SHOW_REFRESH; } break;/* case 'z' : { char newtitle[30]; strcpy(newtitle, ptemplate[conf->pos-1].tmpl->title_prefix); getdata(t_lines - 1, 0, "请输入此模板的文章标题前缀: ", newtitle, 20, DOECHO, NULL, false); if( newtitle[0] == '\0' || newtitle[0]=='\n' || ! strcmp(newtitle,ptemplate[conf->pos-1].tmpl->title_prefix) ) return SHOW_REFRESH; strncpy(ptemplate[conf->pos-1].tmpl->title_prefix, newtitle, 20); ptemplate[conf->pos-1].tmpl->title_prefix[19]='\0'; tmpl_save(); return SHOW_REFRESH; }*/ case 'f' : { char filepath[STRLEN]; int oldmode; oldmode = uinfo.mode; modify_user_mode(EDITUFILE); if (ptemplate[conf->pos-1].tmpl->filename[0] == '\0') { setbfile(filepath, currboard->filename, ""); if (GET_POSTFILENAME(ptemplate[conf->pos-1].tmpl->filename, filepath) != 0) { clear(); move(3,0); prints("创建模板文件失败!"); pressanykey(); return SHOW_REFRESH; } tmpl_save(); } setbfile(filepath, currboard->filename, ptemplate[conf->pos-1].tmpl->filename); vedit(filepath,0,NULL,NULL,0); modify_user_mode(oldmode); return SHOW_REFRESH; } case 's' : { char filepath[STRLEN]; setbfile(filepath, currboard->filename, ptemplate[conf->pos-1].tmpl->filename); clear(); ansimore(filepath,1); return SHOW_REFRESH; } case 'b' : { if (ptemplate[conf->pos-1].tmpl->flag & TMPL_BM_FLAG) ptemplate[conf->pos-1].tmpl->flag &= ~TMPL_BM_FLAG ; else ptemplate[conf->pos-1].tmpl->flag |= TMPL_BM_FLAG; tmpl_save(); return SHOW_REFRESH; } case 'i' : { char newtitle[STRLEN]; strcpy(newtitle, ptemplate[conf->pos-1].tmpl->title_tmpl); getdata(t_lines - 1, 0, "新文章标题: ", newtitle, STRLEN, DOECHO, NULL, false); if (newtitle[0] == '\0' || newtitle[0]=='\n' || ! strcmp(newtitle,ptemplate[conf->pos-1].tmpl->title_tmpl)) return SHOW_REFRESH; strncpy(ptemplate[conf->pos-1].tmpl->title_tmpl, newtitle, STRLEN); ptemplate[conf->pos-1].tmpl->title_tmpl[STRLEN-1]='\0'; tmpl_save(); return SHOW_REFRESH; } case 'x' : { clear(); move(2,0); prints("此模版的标题设置为"); move(4,0); prints("%s",ptemplate[conf->pos-1].tmpl->title_tmpl); pressanykey(); return SHOW_REFRESH; } /* case 'h': { clear(); move(1,0); prints(" x : 查看标题格式\n"); prints(" i : 修改标题格式"); pressanykey(); return SHOW_REFRESH; } */ case 'l': /* by pig2532 on 2005.12.01 */ oldmode = uinfo.mode; show_allmsgs(); modify_user_mode(oldmode); return SHOW_REFRESH; case 'w': /* by pig2532 on 2005-12-1 */ oldmode = uinfo.mode; if (!HAS_PERM(getCurrentUser(), PERM_PAGE)) break; s_msg(); modify_user_mode(oldmode); return SHOW_REFRESH; case 'u': /* by pig2532 on 2005-12-1 */ clear(); oldmode = uinfo.mode; modify_user_mode(QUERY); t_query(NULL); modify_user_mode(oldmode); return SHOW_REFRESH; case 'U': /* pig2532 2005.12.10 */ board_query(); return SHOW_REFRESH; default : break; } return SHOW_CONTINUE; }
/** The cfg_str looks like... * * apikey=jidname@jhostname%jpassword,config=config,host=host * or... * jidname@jhostname%jpassword,config=config,host=host * * Only the apikey is needed, so it can also look like... * * jidname@jhostname%jpassword */ int cproxy_init_agent(char *cfg_str, proxy_behavior behavior, int nthreads) { init_extensions(); if (cfg_str == NULL) { fprintf(stderr, "missing cfg\n"); exit(EXIT_FAILURE); } int cfg_len = strlen(cfg_str); if (cfg_len <= 0) { fprintf(stderr, "empty cfg\n"); exit(EXIT_FAILURE); } char *buff; if (strncmp(cfg_str, "apikey=", 7) == 0) { buff = trimstrdup(cfg_str); } else { buff = calloc(cfg_len + 50, sizeof(char)); if (buff != NULL) { snprintf(buff, cfg_len + 50, "apikey=%s", cfg_str); } buff = trimstr(buff); } char *next = buff; int rv = 0; while (next != NULL) { char *jid = NULL; char *jpw = NULL; char *jpwmem = NULL; char *config = NULL; char *host = NULL; char *cur = trimstr(strsep(&next, ";")); while (cur != NULL) { char *key_val = trimstr(strsep(&cur, ",\r\n")); if (key_val != NULL) { char *key = trimstr(strsep(&key_val, "=")); char *val = trimstr(key_val); bool handled = true; if (key != NULL && val != NULL) { if (wordeq(key, "apikey")) { jid = strsep(&val, "%"); jpw = val; } else if (wordeq(key, "config")) { config = val; } else if (wordeq(key, "host")) { host = val; } else { handled = false; } } else { handled = false; } if (handled == false && key != NULL && key[0] != '#' && key[0] != '\0') { if (settings.verbose > 0) { fprintf(stderr, "unknown configuration key: %s\n", key); } } } } if (jid == NULL || strlen(jid) <= 0) { fprintf(stderr, "missing conflate id\n"); exit(EXIT_FAILURE); } if (jpw == NULL) { // Handle if jid/jpw is in user:password@fqdn format // instead of user@fqdn%password format. // char *colon = strchr(jid, ':'); char *asign = strchr(jid, '@'); if (colon != NULL && asign != NULL && asign > colon) { *asign = '\0'; jpw = jpwmem = strdup(colon + 1); *asign = '@'; do { *colon = *asign; colon++; asign++; } while (*asign != '\0'); *colon = '\0'; } } if (jpw == NULL || strlen(jpw) <= 0) { fprintf(stderr, "missing conflate password\n"); exit(EXIT_FAILURE); } int config_alloc = 0; if (config == NULL) { config_alloc = strlen(jid) + 100; config = calloc(config_alloc, 1); if (config != NULL) { snprintf(config, config_alloc, CONFLATE_DB_PATH "/%s.cfg", jid); } else { fprintf(stderr, "conflate config buf alloc\n"); exit(EXIT_FAILURE); } } if (settings.verbose > 1) { fprintf(stderr, "cproxy_init jid %s\n", jid); } if (cproxy_init_agent_start(jid, jpw, config, host, behavior, nthreads) != NULL) { rv++; } if (config_alloc > 0 && config != NULL) { free(config); } if (jpwmem) { free(jpwmem); } } free(buff); return rv; }
static void cproxy_on_new_config(void *data0, void *data1) { work_collect *completion = data0; proxy_main *m = completion->data; assert(m); kvpair_t *kvs = data1; assert(kvs); assert(is_listen_thread()); m->stat_configs++; uint32_t max_config_ver = 0; for (proxy *p = m->proxy_head; p != NULL; p = p->next) { pthread_mutex_lock(&p->proxy_lock); if (max_config_ver < p->config_ver) { max_config_ver = p->config_ver; } pthread_mutex_unlock(&p->proxy_lock); } uint32_t new_config_ver = max_config_ver + 1; if (settings.verbose > 2) { fprintf(stderr, "conc new_config_ver %u\n", new_config_ver); } // The kvs key-multivalues look roughly like... // // pool-customer1-a // svrname3 // pool-customer1-b // svrname1 // svrname2 // svr-svrname1 // host=mc1.foo.net // port=11211 // weight=1 // bucket=buck1 // usr=test1 // pwd=password // svr-svrnameX // host=mc2.foo.net // port=11211 // behavior-customer1-a // wait_queue_timeout=1000 // downstream_max=10 // behavior-customer1-b // wait_queue_timeout=1000 // downstream_max=10 // pool_drain-customer1-b // svrname1 // svrname3 // pools // customer1-a // customer1-b // bindings // 11221 // 11331 // char **pools = get_key_values(kvs, "pools"); char **bindings = get_key_values(kvs, "bindings"); if (pools == NULL) { goto fail; } int npools = 0; int nbindings = 0; while (pools && pools[npools]) npools++; while (bindings && bindings[nbindings]) nbindings++; if (nbindings > 0 && nbindings != npools) { if (settings.verbose > 1) { fprintf(stderr, "npools does not match nbindings\n"); } goto fail; } char **behavior_kvs = get_key_values(kvs, "behavior"); if (behavior_kvs != NULL) { // Update the default behavior. // proxy_behavior m_behavior = m->behavior; for (int k = 0; behavior_kvs[k]; k++) { char *bstr = trimstrdup(behavior_kvs[k]); if (bstr != NULL) { cproxy_parse_behavior_key_val_str(bstr, &m_behavior); free(bstr); } } m->behavior = m_behavior; } for (int i = 0; i < npools; i++) { char *pool_name = skipspace(pools[i]); if (pool_name != NULL && pool_name[0] != '\0') { char buf[200]; snprintf(buf, sizeof(buf), "pool-%s", pool_name); char **servers = get_key_values(kvs, trimstr(buf)); if (servers != NULL) { // Parse proxy-level behavior. // proxy_behavior proxyb = m->behavior; if (parse_kvs_behavior(kvs, "behavior", pool_name, &proxyb)) { if (settings.verbose > 1) { cproxy_dump_behavior(&proxyb, "conc proxy_behavior", 1); } } // The legacy way to get a port is through the bindings, // but they're also available as an inheritable // proxy_behavior field of port_listen. // int pool_port = proxyb.port_listen; if (i < nbindings && bindings != NULL && bindings[i]) { pool_port = atoi(skipspace(bindings[i])); } if (pool_port > 0) { // Number of servers in this pool. // int s = 0; while (servers[s]) s++; if (s > 0) { // Parse server-level behaviors, so we'll have an // array of behaviors, one entry for each server. // proxy_behavior_pool behavior_pool = { .base = proxyb, .num = s, .arr = calloc(s, sizeof(proxy_behavior)) }; if (behavior_pool.arr != NULL) { char *config_str = parse_kvs_servers("svr", pool_name, kvs, servers, &behavior_pool); if (config_str != NULL && config_str[0] != '\0') { if (settings.verbose > 2) { fprintf(stderr, "conc config: %s\n", config_str); } cproxy_on_new_pool(m, pool_name, pool_port, config_str, new_config_ver, &behavior_pool); free(config_str); } free(behavior_pool.arr); } else { if (settings.verbose > 1) { fprintf(stderr, "ERROR: oom on re-config malloc\n");; } goto fail; } } else { // Note: ignore when no servers for an existing pool. // Because the config_ver won't be updated, we'll // fall into the empty_pool code path below. } } else {
//------------------------------------------------------------- // CfgGet // // Retrieve a parameter from an INI file. Returns a status code // and the paramter string in retbuff. //------------------------------------------------------------- bool CfgGet ( FILE* inifp, char *inisect, char *iniparm, char *retbuff, short bufflen, short *parmlen) { short gotsect; char tbuf[256]; char *ss, *eq, *ps, *vs, *ptr; rewind( inifp ); // find the target section gotsect = 0; while (fgets(tbuf,256,inifp) != NULL) { if ((ss = strchr(tbuf,'[')) != NULL) { if (strnicmp(ss+1,inisect,strlen(inisect)) == 0) { gotsect = 1; break; } } } if (!gotsect) { // section not found return false; } while (fgets(tbuf,256,inifp) != NULL) { // find parameter in sect if ((ptr = strrchr(tbuf,'\n')) != NULL) // remove newline if there *ptr = '\0'; ps = tbuf+strspn(tbuf," \t"); // find the first non-blank if (*ps == ';') // Skip line if comment continue; if (*ps == '[') { // Start of next section return false; } eq = strchr(ps,'='); // Find '=' sign in string if (eq) vs = eq + 1 + strspn(eq+1," \t"); // Find start of value str else continue; // found the target parameter if (strnicmp(ps,iniparm,strlen(iniparm)) == 0) { if ((ptr = strchr(vs,';')) != NULL) // cut off an EOL comment *ptr = '\0'; if (short(strlen(vs)) > bufflen - 1) {// not enough buffer space strncpy(retbuff,vs,bufflen - 1); retbuff[bufflen - 1] = '\0'; // put EOL in string *parmlen = bufflen; return true; } else { strcpy(retbuff,vs); // got it trimstr(retbuff); // trim any trailing blanks *parmlen = strlen(retbuff); return true; } } } return false; // parameter not found }