1 | #include "globals.h"
|
---|
2 | #include "module-anticasc.h"
|
---|
3 | #include "oscam-client.h"
|
---|
4 | #include "oscam-conf.h"
|
---|
5 | #include "oscam-conf-chk.h"
|
---|
6 | #include "oscam-conf-mk.h"
|
---|
7 | #include "oscam-config.h"
|
---|
8 | #include "oscam-garbage.h"
|
---|
9 | #include "oscam-lock.h"
|
---|
10 | #include "oscam-string.h"
|
---|
11 |
|
---|
12 | #define cs_user "oscam.user"
|
---|
13 |
|
---|
14 | static void account_tosleep_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
15 | int32_t *tosleep = setting;
|
---|
16 | if (value) {
|
---|
17 | *tosleep = strToIntVal(value, cfg.tosleep);
|
---|
18 | return;
|
---|
19 | }
|
---|
20 | if (*tosleep != cfg.tosleep || cfg.http_full_cfg)
|
---|
21 | fprintf_conf(f, token, "%d\n", *tosleep);
|
---|
22 | }
|
---|
23 |
|
---|
24 | static void account_c35_suppresscmd08_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
25 | int8_t *c35_suppresscmd08 = setting;
|
---|
26 | if (value) {
|
---|
27 | *c35_suppresscmd08 = (int8_t)strToIntVal(value, cfg.c35_suppresscmd08);
|
---|
28 | return;
|
---|
29 | }
|
---|
30 | if (*c35_suppresscmd08 != cfg.c35_suppresscmd08 || cfg.http_full_cfg)
|
---|
31 | fprintf_conf(f, token, "%d\n", *c35_suppresscmd08);
|
---|
32 | }
|
---|
33 |
|
---|
34 | static void account_ncd_keepalive_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
35 | int8_t *ncd_keepalive = setting;
|
---|
36 | int8_t def_value = 0;
|
---|
37 | #ifdef MODULE_NEWCAMD
|
---|
38 | def_value = cfg.ncd_keepalive;
|
---|
39 | #endif
|
---|
40 | if (value) {
|
---|
41 | *ncd_keepalive = (int8_t)strToIntVal(value, def_value);
|
---|
42 | return;
|
---|
43 | }
|
---|
44 | if (*ncd_keepalive != def_value || cfg.http_full_cfg)
|
---|
45 | fprintf_conf(f, token, "%d\n", *ncd_keepalive);
|
---|
46 | }
|
---|
47 |
|
---|
48 | static void account_allowedprotocols_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
49 | struct s_auth *account = setting;
|
---|
50 | if (value) {
|
---|
51 | account->allowedprotocols = 0;
|
---|
52 | if (strlen(value) > 3) {
|
---|
53 | int i;
|
---|
54 | char *ptr, *saveptr1 = NULL;
|
---|
55 | for (i = 0, ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1), i++) {
|
---|
56 | if (streq(ptr, "camd33")) account->allowedprotocols |= LIS_CAMD33TCP;
|
---|
57 | else if (streq(ptr, "camd35")) account->allowedprotocols |= LIS_CAMD35UDP;
|
---|
58 | else if (streq(ptr, "cs357x")) account->allowedprotocols |= LIS_CAMD35UDP;
|
---|
59 | else if (streq(ptr, "cs378x")) account->allowedprotocols |= LIS_CAMD35TCP;
|
---|
60 | else if (streq(ptr, "newcamd")) account->allowedprotocols |= LIS_NEWCAMD;
|
---|
61 | else if (streq(ptr, "cccam")) account->allowedprotocols |= LIS_CCCAM;
|
---|
62 | else if (streq(ptr, "csp")) account->allowedprotocols |= LIS_CSPUDP;
|
---|
63 | else if (streq(ptr, "gbox")) account->allowedprotocols |= LIS_GBOX;
|
---|
64 | else if (streq(ptr, "radegast")) account->allowedprotocols |= LIS_RADEGAST;
|
---|
65 | // these have no listener ports so it doesn't make sense
|
---|
66 | else if (streq(ptr, "dvbapi")) account->allowedprotocols |= LIS_DVBAPI;
|
---|
67 | else if (streq(ptr, "constcw")) account->allowedprotocols |= LIS_CONSTCW;
|
---|
68 | else if (streq(ptr, "serial")) account->allowedprotocols |= LIS_SERIAL;
|
---|
69 | }
|
---|
70 | }
|
---|
71 | return;
|
---|
72 | }
|
---|
73 | if (account->allowedprotocols || cfg.http_full_cfg ){
|
---|
74 | value = mk_t_allowedprotocols(account);
|
---|
75 | fprintf_conf(f, token, "%s\n", value);
|
---|
76 | free_mk_t(value);
|
---|
77 | }
|
---|
78 | }
|
---|
79 |
|
---|
80 | static void account_au_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
81 | struct s_auth *account = setting;
|
---|
82 | if (value) {
|
---|
83 | // set default values for usage during runtime from Webif
|
---|
84 | account->autoau = 0;
|
---|
85 | if (!account->aureader_list)
|
---|
86 | account->aureader_list = ll_create("aureader_list");
|
---|
87 | if (streq(value, "1"))
|
---|
88 | account->autoau = 1;
|
---|
89 | ll_clear(account->aureader_list);
|
---|
90 | LL_ITER itr = ll_iter_create(configured_readers);
|
---|
91 | struct s_reader *rdr;
|
---|
92 | char *pch, *saveptr1 = NULL;
|
---|
93 | for (pch = strtok_r(value, ",", &saveptr1); pch != NULL; pch = strtok_r(NULL, ",", &saveptr1)) {
|
---|
94 | ll_iter_reset(&itr);
|
---|
95 | while ((rdr = ll_iter_next(&itr))) {
|
---|
96 | if (streq(rdr->label, pch) || account->autoau) {
|
---|
97 | ll_append(account->aureader_list, rdr);
|
---|
98 | }
|
---|
99 | }
|
---|
100 | }
|
---|
101 | return;
|
---|
102 | }
|
---|
103 | if (account->autoau == 1) {
|
---|
104 | fprintf_conf(f, token, "%d\n", account->autoau);
|
---|
105 | } else if (account->aureader_list) {
|
---|
106 | value = mk_t_aureader(account);
|
---|
107 | if (strlen(value) > 0)
|
---|
108 | fprintf_conf(f, token, "%s\n", value);
|
---|
109 | free_mk_t(value);
|
---|
110 | } else if (cfg.http_full_cfg) {
|
---|
111 | fprintf_conf(f, token, "%s\n", "");
|
---|
112 | }
|
---|
113 | }
|
---|
114 |
|
---|
115 | static void account_expdate_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
116 | struct s_auth *account = setting;
|
---|
117 | if (value) {
|
---|
118 | if (!value[0]) {
|
---|
119 | account->expirationdate = (time_t)NULL;
|
---|
120 | return;
|
---|
121 | }
|
---|
122 | int i;
|
---|
123 | struct tm cstime;
|
---|
124 | char *ptr1, *saveptr1 = NULL;
|
---|
125 | memset(&cstime,0,sizeof(cstime));
|
---|
126 | for (i = 0, ptr1 = strtok_r(value, "-/", &saveptr1); i < 3 && ptr1; ptr1 = strtok_r(NULL, "-/", &saveptr1), i++) {
|
---|
127 | switch(i) {
|
---|
128 | case 0: cstime.tm_year = atoi(ptr1) - 1900; break;
|
---|
129 | case 1: cstime.tm_mon = atoi(ptr1) - 1; break;
|
---|
130 | case 2: cstime.tm_mday = atoi(ptr1); break;
|
---|
131 | }
|
---|
132 | }
|
---|
133 | cstime.tm_hour = 23;
|
---|
134 | cstime.tm_min = 59;
|
---|
135 | cstime.tm_sec = 59;
|
---|
136 | cstime.tm_isdst = -1;
|
---|
137 | account->expirationdate = mktime(&cstime);
|
---|
138 | return;
|
---|
139 | }
|
---|
140 | if (account->expirationdate || cfg.http_full_cfg) {
|
---|
141 | char buf[16];
|
---|
142 | struct tm timeinfo;
|
---|
143 | localtime_r(&account->expirationdate, &timeinfo);
|
---|
144 | strftime(buf, 16, "%Y-%m-%d", &timeinfo);
|
---|
145 | fprintf_conf(f, token, "%s\n", streq(buf, "1970-01-01") ? "" : buf);
|
---|
146 | }
|
---|
147 | }
|
---|
148 |
|
---|
149 | static void account_allowedtimeframe_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
150 | struct s_auth *account = setting;
|
---|
151 | if (value) {
|
---|
152 | account->allowedtimeframe[0] = 0;
|
---|
153 | account->allowedtimeframe[1] = 0;
|
---|
154 | if (strlen(value)) {
|
---|
155 | int32_t allowed[4];
|
---|
156 | if (sscanf(value, "%2d:%2d-%2d:%2d", &allowed[0], &allowed[1], &allowed[2], &allowed[3]) == 4) {
|
---|
157 | account->allowedtimeframe[0] = allowed[0] * 60 + allowed[1];
|
---|
158 | account->allowedtimeframe[1] = allowed[2] * 60 + allowed[3];
|
---|
159 | } else {
|
---|
160 | fprintf(stderr, "WARNING: Value '%s' is not valid for allowedtimeframe (hh:mm-hh:mm)\n", value);
|
---|
161 | }
|
---|
162 | }
|
---|
163 | return;
|
---|
164 | }
|
---|
165 | if (account->allowedtimeframe[0] && account->allowedtimeframe[1]) {
|
---|
166 | fprintf_conf(f, token, "%02d:%02d-%02d:%02d\n",
|
---|
167 | account->allowedtimeframe[0] / 60, account->allowedtimeframe[0] % 60,
|
---|
168 | account->allowedtimeframe[1] / 60, account->allowedtimeframe[1] % 60 );
|
---|
169 | } else if (cfg.http_full_cfg) {
|
---|
170 | fprintf_conf(f, token, "%s\n", "");
|
---|
171 | }
|
---|
172 | }
|
---|
173 |
|
---|
174 | static void account_tuntab_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
175 | TUNTAB *ttab = setting;
|
---|
176 | if (value) {
|
---|
177 | if (strlen(value) == 0) {
|
---|
178 | clear_tuntab(ttab);
|
---|
179 | } else {
|
---|
180 | chk_tuntab(value, ttab);
|
---|
181 | }
|
---|
182 | return;
|
---|
183 | }
|
---|
184 | if (ttab->bt_caidfrom[0] || cfg.http_full_cfg) {
|
---|
185 | value = mk_t_tuntab(ttab);
|
---|
186 | fprintf_conf(f, token, "%s\n", value);
|
---|
187 | free_mk_t(value);
|
---|
188 | }
|
---|
189 | }
|
---|
190 |
|
---|
191 | void group_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
192 | uint64_t *grp = setting;
|
---|
193 | if (value) {
|
---|
194 | char *ptr1, *saveptr1 = NULL;
|
---|
195 | *grp = 0;
|
---|
196 | for (ptr1 = strtok_r(value, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1)) {
|
---|
197 | int32_t g;
|
---|
198 | g = atoi(ptr1);
|
---|
199 | if (g > 0 && g < 65)
|
---|
200 | *grp |= (((uint64_t)1) << (g-1));
|
---|
201 | }
|
---|
202 | return;
|
---|
203 | }
|
---|
204 | if (*grp || cfg.http_full_cfg) {
|
---|
205 | value = mk_t_group(*grp);
|
---|
206 | fprintf_conf(f, token, "%s\n", value);
|
---|
207 | free_mk_t(value);
|
---|
208 | }
|
---|
209 | }
|
---|
210 |
|
---|
211 | void services_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
212 | SIDTABS *sidtabs = setting;
|
---|
213 | if (value) {
|
---|
214 | strtolower(value);
|
---|
215 | chk_services(value, sidtabs);
|
---|
216 | return;
|
---|
217 | }
|
---|
218 | value = mk_t_service(sidtabs);
|
---|
219 | if (strlen(value) > 0 || cfg.http_full_cfg)
|
---|
220 | fprintf_conf(f, token, "%s\n", value);
|
---|
221 | free_mk_t(value);
|
---|
222 | }
|
---|
223 |
|
---|
224 | void class_fn(const char *token, char *value, void *setting, FILE *f) {
|
---|
225 | CLASSTAB *cltab = setting;
|
---|
226 | if (value) {
|
---|
227 | strtolower(value);
|
---|
228 | chk_cltab(value, cltab);
|
---|
229 | return;
|
---|
230 | }
|
---|
231 | value = mk_t_cltab(cltab);
|
---|
232 | if (strlen(value) > 0 || cfg.http_full_cfg) {
|
---|
233 | fprintf_conf(f, token, "%s\n", value);
|
---|
234 | free_mk_t(value);
|
---|
235 | }
|
---|
236 | }
|
---|
237 |
|
---|
238 | #ifdef CS_ANTICASC
|
---|
239 | static void account_fixups_fn(void *var) {
|
---|
240 | struct s_auth *account = var;
|
---|
241 | if (account->ac_users < -1) account->ac_users = DEFAULT_AC_USERS;
|
---|
242 | if (account->ac_penalty < -1) account->ac_penalty = DEFAULT_AC_PENALTY;
|
---|
243 | }
|
---|
244 | #endif
|
---|
245 |
|
---|
246 | #define OFS(X) offsetof(struct s_auth, X)
|
---|
247 | #define SIZEOF(X) sizeof(((struct s_auth *)0)->X)
|
---|
248 |
|
---|
249 | static const struct config_list account_opts[] = {
|
---|
250 | #ifdef CS_ANTICASC
|
---|
251 | DEF_OPT_FIXUP_FUNC(account_fixups_fn),
|
---|
252 | #endif
|
---|
253 | DEF_OPT_INT8("disabled" , OFS(disabled), 0 ),
|
---|
254 | DEF_OPT_SSTR("user" , OFS(usr), "", SIZEOF(usr) ),
|
---|
255 | DEF_OPT_STR("pwd" , OFS(pwd), NULL ),
|
---|
256 | #ifdef WEBIF
|
---|
257 | DEF_OPT_STR("description" , OFS(description), NULL ),
|
---|
258 | #endif
|
---|
259 | DEF_OPT_STR("hostname" , OFS(dyndns), NULL ),
|
---|
260 | DEF_OPT_FUNC("caid" , OFS(ctab), check_caidtab_fn ),
|
---|
261 | DEF_OPT_INT8("uniq" , OFS(uniq), 0 ),
|
---|
262 | DEF_OPT_UINT8("sleepsend" , OFS(c35_sleepsend), 0 ),
|
---|
263 | DEF_OPT_INT32("failban" , OFS(failban), 0 ),
|
---|
264 | DEF_OPT_INT8("monlevel" , OFS(monlvl), 0 ),
|
---|
265 | DEF_OPT_FUNC("sleep" , OFS(tosleep), account_tosleep_fn ),
|
---|
266 | DEF_OPT_FUNC("suppresscmd08" , OFS(c35_suppresscmd08), account_c35_suppresscmd08_fn ),
|
---|
267 | DEF_OPT_FUNC("keepalive" , OFS(ncd_keepalive), account_ncd_keepalive_fn ),
|
---|
268 | DEF_OPT_FUNC("au" , 0, account_au_fn ),
|
---|
269 | DEF_OPT_UINT8("emmreassembly" , OFS(emm_reassembly), 1 ),
|
---|
270 | DEF_OPT_FUNC("expdate" , 0, account_expdate_fn ),
|
---|
271 | DEF_OPT_FUNC("allowedprotocols" , 0, account_allowedprotocols_fn ),
|
---|
272 | DEF_OPT_FUNC("allowedtimeframe" , 0, account_allowedtimeframe_fn ),
|
---|
273 | DEF_OPT_FUNC("betatunnel" , OFS(ttab), account_tuntab_fn ),
|
---|
274 | DEF_OPT_FUNC("group" , OFS(grp), group_fn ),
|
---|
275 | DEF_OPT_FUNC("services" , OFS(sidtabs), services_fn ),
|
---|
276 | DEF_OPT_FUNC_X("ident" , OFS(ftab), ftab_fn, FTAB_ACCOUNT | FTAB_PROVID ),
|
---|
277 | DEF_OPT_FUNC_X("chid" , OFS(fchid), ftab_fn, FTAB_ACCOUNT | FTAB_CHID ),
|
---|
278 | DEF_OPT_FUNC("class" , OFS(cltab), class_fn ),
|
---|
279 | #ifdef CS_CACHEEX
|
---|
280 | DEF_OPT_INT8("cacheex" , OFS(cacheex.mode), 0 ),
|
---|
281 | DEF_OPT_INT8("cacheex_maxhop" , OFS(cacheex.maxhop), 0 ),
|
---|
282 | DEF_OPT_FUNC("cacheex_ecm_filter" , OFS(cacheex.filter_caidtab), cacheex_hitvaluetab_fn ),
|
---|
283 | DEF_OPT_UINT8("cacheex_drop_csp" , OFS(cacheex.drop_csp), 0 ),
|
---|
284 | DEF_OPT_UINT8("cacheex_allow_request" , OFS(cacheex.allow_request), 1 ),
|
---|
285 | #endif
|
---|
286 | #ifdef MODULE_CCCAM
|
---|
287 | DEF_OPT_INT32("cccmaxhops" , OFS(cccmaxhops), DEFAULT_CC_MAXHOPS ),
|
---|
288 | DEF_OPT_INT8("cccreshare" , OFS(cccreshare), DEFAULT_CC_RESHARE ),
|
---|
289 | DEF_OPT_INT8("cccignorereshare" , OFS(cccignorereshare), DEFAULT_CC_IGNRSHR ),
|
---|
290 | DEF_OPT_INT8("cccstealth" , OFS(cccstealth), DEFAULT_CC_STEALTH ),
|
---|
291 | #endif
|
---|
292 | #ifdef CS_ANTICASC
|
---|
293 | DEF_OPT_INT32("fakedelay" , OFS(ac_fakedelay), -1 ),
|
---|
294 | DEF_OPT_INT32("numusers" , OFS(ac_users), DEFAULT_AC_USERS ),
|
---|
295 | DEF_OPT_INT8("penalty" , OFS(ac_penalty), DEFAULT_AC_PENALTY ),
|
---|
296 | #endif
|
---|
297 | DEF_LAST_OPT
|
---|
298 | };
|
---|
299 |
|
---|
300 | void chk_account(const char *token, char *value, struct s_auth *account)
|
---|
301 | {
|
---|
302 | if (config_list_parse(account_opts, token, value, account))
|
---|
303 | return;
|
---|
304 | else if (token[0] != '#')
|
---|
305 | fprintf(stderr, "Warning: keyword '%s' in account section not recognized\n", token);
|
---|
306 | }
|
---|
307 |
|
---|
308 | void account_set_defaults(struct s_auth *account) {
|
---|
309 | config_list_set_defaults(account_opts, account);
|
---|
310 | }
|
---|
311 |
|
---|
312 | struct s_auth *init_userdb(void)
|
---|
313 | {
|
---|
314 | FILE *fp = open_config_file(cs_user);
|
---|
315 | if (!fp)
|
---|
316 | return NULL;
|
---|
317 |
|
---|
318 | struct s_auth *authptr = NULL;
|
---|
319 | int32_t tag = 0, nr = 0, expired = 0, disabled = 0;
|
---|
320 | char *token;
|
---|
321 | struct s_auth *account = NULL;
|
---|
322 | struct s_auth *probe = NULL;
|
---|
323 | if (!cs_malloc(&token, MAXLINESIZE))
|
---|
324 | return NULL;
|
---|
325 |
|
---|
326 | while (fgets(token, MAXLINESIZE, fp)) {
|
---|
327 | int32_t l;
|
---|
328 | void *ptr;
|
---|
329 |
|
---|
330 | if ((l=strlen(trim(token))) < 3)
|
---|
331 | continue;
|
---|
332 | if (token[0] == '[' && token[l-1] == ']') {
|
---|
333 | token[l - 1] = 0;
|
---|
334 | tag = streq("account", strtolower(token + 1));
|
---|
335 | if (!cs_malloc(&ptr, sizeof(struct s_auth)))
|
---|
336 | break;
|
---|
337 | if (account)
|
---|
338 | account->next = ptr;
|
---|
339 | else
|
---|
340 | authptr = ptr;
|
---|
341 |
|
---|
342 | account = ptr;
|
---|
343 | account_set_defaults(account);
|
---|
344 | nr++;
|
---|
345 |
|
---|
346 | continue;
|
---|
347 | }
|
---|
348 |
|
---|
349 | if (!tag)
|
---|
350 | continue;
|
---|
351 | char *value = strchr(token, '=');
|
---|
352 | if (!value)
|
---|
353 | continue;
|
---|
354 |
|
---|
355 | *value++ = '\0';
|
---|
356 |
|
---|
357 | // check for duplicate useraccounts and make the name unique
|
---|
358 | if (streq(trim(strtolower(token)), "user")) {
|
---|
359 | for(probe = authptr; probe; probe = probe->next){
|
---|
360 | if (!strcmp(probe->usr, trim(value))){
|
---|
361 | fprintf(stderr, "Warning: duplicate account '%s'\n", value);
|
---|
362 | strncat(value, "_x", sizeof(probe->usr) - strlen(value) - 1);
|
---|
363 | }
|
---|
364 | }
|
---|
365 | }
|
---|
366 | chk_account(trim(strtolower(token)), trim(value), account);
|
---|
367 | }
|
---|
368 | free(token);
|
---|
369 | fclose(fp);
|
---|
370 |
|
---|
371 | for(account = authptr; account; account = account->next){
|
---|
372 | if(account->expirationdate && account->expirationdate < time(NULL))
|
---|
373 | ++expired;
|
---|
374 | if(account->disabled)
|
---|
375 | ++disabled;
|
---|
376 | }
|
---|
377 | cs_log("userdb reloaded: %d accounts loaded, %d expired, %d disabled", nr, expired, disabled);
|
---|
378 | return authptr;
|
---|
379 | }
|
---|
380 |
|
---|
381 | int32_t init_free_userdb(struct s_auth *ptr) {
|
---|
382 | int32_t nro;
|
---|
383 | for (nro = 0; ptr; nro++) {
|
---|
384 | struct s_auth *ptr_next;
|
---|
385 | ptr_next = ptr->next;
|
---|
386 | ll_destroy(ptr->aureader_list);
|
---|
387 | ptr->next = NULL;
|
---|
388 | config_list_gc_values(account_opts, ptr);
|
---|
389 | add_garbage(ptr);
|
---|
390 | ptr = ptr_next;
|
---|
391 | }
|
---|
392 | cs_log("userdb %d accounts freed", nro);
|
---|
393 | return nro;
|
---|
394 | }
|
---|
395 |
|
---|
396 | int32_t write_userdb(void)
|
---|
397 | {
|
---|
398 | struct s_auth *account;
|
---|
399 | FILE *f = create_config_file(cs_user);
|
---|
400 | if (!f)
|
---|
401 | return 1;
|
---|
402 | for (account = cfg.account; account; account = account->next) {
|
---|
403 | fprintf(f, "[account]\n");
|
---|
404 | config_list_apply_fixups(account_opts, account);
|
---|
405 | config_list_save(f, account_opts, account, cfg.http_full_cfg);
|
---|
406 | fprintf(f, "\n");
|
---|
407 | }
|
---|
408 | return flush_config_file(f, cs_user);
|
---|
409 | }
|
---|
410 |
|
---|
411 | void cs_accounts_chk(void)
|
---|
412 | {
|
---|
413 | struct s_auth *account1,*account2;
|
---|
414 | struct s_auth *new_accounts = init_userdb();
|
---|
415 | cs_writelock(&config_lock);
|
---|
416 | struct s_auth *old_accounts = cfg.account;
|
---|
417 | for (account1 = cfg.account; account1; account1 = account1->next) {
|
---|
418 | for (account2 = new_accounts; account2; account2 = account2->next) {
|
---|
419 | if (!strcmp(account1->usr, account2->usr)) {
|
---|
420 | account2->cwfound = account1->cwfound;
|
---|
421 | account2->cwcache = account1->cwcache;
|
---|
422 | account2->cwnot = account1->cwnot;
|
---|
423 | account2->cwtun = account1->cwtun;
|
---|
424 | account2->cwignored = account1->cwignored;
|
---|
425 | account2->cwtout = account1->cwtout;
|
---|
426 | account2->emmok = account1->emmok;
|
---|
427 | account2->emmnok = account1->emmnok;
|
---|
428 | account2->firstlogin = account1->firstlogin;
|
---|
429 | ac_copy_vars(account1, account2);
|
---|
430 | }
|
---|
431 | }
|
---|
432 | }
|
---|
433 | cs_reinit_clients(new_accounts);
|
---|
434 | cfg.account = new_accounts;
|
---|
435 | init_free_userdb(old_accounts);
|
---|
436 | ac_clear();
|
---|
437 | cs_writeunlock(&config_lock);
|
---|
438 | }
|
---|