revert breaks some stupid old compilers
[oscam.git] / oscam-config-account.c
blob29e1868973e01d0e42c76c102b1be45e4a9585a0
1 #define MODULE_LOG_PREFIX "config"
3 #include "globals.h"
4 #include "module-anticasc.h"
5 #include "oscam-array.h"
6 #include "oscam-client.h"
7 #include "oscam-conf.h"
8 #include "oscam-conf-chk.h"
9 #include "oscam-conf-mk.h"
10 #include "oscam-config.h"
11 #include "oscam-garbage.h"
12 #include "oscam-lock.h"
13 #include "oscam-string.h"
15 #define cs_user "oscam.user"
17 static void account_tosleep_fn(const char *token, char *value, void *setting, FILE *f)
19 int32_t *tosleep = setting;
20 if(value)
22 *tosleep = strToIntVal(value, cfg.tosleep);
23 return;
25 if(*tosleep != cfg.tosleep || cfg.http_full_cfg)
26 { fprintf_conf(f, token, "%d\n", *tosleep); }
32 static void account_c35_suppresscmd08_fn(const char *token, char *value, void *setting, FILE *f)
34 int8_t *c35_suppresscmd08 = setting;
35 if(value)
37 *c35_suppresscmd08 = (int8_t)strToIntVal(value, cfg.c35_suppresscmd08);
38 return;
40 if(*c35_suppresscmd08 != cfg.c35_suppresscmd08 || cfg.http_full_cfg)
41 { fprintf_conf(f, token, "%d\n", *c35_suppresscmd08); }
44 /*static void account_umaxidle_fn(const char *token, char *value, void *setting, FILE *f)
46 int32_t *umaxidle = setting;
47 if(value)
49 *umaxidle = (int32_t)strToIntVal(value, cfg.umaxidle);
50 return;
52 if(*umaxidle != cfg.umaxidle || cfg.http_full_cfg)
53 { fprintf_conf(f, token, "%u\n", *umaxidle); }
58 static void account_ncd_keepalive_fn(const char *token, char *value, void *setting, FILE *f)
60 int8_t *ncd_keepalive = setting;
61 int8_t def_value = 0;
62 #ifdef MODULE_NEWCAMD
63 def_value = cfg.ncd_keepalive;
64 #endif
65 if(value)
67 *ncd_keepalive = (int8_t)strToIntVal(value, def_value);
68 return;
70 if(*ncd_keepalive != def_value || cfg.http_full_cfg)
71 { fprintf_conf(f, token, "%d\n", *ncd_keepalive); }
74 static void account_allowedprotocols_fn(const char *token, char *value, void *setting, FILE *f)
76 struct s_auth *account = setting;
77 if(value)
79 account->allowedprotocols = 0;
80 if(strlen(value) > 3)
82 int i;
83 char *ptr, *saveptr1 = NULL;
84 for(i = 0, ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1), i++)
86 if(streq(ptr, "camd33")) { account->allowedprotocols |= LIS_CAMD33TCP; }
87 else if(streq(ptr, "camd35")) { account->allowedprotocols |= LIS_CAMD35UDP; }
88 else if(streq(ptr, "cs357x")) { account->allowedprotocols |= LIS_CAMD35UDP; }
89 else if(streq(ptr, "cs378x")) { account->allowedprotocols |= LIS_CAMD35TCP; }
90 else if(streq(ptr, "newcamd")) { account->allowedprotocols |= LIS_NEWCAMD; }
91 else if(streq(ptr, "cccam")) { account->allowedprotocols |= LIS_CCCAM; }
92 else if(streq(ptr, "csp")) { account->allowedprotocols |= LIS_CSPUDP; }
93 else if(streq(ptr, "gbox")) { account->allowedprotocols |= LIS_GBOX; }
94 else if(streq(ptr, "radegast")) { account->allowedprotocols |= LIS_RADEGAST; }
95 else if(streq(ptr, "scam")) { account->allowedprotocols |= LIS_SCAM; }
96 // these have no listener ports so it doesn't make sense
97 else if(streq(ptr, "dvbapi")) { account->allowedprotocols |= LIS_DVBAPI; }
98 else if(streq(ptr, "constcw")) { account->allowedprotocols |= LIS_CONSTCW; }
99 else if(streq(ptr, "serial")) { account->allowedprotocols |= LIS_SERIAL; }
102 return;
104 if(account->allowedprotocols || cfg.http_full_cfg)
106 value = mk_t_allowedprotocols(account);
107 fprintf_conf(f, token, "%s\n", value);
108 free_mk_t(value);
112 static void account_au_fn(const char *token, char *value, void *setting, FILE *f)
114 struct s_auth *account = setting;
115 if(value)
117 // set default values for usage during runtime from Webif
118 account->autoau = 0;
119 if(!account->aureader_list)
120 { account->aureader_list = ll_create("aureader_list"); }
121 if(streq(value, "1"))
122 { account->autoau = 1; }
123 ll_clear(account->aureader_list);
124 LL_ITER itr = ll_iter_create(configured_readers);
125 struct s_reader *rdr;
126 char *pch, *saveptr1 = NULL;
127 for(pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1))
129 ll_iter_reset(&itr);
130 while((rdr = ll_iter_next(&itr)))
132 if(streq(rdr->label, pch) || account->autoau)
134 ll_append(account->aureader_list, rdr);
138 return;
140 if(account->autoau == 1)
142 fprintf_conf(f, token, "%d\n", account->autoau);
144 else if(account->aureader_list)
146 value = mk_t_aureader(account);
147 if(strlen(value) > 0)
148 { fprintf_conf(f, token, "%s\n", value); }
149 free_mk_t(value);
151 else if(cfg.http_full_cfg)
153 fprintf_conf(f, token, "%s\n", "");
157 static void account_expdate_fn(const char *token, char *value, void *setting, FILE *f)
159 struct s_auth *account = setting;
160 if(value)
162 if(!value[0])
164 account->expirationdate = (time_t)NULL;
165 return;
167 int i;
168 struct tm cstime;
169 char *ptr1, *saveptr1 = NULL;
170 memset(&cstime, 0, sizeof(cstime));
171 for(i = 0, ptr1 = strtok_r(value, "-/", &saveptr1); i < 3 && ptr1; ptr1 = strtok_r(NULL, "-/", &saveptr1), i++)
173 switch(i)
175 case 0:
176 cstime.tm_year = atoi(ptr1) - 1900;
177 break;
178 case 1:
179 cstime.tm_mon = atoi(ptr1) - 1;
180 break;
181 case 2:
182 cstime.tm_mday = atoi(ptr1);
183 break;
186 cstime.tm_hour = 23;
187 cstime.tm_min = 59;
188 cstime.tm_sec = 59;
189 cstime.tm_isdst = -1;
190 account->expirationdate = mktime(&cstime);
191 return;
193 if(account->expirationdate || cfg.http_full_cfg)
195 char buf[16];
196 struct tm timeinfo;
197 localtime_r(&account->expirationdate, &timeinfo);
198 strftime(buf, 16, "%Y-%m-%d", &timeinfo);
199 fprintf_conf(f, token, "%s\n", streq(buf, "1970-01-01") ? "" : buf);
203 static void account_allowedtimeframe_fn(const char *token, char *value, void *setting, FILE *f)
205 struct s_auth *account = setting;
206 int32_t i, j, t, startt, endt;
207 char *dest;
208 uint8_t day_idx;
209 int32_t allowed[4];
210 uint32_t tempo = 0;
212 char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL, *saveptr2 = NULL;
214 if(value)
216 //First empty allowedtimeframe array very important otherwise new config won't be properly set
217 for(i=0;i<SIZE_SHORTDAY;i++) {
218 for(j=0;j<24;j++) {
219 account->allowedtimeframe[i][j][0]=0;
220 account->allowedtimeframe[i][j][1]=0;
223 account->allowedtimeframe_set=0;
224 strtoupper(value);
226 for(i = 0, ptr1 = strtok_r(value, ";", &saveptr1); (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++)
228 if((ptr2 = strchr(trim(ptr1), '@')))
230 *ptr2++ = '\0'; //clean up @ symbol
231 //ptr1 is the day
232 dest = strstr(weekdstr,ptr1);
233 day_idx = (dest - weekdstr)/3;
235 for(j = 0, ptr3 = strtok_r(ptr2, ",", &saveptr2); (ptr3); ptr3 = strtok_r(NULL, ",", &saveptr2), j++)
237 if((sscanf(ptr3, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4) && (day_idx<SIZE_SHORTDAY))
239 startt = allowed[0] * 60 + allowed[1];
240 endt = allowed[2] * 60 + allowed[3];
241 if(startt == endt) { endt++; } //end time cannot be the same as the star time
242 if((startt <0) || (startt > 1439)) { startt = 0; } //could not start later than 23H59, avoid overflow
243 if((endt <0) || (endt > 1440)) { endt = 1440; } //could not be higher than 24H00, avoid overflow
244 account->allowedtimeframe_set=1;
245 if(startt > endt) {
246 for(t=startt; t<1440 ;t++)
248 tempo = (1 << (t % 30));
249 account->allowedtimeframe[day_idx][t/60][(t/30)%2]=account->allowedtimeframe[day_idx][t/60][(t/30)%2]|tempo;
251 startt=0;
253 for(t=startt; t<endt ;t++)
255 tempo = (1 << (t % 30));
256 account->allowedtimeframe[day_idx][t/60][((t/30)%2)]=account->allowedtimeframe[day_idx][t/60][(t/30)%2]|tempo;
259 else
261 fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (DAY@HH:MM-HH:MM)\n", value);
265 else //No day specified so whole week (ALL)
267 if(sscanf(ptr1, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4)
269 startt = allowed[0] * 60 + allowed[1];
270 endt = allowed[2] * 60 + allowed[3];
271 if(startt == endt) { endt++; } //end time cannot be the same as the star time
272 if((startt <0) || (startt > 1439)) { startt = 0; } //could not start later than 23H59, avoid overflow
273 if((endt <0) || (endt > 1440)) { endt = 1440; } //could not be higher than 24H00, avoid overflow
274 account->allowedtimeframe_set=1;
275 dest = strstr(weekdstr,"ALL");
276 day_idx = (dest - weekdstr)/3;
277 if(startt > endt)
279 for(t=startt; t<1440 ;t++)
281 tempo = (1 << (t % 30));
282 account->allowedtimeframe[day_idx][t/60][(t/30)%2]=account->allowedtimeframe[7][t/60][(t/30)%2]|tempo;
284 startt=0;
286 for(t=startt; t<endt ;t++)
288 tempo = (1 << (t % 30));
289 account->allowedtimeframe[day_idx][t/60][(t/30)%2]=account->allowedtimeframe[7][t/60][(t/30)%2]|tempo;
292 else
294 fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (hh:mm-hh:mm)\n", value);
299 return;
301 if(account->allowedtimeframe_set)
303 value = mk_t_allowedtimeframe(account);
304 fprintf_conf(f, token, "%s\n", value);
305 free_mk_t(value);
307 else if(cfg.http_full_cfg)
309 fprintf_conf(f, token, "%s\n", "");
313 static void account_tuntab_fn(const char *token, char *value, void *setting, FILE *f)
315 TUNTAB *ttab = setting;
316 if(value)
318 if(strlen(value) == 0)
320 tuntab_clear(ttab);
322 else
324 chk_tuntab(value, ttab);
326 return;
328 if((ttab->ttdata && ttab->ttdata[0].bt_caidfrom) || cfg.http_full_cfg)
330 value = mk_t_tuntab(ttab);
331 fprintf_conf(f, token, "%s\n", value);
332 free_mk_t(value);
336 void group_fn(const char *token, char *value, void *setting, FILE *f)
338 uint64_t *grp = setting;
339 if(value)
341 char *ptr1, *saveptr1 = NULL;
342 *grp = 0;
343 for(ptr1 = strtok_r(value, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1))
345 int32_t g;
346 g = atoi(ptr1);
347 if(g > 0 && g < 65)
348 { *grp |= (((uint64_t)1) << (g - 1)); }
350 return;
352 if(*grp || cfg.http_full_cfg)
354 value = mk_t_group(*grp);
355 fprintf_conf(f, token, "%s\n", value);
356 free_mk_t(value);
360 void services_fn(const char *token, char *value, void *setting, FILE *f)
362 SIDTABS *sidtabs = setting;
363 if(value)
365 strtolower(value);
366 chk_services(value, sidtabs);
367 return;
369 value = mk_t_service(sidtabs);
370 if(strlen(value) > 0 || cfg.http_full_cfg)
371 { fprintf_conf(f, token, "%s\n", value); }
372 free_mk_t(value);
375 void class_fn(const char *token, char *value, void *setting, FILE *f)
377 CLASSTAB *cltab = setting;
378 if(value)
380 strtolower(value);
381 chk_cltab(value, cltab);
382 return;
384 value = mk_t_cltab(cltab);
385 if(strlen(value) > 0 || cfg.http_full_cfg)
387 fprintf_conf(f, token, "%s\n", value);
388 free_mk_t(value);
392 #ifdef CS_ANTICASC
393 static void account_fixups_fn(void *var)
395 struct s_auth *account = var;
396 if(account->ac_users < -1) { account->ac_users = DEFAULT_AC_USERS; }
397 if(account->ac_penalty < -1) { account->ac_penalty = DEFAULT_AC_PENALTY; }
398 if(account->acosc_max_active_sids < -1) { account->acosc_max_active_sids = -1; }
399 if(account->acosc_zap_limit < -1) { account->acosc_zap_limit = -1; }
400 if(account->acosc_penalty < -1) { account->acosc_penalty = -1; }
401 if(account->acosc_penalty_duration < -1) { account->acosc_penalty_duration = -1; }
402 if(account->acosc_delay < -1) { account->acosc_delay = -1; }
404 #endif
406 #define OFS(X) offsetof(struct s_auth, X)
407 #define SIZEOF(X) sizeof(((struct s_auth *)0)->X)
409 static const struct config_list account_opts[] =
411 #ifdef CS_ANTICASC
412 DEF_OPT_FIXUP_FUNC(account_fixups_fn),
413 #endif
414 DEF_OPT_INT8("disabled" , OFS(disabled), 0),
415 DEF_OPT_SSTR("user" , OFS(usr), "", SIZEOF(usr)),
416 DEF_OPT_STR("pwd" , OFS(pwd), NULL),
417 #ifdef WEBIF
418 DEF_OPT_STR("description" , OFS(description), NULL),
419 #endif
420 DEF_OPT_STR("hostname" , OFS(dyndns), NULL),
421 DEF_OPT_FUNC("caid" , OFS(ctab), check_caidtab_fn),
422 DEF_OPT_INT8("uniq" , OFS(uniq), 0),
423 DEF_OPT_UINT8("sleepsend" , OFS(c35_sleepsend), 0),
424 DEF_OPT_INT32("failban" , OFS(failban), 0),
425 DEF_OPT_INT8("monlevel" , OFS(monlvl), 0),
426 DEF_OPT_FUNC("sleep" , OFS(tosleep), account_tosleep_fn),
427 DEF_OPT_FUNC("suppresscmd08" , OFS(c35_suppresscmd08), account_c35_suppresscmd08_fn),
428 DEF_OPT_INT32("umaxidle" , OFS(umaxidle), -1),
429 DEF_OPT_FUNC("keepalive" , OFS(ncd_keepalive), account_ncd_keepalive_fn),
430 DEF_OPT_FUNC("au" , 0, account_au_fn),
431 DEF_OPT_UINT8("emmreassembly" , OFS(emm_reassembly), 2),
432 DEF_OPT_FUNC("expdate" , 0, account_expdate_fn),
433 DEF_OPT_FUNC("allowedprotocols" , 0, account_allowedprotocols_fn),
434 DEF_OPT_FUNC("allowedtimeframe" , 0, account_allowedtimeframe_fn),
435 DEF_OPT_FUNC("betatunnel" , OFS(ttab), account_tuntab_fn),
436 DEF_OPT_FUNC("group" , OFS(grp), group_fn),
437 DEF_OPT_FUNC("services" , OFS(sidtabs), services_fn),
438 DEF_OPT_INT8("preferlocalcards" , OFS(preferlocalcards), -1),
439 DEF_OPT_FUNC_X("ident" , OFS(ftab), ftab_fn, FTAB_ACCOUNT | FTAB_PROVID),
440 DEF_OPT_FUNC_X("chid" , OFS(fchid), ftab_fn, FTAB_ACCOUNT | FTAB_CHID),
441 DEF_OPT_FUNC("class" , OFS(cltab), class_fn),
442 DEF_OPT_UINT32("max_connections" , OFS(max_connections), 1),
443 #ifdef CS_CACHEEX
444 DEF_OPT_INT8("cacheex" , OFS(cacheex.mode), 0),
445 DEF_OPT_INT8("cacheex_maxhop" , OFS(cacheex.maxhop), 0),
446 DEF_OPT_FUNC("cacheex_ecm_filter" , OFS(cacheex.filter_caidtab), cacheex_hitvaluetab_fn),
447 DEF_OPT_UINT8("cacheex_drop_csp" , OFS(cacheex.drop_csp), 0),
448 DEF_OPT_UINT8("cacheex_allow_request" , OFS(cacheex.allow_request), 0),
449 DEF_OPT_UINT8("no_wait_time" , OFS(no_wait_time), 0),
450 DEF_OPT_UINT8("cacheex_allow_filter", OFS(cacheex.allow_filter), 1),
451 DEF_OPT_UINT8("cacheex_block_fakecws",OFS(cacheex.block_fakecws), 0),
452 DEF_OPT_UINT8("disablecrccacheex" ,OFS(disablecrccacheex), 0),
453 DEF_OPT_FUNC_X("disablecrccacheex_only_for", OFS(disablecrccacheex_only_for), ftab_fn, FTAB_ACCOUNT | FTAB_IGNCRCCEX4USERONLYFOR),
454 #endif
455 #ifdef MODULE_CCCAM
456 DEF_OPT_INT32("cccmaxhops" , OFS(cccmaxhops), DEFAULT_CC_MAXHOPS),
457 DEF_OPT_INT8("cccreshare" , OFS(cccreshare), DEFAULT_CC_RESHARE),
458 DEF_OPT_INT8("cccignorereshare" , OFS(cccignorereshare), DEFAULT_CC_IGNRSHR),
459 DEF_OPT_INT8("cccstealth" , OFS(cccstealth), DEFAULT_CC_STEALTH),
460 #endif
461 #ifdef CS_ANTICASC
462 DEF_OPT_INT32("fakedelay" , OFS(ac_fakedelay), -1),
463 DEF_OPT_INT32("numusers" , OFS(ac_users), DEFAULT_AC_USERS),
464 DEF_OPT_INT8("penalty" , OFS(ac_penalty), DEFAULT_AC_PENALTY),
465 DEF_OPT_INT8("acosc_max_active_sids" , OFS(acosc_max_active_sids), -1 ),
466 DEF_OPT_INT8("acosc_zap_limit" , OFS(acosc_zap_limit), -1 ),
467 DEF_OPT_INT8("acosc_penalty" , OFS(acosc_penalty), -1 ),
468 DEF_OPT_INT32("acosc_penalty_duration" , OFS(acosc_penalty_duration), -1 ),
469 DEF_OPT_INT32("acosc_delay" , OFS(acosc_delay), -1 ),
470 #endif
471 #ifdef WITH_LB
472 DEF_OPT_INT32("lb_nbest_readers" , OFS(lb_nbest_readers), -1),
473 DEF_OPT_INT32("lb_nfb_readers" , OFS(lb_nfb_readers), -1),
474 DEF_OPT_FUNC("lb_nbest_percaid" , OFS(lb_nbest_readers_tab), caidvaluetab_fn),
475 #endif
476 #ifdef CW_CYCLE_CHECK
477 DEF_OPT_INT8("cwc_disable" , OFS(cwc_disable), 0),
478 #endif
479 DEF_LAST_OPT
482 void chk_account(const char *token, char *value, struct s_auth *account)
484 if(config_list_parse(account_opts, token, value, account))
485 { return; }
486 else if(token[0] != '#')
487 { fprintf(stderr, "Warning: keyword '%s' in account section not recognized\n", token); }
490 void account_set_defaults(struct s_auth *account)
492 config_list_set_defaults(account_opts, account);
495 struct s_auth *init_userdb(void)
497 FILE *fp = open_config_file(cs_user);
498 if(!fp)
499 { return NULL; }
501 struct s_auth *authptr = NULL;
502 int32_t tag = 0, nr = 0, expired = 0, disabled = 0;
503 char *token;
504 struct s_auth *account = NULL;
505 struct s_auth *probe = NULL;
506 if(!cs_malloc(&token, MAXLINESIZE))
507 { return NULL; }
509 while(fgets(token, MAXLINESIZE, fp))
511 int32_t l;
512 void *ptr;
514 if((l = strlen(trim(token))) < 3)
515 { continue; }
516 if(token[0] == '[' && token[l - 1] == ']')
518 token[l - 1] = 0;
519 tag = streq("account", strtolower(token + 1));
520 if(!cs_malloc(&ptr, sizeof(struct s_auth)))
521 { break; }
522 if(account)
523 { account->next = ptr; }
524 else
525 { authptr = ptr; }
527 account = ptr;
528 account_set_defaults(account);
529 nr++;
531 continue;
534 if(!tag)
535 { continue; }
536 char *value = strchr(token, '=');
537 if(!value)
538 { continue; }
540 *value++ = '\0';
542 // check for duplicate useraccounts and make the name unique
543 if(streq(trim(strtolower(token)), "user"))
545 for(probe = authptr; probe; probe = probe->next)
547 if(!strcmp(probe->usr, trim(value)))
549 fprintf(stderr, "Warning: duplicate account '%s'\n", value);
550 strncat(value, "_x", sizeof(probe->usr) - strlen(value) - 1);
554 chk_account(trim(strtolower(token)), trim(value), account);
556 NULLFREE(token);
557 fclose(fp);
559 for(account = authptr; account; account = account->next)
561 if(account->expirationdate && account->expirationdate < time(NULL))
562 { ++expired; }
563 if(account->disabled)
564 { ++disabled; }
566 cs_log("userdb reloaded: %d accounts loaded, %d expired, %d disabled", nr, expired, disabled);
567 return authptr;
570 int32_t init_free_userdb(struct s_auth *ptr)
572 int32_t nro;
573 for(nro = 0; ptr; nro++)
575 struct s_auth *ptr_next;
576 ptr_next = ptr->next;
577 ll_destroy(&ptr->aureader_list);
578 ptr->next = NULL;
579 config_list_gc_values(account_opts, ptr);
580 ftab_clear(&ptr->ftab);
581 ftab_clear(&ptr->fchid);
582 tuntab_clear(&ptr->ttab);
583 caidtab_clear(&ptr->ctab);
584 NULLFREE(ptr->cltab.aclass);
585 NULLFREE(ptr->cltab.bclass);
586 #ifdef CS_CACHEEX
587 cecspvaluetab_clear(&ptr->cacheex.filter_caidtab);
588 #endif
589 #ifdef WITH_LB
590 caidvaluetab_clear(&ptr->lb_nbest_readers_tab);
591 #endif
592 add_garbage(ptr);
593 ptr = ptr_next;
595 cs_log("userdb %d accounts freed", nro);
596 return nro;
599 int32_t write_userdb(void)
601 struct s_auth *account;
602 FILE *f = create_config_file(cs_user);
603 if(!f)
604 { return 1; }
605 for(account = cfg.account; account; account = account->next)
607 fprintf(f, "[account]\n");
608 config_list_apply_fixups(account_opts, account);
609 config_list_save(f, account_opts, account, cfg.http_full_cfg);
610 fprintf(f, "\n");
612 return flush_config_file(f, cs_user);
615 void cs_accounts_chk(void)
617 struct s_auth *account1, *account2;
618 struct s_auth *new_accounts = init_userdb();
619 cs_writelock(__func__, &config_lock);
620 struct s_auth *old_accounts = cfg.account;
621 for(account1 = cfg.account; account1; account1 = account1->next)
623 for(account2 = new_accounts; account2; account2 = account2->next)
625 if(!strcmp(account1->usr, account2->usr))
627 account2->cwfound = account1->cwfound;
628 account2->cwcache = account1->cwcache;
629 account2->cwnot = account1->cwnot;
630 account2->cwtun = account1->cwtun;
631 account2->cwignored = account1->cwignored;
632 account2->cwtout = account1->cwtout;
633 account2->emmok = account1->emmok;
634 account2->emmnok = account1->emmnok;
635 account2->firstlogin = account1->firstlogin;
636 ac_copy_vars(account1, account2);
640 cs_reinit_clients(new_accounts);
641 cfg.account = new_accounts;
642 init_free_userdb(old_accounts);
643 ac_clear();
644 cs_writeunlock(__func__, &config_lock);