/* * Figure out the next frame up in the call stack. * For trap(), we print the address of the faulting instruction and * proceed with the calling frame. We return the ip that faulted. * If the trap was caused by jumping through a bogus pointer, then * the next line in the backtrace will list some random function as * being called. It should get the argument list correct, though. * It might be possible to dig out from the next frame up the name * of the function that faulted, but that could get hairy. */ void db_nextframe(struct x86_64_frame **fp, db_addr_t *ip, long *argp, int is_trap, int (*pr)(const char *, ...)) { switch (is_trap) { case NONE: *ip = (db_addr_t) db_get_value((db_addr_t)&(*fp)->f_retaddr, 8, FALSE); *fp = (struct x86_64_frame *) db_get_value((db_addr_t)&(*fp)->f_frame, 8, FALSE); break; default: { struct trapframe *tf; /* The only argument to trap() or syscall() is the trapframe. */ tf = (struct trapframe *)argp; switch (is_trap) { case TRAP: (*pr)("--- trap (number %d) ---\n", tf->tf_trapno); break; case SYSCALL: (*pr)("--- syscall (number %ld) ---\n", tf->tf_rax); break; case INTERRUPT: (*pr)("--- interrupt ---\n"); break; } *fp = (struct x86_64_frame *)tf->tf_rbp; *ip = (db_addr_t)tf->tf_rip; break; } } }
int web_fav(void) { if (!session_id()) return BBS_ELGNREQ; xml_header(NULL); printf("<bbsfav>"); print_session(); db_res_t *res = db_query("SELECT b.id, b.name, b.descr FROM boards b" " JOIN fav_boards f ON b.id = f.board WHERE f.user_id = %d", session_uid()); if (res) { for (int i = 0; i < db_res_rows(res); ++i) { int bid = db_get_integer(res, i, 0); const char *name = db_get_value(res, i, 1); GBK_BUFFER(descr, BOARD_DESCR_CCHARS); convert_u2g(db_get_value(res, i, 2), gbk_descr); printf("<brd bid='%d' brd='%s'>", bid, name); xml_fputs(gbk_descr); printf("</brd>"); } } db_clear(res); printf("</bbsfav>"); return 0; }
int bbssec_main(void) { db_res_t *r1 = db_query("SELECT id, name, descr, short_descr" " FROM board_sectors ORDER BY name ASC"); if (!r1) return BBS_EINVAL; db_res_t *res = db_query("SELECT b.name, b.descr, b.sector" " FROM boards b JOIN board_sectors s ON b.sector = s.id" " WHERE b.flag & %d <> 0", BOARD_FLAG_RECOMMEND); if (!res) { db_clear(r1); return BBS_EINVAL; } xml_header(NULL); printf("<bbssec>"); print_session(); int last = -1; for (int i = 0; i < db_res_rows(r1); ++i) { printf("<sec id='%s' desc='%s [%s]'>", db_get_value(r1, i, 1), db_get_value(r1, i, 2), db_get_value(r1, i, 3)); int sid = db_get_integer(r1, i, 0); last = show_sector(sid, res, last); printf("</sec>"); } db_clear(res); db_clear(r1); printf("</bbssec>"); return 0; }
static void _fill_session_array(tui_list_t *p, int i) { online_users_t *up = p->data; db_res_t *res = up->res; bool visible = db_get_bool(res, i, 3); if (!visible && !HAS_PERM(PERM_SEECLOAK)) return; session_id_t sid = db_get_session_id(res, i, 0); if (up->bid && session_get_board(sid) != up->bid) return; online_user_info_t *ip = up->users + up->num; memset(ip, 0, sizeof(*ip)); ip->sid = sid; ip->name = db_get_value(res, i, 2); ip->host = db_get_value(res, i, 4); ip->note = up->follow ? db_get_value(res, i, 6) : NULL; ip->uid = db_get_user_id(res, i, 1); ip->flag = (db_get_bool(res, i, 5) ? SESSION_FLAG_WEB : 0) | (visible ? 0 : SESSION_FLAG_INVISIBLE); ++up->num; }
INT ana_end_of_run(INT run_number, char *error) { FILE *f; time_t now; char str[256]; int size; double n; HNDLE hDB; BOOL flag; cm_get_experiment_database(&hDB, NULL); /* update run log if run was written and running online */ size = sizeof(flag); db_get_value(hDB, 0, "/Logger/Write data", &flag, &size, TID_BOOL, TRUE); if (flag && runinfo.online_mode == 1) { /* update run log */ size = sizeof(str); str[0] = 0; db_get_value(hDB, 0, "/Logger/Data Dir", str, &size, TID_STRING, TRUE); if (str[0] != 0) if (str[strlen(str) - 1] != DIR_SEPARATOR) strcat(str, DIR_SEPARATOR_STR); strcat(str, "runlog.txt"); f = fopen(str, "a"); time(&now); strcpy(str, ctime(&now)); str[10] = 0; fprintf(f, "%s\t%3d\t", str, runinfo.run_number); strcpy(str, runinfo.start_time); str[19] = 0; fprintf(f, "%s\t", str + 11); strcpy(str, ctime(&now)); str[19] = 0; fprintf(f, "%s\t", str + 11); size = sizeof(n); db_get_value(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &n, &size, TID_DOUBLE, TRUE); fprintf(f, "%5.1lfk\t", n / 1000); fprintf(f, "%s\n", exp_param.comment); fclose(f); } return CM_SUCCESS; }
void db_restart_at_pc(db_regs_t *regs, bool watchpt) { db_addr_t pc = PC_REGS(regs); #ifdef SOFTWARE_SSTEP db_addr_t brpc; #endif if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) || (db_run_mode == STEP_CALLT)) { db_expr_t ins __unused; /* * We are about to execute this instruction, * so count it now. */ ins = db_get_value(pc, sizeof(int), false); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); #ifdef SOFTWARE_SSTEP /* * Account for instructions in delay slots. */ brpc = next_instr_address(pc, true); if ((brpc != pc) && (inst_branch(ins) || inst_call(ins) || inst_return(ins))) { ins = db_get_value(brpc, sizeof(int), false); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); } #endif } if (db_run_mode == STEP_CONTINUE) { if (watchpt || db_find_breakpoint_here(pc)) { /* * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; db_set_single_step(regs); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { db_set_single_step(regs); } }
//-------------------------------- // look up a first name and return the id number // returns 0 if error // // int db_get_id(char* firstname) { int id; char id_string[20], name[20]; char key[80]; int result; for(id=1; id<1000; id++) { snprintf (id_string, sizeof(id_string), "%d",id); // convert id number from integer to string (integer, string, base) sprintf(key, "#%s > firstname", id_string); result = db_get_value(key, name); // look up the first name if(result==FOUND) { result = strcmp(name, firstname); if(result==0) { // That's the entity we're looking for return id; } // That's not the entity we're looking for, so try again else { continue; } } } return 0; // database size limit reached (DGI) }
boolean_t db_unary(db_expr_t *valuep) { int t; t = db_read_token(); if (t == tMINUS) { if (!db_unary(valuep)) { db_error("Syntax error\n"); /*NOTREACHED*/ } *valuep = -*valuep; return (TRUE); } if (t == tSTAR) { /* indirection */ if (!db_unary(valuep)) { db_error("Syntax error\n"); /*NOTREACHED*/ } *valuep = db_get_value((db_addr_t)*valuep, sizeof(int), FALSE); return (TRUE); } db_unread_token(t); return (db_term(valuep)); }
void db_set_single_step(db_regs_t *regs) { db_addr_t pc = PC_REGS(regs); #ifndef SOFTWARE_SSTEP_EMUL db_addr_t brpc; u_int inst; /* * User was stopped at pc, e.g. the instruction * at pc was not executed. */ inst = db_get_value(pc, sizeof(int), FALSE); if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) { brpc = branch_taken(inst, pc, getreg_val, regs); if (brpc != pc) { /* self-branches are hopeless */ db_taken_bkpt = db_set_temp_breakpoint(brpc); } #if 0 /* XXX this seems like a true bug, no? */ pc = next_instr_address(pc, 1); #endif } #endif /*SOFTWARE_SSTEP_EMUL*/ pc = next_instr_address(pc, 0); db_not_taken_bkpt = db_set_temp_breakpoint(pc); }
/* * Set a temporary breakpoint. * The instruction is changed immediately, * so the breakpoint does not have to be on the breakpoint list. */ db_breakpoint_t db_set_temp_breakpoint(db_addr_t addr) { db_breakpoint_t bkpt; #ifdef DB_VALID_BREAKPOINT if (!DB_VALID_BREAKPOINT(addr)) { db_printf("Not a valid address for a breakpoint.\n"); return (0); } #endif bkpt = db_breakpoint_alloc(); if (bkpt == 0) { db_printf("Too many breakpoints.\n"); return (0); } bkpt->address = addr; bkpt->flags = BKPT_TEMP; bkpt->init_count = 1; bkpt->count = 1; bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE); db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst)); return bkpt; }
void db_restart_at_pc(boolean_t watchpt) { db_addr_t pc = PC_REGS(DDB_REGS); if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) || (db_run_mode == STEP_CALLT)) { db_expr_t ins __unused; /* seems used but gcc thinks not */ /* * We are about to execute this instruction, * so count it now. */ ins = db_get_value(pc, sizeof(int), FALSE); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); #ifdef SOFTWARE_SSTEP /* XXX works on mips, but... */ if (inst_branch(ins) || inst_call(ins)) { ins = db_get_value(next_instr_address(pc,1), sizeof(int), FALSE); db_inst_count++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); } #endif /* SOFTWARE_SSTEP */ } if (db_run_mode == STEP_CONTINUE) { if (watchpt || db_find_breakpoint_here(pc)) { /* * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; db_set_single_step(DDB_REGS); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { db_set_single_step(DDB_REGS); } }
/*ARGSUSED*/ void db_write_cmd(db_expr_t address, boolean_t have_addr, db_expr_t count, char *modif) { db_addr_t addr; db_expr_t old_value; db_expr_t new_value; int size; boolean_t wrote_one = FALSE; char tmpfmt[28]; addr = (db_addr_t) address; switch (modif[0]) { case 'b': size = 1; break; case 'h': size = 2; break; case 'l': case '\0': size = 4; break; #ifdef __LP64__ case 'q': size = 8; break; #endif default: size = -1; db_error("Unknown size\n"); /*NOTREACHED*/ } while (db_expression(&new_value)) { old_value = db_get_value(addr, size, FALSE); db_printsym(addr, DB_STGY_ANY, db_printf); db_printf("\t\t%s\t", db_format(tmpfmt, sizeof tmpfmt, old_value, DB_FORMAT_N, 0, 8)); db_printf("=\t%s\n", db_format(tmpfmt, sizeof tmpfmt, new_value, DB_FORMAT_N, 0, 8)); db_put_value(addr, size, new_value); addr += size; wrote_one = TRUE; } if (!wrote_one) { db_error("Nothing written.\n"); /*NOTREACHED*/ } db_next = addr; db_prev = addr - size; db_skip_to_eol(); }
//----------------------------------------------------------------------- // // ex: // db_check("cat"); // int db_check(char* subject){ char key[60]; char value[20]; sprintf(key, "%s > class", subject); return db_get_value(key, value); // lookup }
/*ARGSUSED*/ void db_write_cmd(db_expr_t address, bool have_addr, db_expr_t count, const char *modif) { db_addr_t addr; db_expr_t old_value; db_expr_t new_value; int size; bool wrote_one; bool show_old_val; addr = (db_addr_t) address; wrote_one = false; show_old_val = islower((unsigned char)modif[0]); switch (tolower((unsigned char)modif[0])) { case 'b': size = 1; break; case 'h': size = 2; break; case 'l': case '\0': size = 4; break; default: size = -1; db_error("Unknown size\n"); /*NOTREACHED*/ } while (db_expression(&new_value)) { db_printsym(addr, DB_STGY_ANY, db_printf); if (show_old_val) { old_value = db_get_value(addr, size, false); db_printf("\t\t%s = ", db_num_to_str(old_value)); db_printf("%s\n", db_num_to_str(new_value)); } else db_printf("\t\t= %s\n", db_num_to_str(new_value)); db_put_value(addr, size, new_value); addr += size; wrote_one = true; } if (!wrote_one) { db_error("Nothing written.\n"); /*NOTREACHED*/ } db_next = addr; db_prev = addr - size; db_skip_to_eol(); }
static int show_sector(int sid, db_res_t *res, int last) { for (int i = last + 1; i < db_res_rows(res); ++i) { int sector = db_get_integer(res, i, 2); if (sector == sid) { last = i; const char *utf8_descr = db_get_value(res, i, 1); GBK_BUFFER(descr, BOARD_DESCR_CCHARS); if (!web_request_type(UTF8)) { convert_u2g(utf8_descr, gbk_descr); } printf("<brd name='%s' desc='%s'/>", db_get_value(res, i, 0), web_request_type(UTF8) ? utf8_descr : gbk_descr); } } return last; }
/* * Figure out how many arguments were passed into the frame at "fp". */ int db_numargs(struct i386_frame *fp) { int *argp; int inst; int args; extern char etext[]; argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE); if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext) { args = 5; } else { inst = db_get_value((int)argp, 4, FALSE); if ((inst & 0xff) == 0x59) /* popl %ecx */ args = 1; else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */ args = ((inst >> 16) & 0xff) / 4; else args = 5; }
static void db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask, unsigned int count) { while (count-- != 0) { db_prev = addr; if ((db_get_value(addr, size, false) & mask) == value) break; addr += size; } db_next = addr; }
void db_set_single_step(db_regs_t *regs) { db_addr_t pc = PC_REGS(regs), brpc = pc; bool unconditional; unsigned int inst; /* * User was stopped at pc, e.g. the instruction * at pc was not executed. */ inst = db_get_value(pc, sizeof(int), false); if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) { brpc = branch_taken(inst, pc, regs); if (brpc != pc) { /* self-branches are hopeless */ db_set_temp_breakpoint(&db_taken_bkpt, brpc); } else db_taken_bkpt.address = 0; pc = next_instr_address(pc, true); } /* * Check if this control flow instruction is an * unconditional transfer. */ unconditional = inst_unconditional_flow_transfer(inst); pc = next_instr_address(pc, false); /* * We only set the sequential breakpoint if previous * instruction was not an unconditional change of flow * control. If the previous instruction is an * unconditional change of flow control, setting a * breakpoint in the next sequential location may set * a breakpoint in data or in another routine, which * could screw up in either the program or the debugger. * (Consider, for instance, that the next sequential * instruction is the start of a routine needed by the * debugger.) * * Also, don't set both the taken and not-taken breakpoints * in the same place even if the MD code would otherwise * have us do so. */ if (unconditional == false && db_find_breakpoint_here(pc) == 0 && pc != brpc) db_set_temp_breakpoint(&db_not_taken_bkpt, pc); else db_not_taken_bkpt.address = 0; }
void db_search(db_addr_t addr, int size, db_expr_t value, db_expr_t mask, db_expr_t count) { /* Negative counts means forever. */ while (count < 0 || count-- != 0) { db_prev = addr; if ((db_get_value(addr, size, FALSE) & mask) == value) break; addr += size; } db_next = addr; }
static void show_sessions_of_friends(void) { db_res_t *res = session_get_followed(); if (!res) return; fb_time_t now = fb_time(); for (int i = 0; i < db_res_rows(res); ++i) { bool visible = db_get_bool(res, i, 3); if (!visible && !HAS_PERM(PERM_SEECLOAK)) continue; session_id_t sid = db_get_session_id(res, i, 0); const char *uname = db_get_value(res, i, 2); const char *ip = db_get_value(res, i, 4); fb_time_t refresh = session_get_idle(sid); int status = get_user_status(sid); struct userec user; getuserec(uname, &user); int idle; if (refresh < 1 || status == ST_BBSNET) idle = 0; else idle = (now - refresh) / 60; if (HAS_DEFINE(user.userdefine, DEF_NOTHIDEIP)) ip = mask_host(ip); else ip = "......"; printf("<ov id='%s' action='%s' idle='%d' ip='%s'>", uname, session_status_descr(status), idle, ip); xml_fputs(user.username); printf("</ov>"); } db_clear(res); }
/** Scan ODB for alarms. @return AL_SUCCESS */ INT al_get_alarms(char *result, int result_size) { HNDLE hDB, hkey, hsubkey; int i, j, n, flag, size; char alarm_class[32], msg[256], value_str[256], str[256]; cm_get_experiment_database(&hDB, NULL); result[0] = 0; n = 0; db_find_key(hDB, 0, "/Alarms/Alarms", &hkey); if (hkey) { /* check global alarm flag */ flag = TRUE; size = sizeof(flag); db_get_value(hDB, 0, "/Alarms/Alarm System active", &flag, &size, TID_BOOL, TRUE); if (flag) { for (i = 0;; i++) { db_enum_link(hDB, hkey, i, &hsubkey); if (!hsubkey) break; size = sizeof(flag); db_get_value(hDB, hsubkey, "Triggered", &flag, &size, TID_INT, TRUE); if (flag) { n++; size = sizeof(alarm_class); db_get_value(hDB, hsubkey, "Alarm Class", alarm_class, &size, TID_STRING, TRUE); size = sizeof(msg); db_get_value(hDB, hsubkey, "Alarm Message", msg, &size, TID_STRING, TRUE); size = sizeof(j); db_get_value(hDB, hsubkey, "Type", &j, &size, TID_INT, TRUE); if (j == AT_EVALUATED) { size = sizeof(str); db_get_value(hDB, hsubkey, "Condition", str, &size, TID_STRING, TRUE); /* retrieve value */ al_evaluate_condition(str, value_str); sprintf(str, msg, value_str); } else strlcpy(str, msg, sizeof(str)); strlcat(result, alarm_class, result_size); strlcat(result, ": ", result_size); strlcat(result, str, result_size); strlcat(result, "\n", result_size); } } } } return n; }
void db_set_temp_breakpoint(db_breakpoint_t bkpt, db_addr_t addr) { bkpt->map = NULL; bkpt->address = addr; /* bkpt->flags = BKPT_TEMP; - this is not used */ bkpt->init_count = 1; bkpt->count = 1; bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, false); db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst, bkpt->address)); }
/* { groups: [ { name: OPTIONAL TEXT, descr: OPTIONAL TEXT, boards: [ { id: INTEGER, name: TEXT, unread: OPTIONAL BOOLEAN }, ... ] }, ... ] } */ int api_board_fav(void) { if (!session_id()) return WEB_ERROR_LOGIN_REQUIRED; xml_node_t *root = set_response_root("bbs-board-fav", XML_NODE_ANONYMOUS_JSON, XML_ENCODING_UTF8); xml_node_t *groups = xml_new_node("groups", XML_NODE_CHILD_ARRAY); xml_add_child(root, groups); query_t *q = query_new(0); query_select(q, "board, name, folder"); query_from(q, "fav_boards"); query_where(q, "user_id = %"DBIdUID, session_uid()); db_res_t *boards = query_exec(q); q = query_new(0); query_select(q, "id, name, descr"); query_from(q, "fav_board_folders"); query_where(q, "user_id = %"DBIdUID, session_uid()); db_res_t *folders = query_exec(q); if (folders && boards) { attach_group(groups, boards, FAV_BOARD_ROOT_FOLDER); for (int i = db_res_rows(folders) - 1; i >= 0; --i) { int id = db_get_integer(folders, i, 0); xml_node_t *group = attach_group(groups, boards, id); xml_attr_string(group, "name", db_get_value(folders, i, 1), true); xml_attr_string(group, "descr", db_get_value(folders, i, 2), true); } } db_clear(folders); db_clear(boards); return WEB_OK; }
void db_set_breakpoints(void) { db_breakpoint_t bkpt; if (!db_breakpoints_inserted) { for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE); db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst)); } db_breakpoints_inserted = TRUE; } }
int main() { int status, size; HNDLE hDB, hKey; /* connect to experiment */ status = cm_connect_experiment("", "", "ODBTest", NULL); if (status != CM_SUCCESS) return 1; /* get handle to online database */ cm_get_experiment_database(&hDB, &hKey); /* read key "runinfo/run number" */ size = sizeof(run_number); status = db_get_value(hDB, 0, "/runinfo/run number", &run_number, &size, TID_INT, TRUE); if (status != DB_SUCCESS) { printf("Cannot read run number"); return 0; } printf("Current run number is %d\n", run_number); /* set new run number */ run_number++; db_set_value(hDB, 0, "/runinfo/run number", &run_number, size, 1, TID_INT); /* now open run_number with automatic updates */ db_find_key(hDB, 0, "/runinfo/run number", &hKey); db_open_record(hDB, hKey, &run_number, sizeof(run_number), MODE_READ, run_number_changed, NULL); printf("Waiting for run number to change. Hit RETURN to abort\n"); do { cm_yield(1000); } while (!ss_kbhit()); db_close_record(hDB, hKey); /* disconnect from experiment */ cm_disconnect_experiment(); return 1; }
/*ARGSUSED*/ void db_write_cmd(db_expr_t address, boolean_t have_addr, db_expr_t count, char *modif) { db_addr_t addr; db_expr_t old_value; db_expr_t new_value; int size; boolean_t wrote_one = FALSE; addr = (db_addr_t) address; switch (modif[0]) { case 'b': size = 1; break; case 'h': size = 2; break; case 'l': case '\0': size = 4; break; default: db_error("Unknown size\n"); return; } while (db_expression(&new_value)) { old_value = db_get_value(addr, size, FALSE); db_printsym(addr, DB_STGY_ANY); db_printf("\t\t%s = ", db_num_to_str(old_value)); db_printf("%s\n", db_num_to_str(new_value)); db_put_value(addr, size, new_value); addr += size; wrote_one = TRUE; } if (!wrote_one) db_error("Nothing written.\n"); db_next = addr; db_prev = addr - size; db_skip_to_eol(); }
int db_next_available_id(void){ int i; char value[20]; int result; char key[20], id_string[20]; char output[80]; for(i=1; i<1000; i++){ // look for id snprintf(key, sizeof(key), "#%d > class", i); // ex: "#23 > class" if(db_get_value(key,value) != FOUND){ return i; } } sprintf(output, "error in function DNAI"); stioc(output); return 0; }
int db_next_available_id_string(char* id_string){ int i; char value[20]; int result; char key[20]; char output[80]; for(i=1; i<1000; i++){ // look for id snprintf(key, sizeof(key), "#%d > class", i); // ex: "#23 > class" if(db_get_value(key,value) != FOUND){ sprintf(id_string, "#%d", i); // convert id# to db string return 1; } } sprintf(output, "error in function DNAIS"); stioc(output); return 0; }
//----------------------------------------------------------------------- // // ex: is cat a creature? // db_root_check("cat", "creature"); // int db_root_check(char* startingwith, char* lookingfor){ // animal creature int result; int n; char subject[60]; char key[60]; char value[20]; strcpy(subject, startingwith); for(n=0; n<5; n++){ sprintf(key, "%s > class", subject); result = db_get_value(key, value); // lookup if(result == NOT_FOUND) return NOT_FOUND; // if not in database at all, exit if(strcmp(value,lookingfor)==0)return FOUND; // is it what we're looking for? if(strcmp(value,"root")==0)return NOT_FOUND; // has it reached to root? strcpy(subject,value); // if no luck so far, the value becomes the subject } return NOT_FOUND; // not found }
static xml_node_t *attach_group(xml_node_t *groups, db_res_t *res, int id) { xml_node_t *group = xml_new_child(groups, "group", XML_NODE_ANONYMOUS_JSON); xml_node_t *boards = xml_new_child(group, "boards", XML_NODE_CHILD_ARRAY); for (int i = db_res_rows(res) - 1; i >= 0; --i) { int folder = db_get_integer(res, i, 2); if (folder == id) { xml_node_t *board = xml_new_child(boards, "board", XML_NODE_ANONYMOUS_JSON); int bid = db_get_integer(res, i, 0); xml_attr_integer(board, "id", bid); const char *name = db_get_value(res, i, 1); xml_attr_string(board, "name", name, false); xml_attr_boolean(board, "unread", brc_board_unread(currentuser.userid, name, bid)); } } return group; }