faction *gm_addfaction(const char *email, plane * p, region * r) { attrib *a; unit *u; faction *f = calloc(1, sizeof(faction)); assert(p != NULL); /* GM faction */ a_add(&f->attribs, make_key(atoi36("quest"))); f->banner = _strdup("quest faction"); f->name = _strdup("quest faction"); f->passw = _strdup(itoa36(rng_int())); if (set_email(&f->email, email) != 0) { log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), email); } f->race = new_race[RC_TEMPLATE]; f->age = 0; f->lastorders = turn; f->alive = true; f->locale = default_locale; f->options = want(O_COMPRESS) | want(O_REPORT) | want(O_COMPUTER) | want(O_ADRESSEN); { faction *xist; int id = atoi36("gm00") - 1; do { xist = findfaction(++id); } while (xist); f->no = id; addlist(&factions, f); fhash(f); } /* generic permissions */ a = a_add(&f->attribs, a_new(&at_permissions)); if (a) { attrib *ap = (attrib *) a->data.v; const char *keys[] = { "gmterf", "gmtele", "gmgive", "gmskil", "gmtake", "gmmsgr", "gmmsgu", "gmgate", 0 }; const char **key_p = keys; while (*key_p) { add_key(&ap, atoi36(*key_p)); ++key_p; } a_add(&ap, make_atgmcreate(resource2item(r_silver))); a->data.v = ap; } /* one initial unit */ u = create_unit(r, f, 1, new_race[RC_TEMPLATE], 1, "quest master", NULL); u->irace = new_race[RC_GNOME]; return f; }
static void test_forbiddenid(CuTest *tc) { CuAssertIntEquals(tc, 0, forbiddenid(1)); CuAssertIntEquals(tc, 1, forbiddenid(0)); CuAssertIntEquals(tc, 1, forbiddenid(-1)); CuAssertIntEquals(tc, 1, forbiddenid(atoi36("temp"))); CuAssertIntEquals(tc, 1, forbiddenid(atoi36("tem"))); CuAssertIntEquals(tc, 1, forbiddenid(atoi36("te"))); CuAssertIntEquals(tc, 1, forbiddenid(atoi36("t"))); }
static void test_atoi36(CuTest * tc) { CuAssertIntEquals(tc, 0, atoi36("0")); CuAssertIntEquals(tc, 666, atoi36("ii")); CuAssertIntEquals(tc, -10, atoi36("-a")); CuAssertIntEquals(tc, -1, atoi36("-1")); CuAssertIntEquals(tc, -10, atoi("-10")); CuAssertIntEquals(tc, -10, atoi("-10")); }
static void gm_messagefaction(const void *tnext, struct unit *gm, struct order *ord) { int n = getid(); faction *f = findfaction(n); const char *msg = getstrtoken(); plane *p = rplane(gm->region); attrib *permissions = a_find(gm->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) { mistake(gm, ord, "permission denied."); return; } if (f != NULL) { region *r; for (r = regions; r; r = r->next) if (rplane(r) == p) { unit *u; for (u = r->units; u; u = u->next) if (u->faction == f) { add_message(&f->msgs, msg_message("msg_event", "string", msg)); return; } } } mistake(gm, ord, "cannot send messages to this faction."); }
/** ** GM: TELL PLANE <string> ** requires: permission-key "gmmsgr" **/ static void gm_messageplane(const void *tnext, struct unit *gm, struct order *ord) { const struct plane *p = rplane(gm->region); const char *zmsg = getstrtoken(); if (p == NULL) { mistake(gm, ord, "In diese Ebene kann keine Nachricht gesandt werden."); } else { /* checking permissions */ attrib *permissions = a_find(gm->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) { mistake(gm, ord, "permission denied."); } else { message *msg = msg_message("msg_event", "string", zmsg); faction *f; region *r; for (f = factions; f; f = f->next) { freset(f, FFL_SELECT); } for (r = regions; r; r = r->next) { unit *u; if (rplane(r) != p) continue; for (u = r->units; u; u = u->next) if (!fval(u->faction, FFL_SELECT)) { f = u->faction; fset(f, FFL_SELECT); add_message(&f->msgs, msg); } } msg_release(msg); } } }
/** ** GM: TELEPORT <unit> <x> <y> ** requires: permission-key "gmtele" **/ static void gm_teleport(const void *tnext, struct unit *u, struct order *ord) { const struct plane *p = rplane(u->region); unit *to = findunit(getid()); int x = rel_to_abs(p, u->faction, getint(), 0); int y = rel_to_abs(p, u->faction, getint(), 1); region *r = findregion(x, y); if (r == NULL || p != rplane(r)) { mistake(u, ord, "region is in another plane."); } else if (to == NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", "")); } else if (rplane(to->region) != rplane(r) && !ucontact(to, u)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", "target", to)); } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmtele"))) { mistake(u, ord, "permission denied."); } else move_unit(to, r, NULL); } }
/** ** GM: TERRAFORM <x> <y> <terrain> ** requires: permission-key "gmterf" **/ static void gm_terraform(const void *tnext, struct unit *u, struct order *ord) { const struct plane *p = rplane(u->region); int x = rel_to_abs(p, u->faction, getint(), 0); int y = rel_to_abs(p, u->faction, getint(), 1); const char *c = getstrtoken(); variant token; void **tokens = get_translations(u->faction->locale, UT_TERRAINS); region *r; pnormalize(&x, &y, p); r = findregion(x, y); if (r == NULL || p != rplane(r)) { mistake(u, ord, "region is in another plane."); return; } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmterf"))) return; } if (findtoken(*tokens, c, &token) != E_TOK_NOMATCH) { const terrain_type *terrain = (const terrain_type *)token.v; terraform_region(r, terrain); } }
/** ** GM: GATE <id> <x> <y> ** requires: permission-key "gmgate" **/ static void gm_gate(const void *tnext, struct unit * u, struct order *ord) { const struct plane *pl = rplane(u->region); int id = getid(); int x = rel_to_abs(pl, u->faction, getint(), 0); int y = rel_to_abs(pl, u->faction, getint(), 1); building *b = findbuilding(id); region *r; pnormalize(&x, &y, pl); r = findregion(x, y); if (b == NULL || r == NULL || pl != rplane(b->region) || pl != rplane(r)) { mistake(u, ord, "the unit cannot transform this building."); return; } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (permissions && has_permission(permissions, atoi36("gmgate"))) { remove_triggers(&b->attribs, "timer", &tt_gate); remove_triggers(&b->attribs, "create", &tt_unguard); if (r != b->region) { add_trigger(&b->attribs, "timer", trigger_gate(b, r)); add_trigger(&b->attribs, "create", trigger_unguard(b)); fset(b, BLD_UNGUARDED); } } } }
/** ** GM: KILL FACTION <id> <string> ** requires: permission-key "gmmsgr" **/ static void gm_killfaction(const void *tnext, struct unit *u, struct order *ord) { int n = getid(); faction *f = findfaction(n); const char *msg = getstrtoken(); plane *p = rplane(u->region); attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmkill"))) { mistake(u, ord, "permission denied."); return; } if (f != NULL) { region *r; for (r = regions; r; r = r->next) if (rplane(r) == p) { unit *target; for (target = r->units; target; target = target->next) { if (target->faction == f) { scale_number(target, 0); ADDMSG(&target->faction->msgs, msg_message("killedbygm", "region unit string", r, target, msg)); return; } } } } mistake(u, ord, "cannot remove a unit from this faction."); }
/** ** GM: SKILL <unit> <skill> <tage> ** requires: permission-key "gmskil" **/ static void gm_skill(const void *tnext, struct unit *u, struct order *ord) { unit *to = findunit(getid()); skill_t skill = findskill(getstrtoken(), u->faction->locale); int num = getint(); if (to == NULL || rplane(to->region) != rplane(u->region)) { /* unknown or in another plane */ ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", "")); } else if (skill == NOSKILL || skill == SK_MAGIC || skill == SK_ALCHEMY) { /* unknown or not enough */ mistake(u, ord, "unknown skill, or skill cannot be raised."); } else if (num < 0 || num > 30) { /* sanity check failed */ mistake(u, ord, "invalid value."); } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmskil"))) { mistake(u, ord, "permission denied."); } else { set_level(to, skill, num); } } }
static struct quicklist * read_factions(sqlite3 * db, int game_id) { int res; quicklist *result = 0; const char * sql = "SELECT f.id, fd.code, fd.name, fd.email FROM faction f" " LEFT OUTER JOIN faction_data fd" " WHERE f.id=fd.faction_id AND f.game_id=? AND" " fd.turn=(SELECT MAX(turn) FROM faction_data fx WHERE fx.faction_id=f.id)" " ORDER BY f.id"; sqlite3_stmt *stmt = 0; sqlite3_prepare_v2(db, sql, -1, &stmt, 0); sqlite3_bind_int(stmt, 1, game_id); res = sqlite3_step(stmt); while (res == SQLITE_ROW) { const char * text; db_faction * dbf = (db_faction*)calloc(1, sizeof(db_faction)); dbf->uid = (int)sqlite3_column_int64(stmt, 0); text = (const char *)sqlite3_column_text(stmt, 1); if (text) dbf->no = atoi36(text); text = (const char *)sqlite3_column_text(stmt, 2); if (text) dbf->name = _strdup(text); text = (const char *)sqlite3_column_text(stmt, 3); if (text) dbf->email = _strdup(text); ql_push(&result, dbf); res = sqlite3_step(stmt); } sqlite3_finalize(stmt); return result; }
/** ** GM: TAKE <unit> <int> <itemtype> ** requires: permission-key "gmtake" **/ static void gm_take(const void *tnext, struct unit *u, struct order *ord) { unit *to = findunit(getid()); int num = getint(); const item_type *itype = finditemtype(getstrtoken(), u->faction->locale); if (to == NULL || rplane(to->region) != rplane(u->region)) { /* unknown or in another plane */ ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", "")); } else if (itype == NULL || i_get(to->items, itype) == 0) { /* unknown or not enough */ mistake(u, ord, "invalid item or item not found."); } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmtake"))) { mistake(u, ord, "permission denied."); } else { int i = i_get(to->items, itype); if (i < num) num = i; if (num) { i_change(&to->items, itype, -num); i_change(&u->items, itype, num); } } } }
/** ** GM: TELL <unit> <string> ** requires: permission-key "gmmsgr" **/ static void gm_messageunit(const void *tnext, struct unit *u, struct order *ord) { const struct plane *p = rplane(u->region); unit *target = findunit(getid()); const char *msg = getstrtoken(); region *r; if (target == NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", "")); return; } r = target->region; if (r == NULL || p != rplane(r)) { mistake(u, ord, "region is in another plane."); } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmmsgu"))) { mistake(u, ord, "permission denied."); } else { add_message(&target->faction->msgs, msg_message("regionmessage", "region sender string", r, u, msg)); } } }
static int tolua_region_getkey(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); int flag = atoi36(name); lua_pushboolean(L, key_get(self->attribs, flag)); return 1; }
int getid(void) { char token[8]; const char *str = gettoken(token, sizeof(token)); int i = str ? atoi36(str) : 0; if (i < 0) { return -1; } return i; }
static int use_museumexitticket(unit * u, const struct item_type *itype, int amount, order * ord) { attrib *a; region *r; unit *warden = findunit(atoi36("mwar")); int unit_cookie; unused_arg(amount); /* Prüfen ob in Eingangshalle */ if (u->region->x != 9525 || u->region->y != 9525) { cmistake(u, ord, 266, MSG_MAGIC); return 0; } a = a_find(u->attribs, &at_museumexit); assert(a); r = findregion(a->data.sa[0], a->data.sa[1]); assert(r); a_remove(&u->attribs, a); /* Übergebene Gegenstände zurückgeben */ a = a_find(u->attribs, &at_museumgivebackcookie); if (a) { unit_cookie = a->data.i; a_remove(&u->attribs, a); for (a = a_find(warden->attribs, &at_museumgiveback); a && a->type == &at_museumgiveback; a = a->next) { if (((museumgiveback *)(a->data.v))->cookie == unit_cookie) break; } if (a && a->type == &at_museumgiveback) { museumgiveback *gb = (museumgiveback *)(a->data.v); item *it; for (it = gb->items; it; it = it->next) { i_change(&u->items, it->type, it->number); } ADDMSG(&u->faction->msgs, msg_message("museumgiveback", "region unit sender items", r, u, warden, gb->items)); a_remove(&warden->attribs, a); } } /* Benutzer zurück teleportieren */ move_unit(u, r, NULL); /* Exitticket abziehen */ i_change(&u->items, itype, -1); return 0; }
static void test_upgrade_dict(CuTest *tc) { attrib *a; a = a_new(&at_dict); dict_set(a, "embassy_muschel", 42); CuAssertPtrNotNull(tc, a->type->upgrade); a->type->upgrade(&a, a); CuAssertIntEquals(tc, 42, key_get(a, atoi36("mupL"))); a_removeall(&a, NULL); }
int tolua_toid(lua_State * L, int idx, int def) { int no = 0; int type = lua_type(L, idx); if (type == LUA_TNUMBER) { no = (int)tolua_tonumber(L, idx, def); } else { const char *str = tolua_tostring(L, idx, NULL); no = str ? atoi36(str) : def; } return no; }
int *parse_ids(const order *ord) { const char *s; int *il = NULL; init_order(ord); s = getstrtoken(); if (s != NULL && *s) { il = intlist_init(); while (s && *s) { il = intlist_add(il, atoi36(s)); s = getstrtoken(); } } return il; }
static int tolua_region_setkey(lua_State * L) { region *self = (region *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); int value = tolua_toboolean(L, 3, 0); int flag = atoi36(name); if (value) { key_set(&self->attribs, flag); } else { key_unset(&self->attribs, flag); } return 0; }
static int tolua_region_setkey(lua_State * L) { region *self = (region *) tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); int value = tolua_toboolean(L, 3, 0); int flag = atoi36(name); attrib *a = find_key(self->attribs, flag); if (a == NULL && value) { add_key(&self->attribs, flag); } else if (a != NULL && !value) { a_remove(&self->attribs, a); } return 0; }
static void test_getunit(CuTest *tc) { unit *u, *u2; order *ord; attrib *a; struct region *r; struct locale *lang; struct terrain_type *t_plain; test_cleanup(); lang = get_or_create_locale("de"); test_translate_param(lang, P_TEMP, "TEMP"); /* note that the english order is FIGHT, not COMBAT, so this is a poor example */ t_plain = test_create_terrain("plain", LAND_REGION); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, t_plain)); a = a_add(&u->attribs, a_new(&at_alias)); a->data.i = atoi36("42"); /* this unit is also TEMP 42 */ r = test_create_region(1, 0, t_plain); ord = create_order(K_GIVE, lang, itoa36(u->no)); init_order(ord); CuAssertIntEquals(tc, GET_UNIT, getunit(u->region, u->faction, &u2)); CuAssertPtrEquals(tc, u, u2); init_order(ord); CuAssertIntEquals(tc, GET_NOTFOUND, getunit(r, u->faction, &u2)); CuAssertPtrEquals(tc, NULL, u2); free_order(ord); ord = create_order(K_GIVE, lang, itoa36(u->no + 1)); init_order(ord); CuAssertIntEquals(tc, GET_NOTFOUND, getunit(u->region, u->faction, &u2)); CuAssertPtrEquals(tc, NULL, u2); free_order(ord); ord = create_order(K_GIVE, lang, "0"); init_order(ord); CuAssertIntEquals(tc, GET_PEASANTS, getunit(u->region, u->faction, &u2)); CuAssertPtrEquals(tc, NULL, u2); free_order(ord); ord = create_order(K_GIVE, lang, "TEMP 42"); init_order(ord); CuAssertIntEquals(tc, GET_UNIT, getunit(u->region, u->faction, &u2)); CuAssertPtrEquals(tc, u, u2); free_order(ord); test_cleanup(); }
static void test_read_unitid(CuTest *tc) { unit *u; order *ord; attrib *a; struct locale *lang; struct terrain_type *t_plain; test_cleanup(); lang = get_or_create_locale("de"); test_translate_param(lang, P_TEMP, "TEMP"); /* note that the english order is FIGHT, not COMBAT, so this is a poor example */ t_plain = test_create_terrain("plain", LAND_REGION); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, t_plain)); a = a_add(&u->attribs, a_new(&at_alias)); a->data.i = atoi36("42"); /* this unit is also TEMP 42 */ ord = create_order(K_GIVE, lang, "TEMP 42"); init_order(ord); CuAssertIntEquals(tc, u->no, read_unitid(u->faction, u->region)); free_order(ord); ord = create_order(K_GIVE, lang, "8"); init_order(ord); CuAssertIntEquals(tc, 8, read_unitid(u->faction, u->region)); free_order(ord); ord = create_order(K_GIVE, lang, ""); init_order(ord); CuAssertIntEquals(tc, -1, read_unitid(u->faction, u->region)); free_order(ord); ord = create_order(K_GIVE, lang, "TEMP"); init_order(ord); CuAssertIntEquals(tc, -1, read_unitid(u->faction, u->region)); free_order(ord); // bug https://bugs.eressea.de/view.php?id=1685 ord = create_order(K_GIVE, lang, "##"); init_order(ord); CuAssertIntEquals(tc, -1, read_unitid(u->faction, u->region)); free_order(ord); test_cleanup(); }
/** ** GM: TELL REGION <x> <y> <string> ** requires: permission-key "gmmsgr" **/ static void gm_messageregion(const void *tnext, struct unit *u, struct order *ord) { const struct plane *p = rplane(u->region); int x = rel_to_abs(p, u->faction, getint(), 0); int y = rel_to_abs(p, u->faction, getint(), 1); const char *msg = getstrtoken(); region *r = findregion(x, y); if (r == NULL || p != rplane(r)) { mistake(u, ord, "region is in another plane."); } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmmsgr"))) { mistake(u, ord, "permission denied."); } else { add_message(&r->msgs, msg_message("msg_event", "string", msg)); } } }
/** ** GM: KILL UNIT <id> <string> ** requires: permission-key "gmkill" **/ static void gm_killunit(const void *tnext, struct unit *u, struct order *ord) { const struct plane *p = rplane(u->region); unit *target = findunit(getid()); const char *msg = getstrtoken(); region *r = target->region; if (r == NULL || p != rplane(r)) { mistake(u, ord, "region is in another plane."); } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmkill"))) { mistake(u, ord, "permission denied."); } else { scale_number(target, 0); ADDMSG(&target->faction->msgs, msg_message("killedbygm", "region unit string", r, target, msg)); } } }
static bool has_permission(const attrib * permissions, unsigned int key) { return (find_key((attrib *) permissions->data.v, key) || find_key((attrib *) permissions->data.v, atoi36("master"))); }
int db_update_factions(sqlite3 * db, bool force) { int game_id = 6; const char sql_select[] = "SELECT faction.id, faction.email_id, faction.code, email.email, faction.password_md5, faction.name, faction.lastturn FROM email, faction" " WHERE email.id=faction.email_id AND faction.game_id=? AND (lastturn IS NULL OR lastturn>?)"; sqlite3_stmt *stmt_select = stmt_cache_get(db, sql_select); faction *f; int res; res = sqlite3_bind_int(stmt_select, 1, game_id); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_bind_int(stmt_select, 2, turn - 2); SQL_EXPECT(res, SQLITE_OK); for (;;) { sqlite3_uint64 id_faction; int lastturn; res = sqlite3_step(stmt_select); if (res != SQLITE_ROW) break; id_faction = sqlite3_column_int64(stmt_select, 0); lastturn = sqlite3_column_int(stmt_select, 6); f = get_faction_by_id((int)id_faction); if (f == NULL || !f->alive) { if (lastturn == 0) { const char sql_update[] = "UPDATE faction SET lastturn=? WHERE id=?"; sqlite3_stmt *stmt = stmt_cache_get(db, sql_update); lastturn = f ? f->lastorders : turn - 1; sqlite3_bind_int(stmt, 1, lastturn); sqlite3_bind_int64(stmt, 2, id_faction); res = sqlite3_step(stmt); SQL_EXPECT(res, SQLITE_DONE); } } else { md5_state_t ms; md5_byte_t digest[16]; int i; char passwd_md5[MD5_LENGTH_0]; sqlite3_uint64 id_email; bool update = force; db_faction dbstate; const char *no_b36; fset(f, FFL_MARK); dbstate.id_faction = id_faction; dbstate.id_email = sqlite3_column_int64(stmt_select, 1); no_b36 = (const char *)sqlite3_column_text(stmt_select, 2); dbstate.no = no_b36 ? atoi36(no_b36) : -1; dbstate.email = (const char *)sqlite3_column_text(stmt_select, 3); dbstate.passwd_md5 = (const char *)sqlite3_column_text(stmt_select, 4); dbstate.name = (const char *)sqlite3_column_text(stmt_select, 5); id_email = dbstate.id_email; res = db_update_email(db, f, &dbstate, force, &id_email); SQL_EXPECT(res, SQLITE_OK); md5_init(&ms); md5_append(&ms, (md5_byte_t *) f->passw, (int)strlen(f->passw)); md5_finish(&ms, digest); for (i = 0; i != 16; ++i) sprintf(passwd_md5 + 2 * i, "%.02x", digest[i]); if (!update) { update = ((id_email != 0 && dbstate.id_email != id_email) || dbstate.no != f->no || dbstate.passwd_md5 == NULL || strcmp(passwd_md5, dbstate.passwd_md5) != 0 || dbstate.name == NULL || strncmp(f->name, dbstate.name, MAX_FACTION_NAME) != 0); } if (update) { const char sql_update_faction[] = "UPDATE faction SET email_id=?, password_md5=?, code=?, name=?, firstturn=? WHERE id=?"; sqlite3_stmt *stmt_update_faction = stmt_cache_get(db, sql_update_faction); res = sqlite3_bind_int64(stmt_update_faction, 1, id_email); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_bind_text(stmt_update_faction, 2, passwd_md5, MD5_LENGTH, SQLITE_TRANSIENT); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_bind_text(stmt_update_faction, 3, no_b36, -1, SQLITE_TRANSIENT); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_bind_text(stmt_update_faction, 4, f->name, -1, SQLITE_TRANSIENT); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_bind_int(stmt_update_faction, 5, turn - f->age); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_bind_int64(stmt_update_faction, 6, f->subscription); SQL_EXPECT(res, SQLITE_OK); res = sqlite3_step(stmt_update_faction); SQL_EXPECT(res, SQLITE_DONE); } } } for (f = factions; f; f = f->next) { if (!fval(f, FFL_MARK)) { log_error("%s (sub=%d, email=%s) has no entry in the database\n", factionname(f), f->subscription, f->email); } else { freset(f, FFL_MARK); } } return SQLITE_OK; }