#include "tbl_qcmd.h" tble_exec *tbl_exec_c() { MVAR_ALLOC_STRC(ret,tble_exec,{ return NULL;}); return ret; } tbl_exec *tbl_exec_list_c(int size) { MVAR_ALLOC_STRC(ret,tbl_exec,{ return NULL;}); ret->id = uniq_id(); ret->size = 0; ret->max_size = size; MVAR_ALLOC_ARR(cmd,tble_exec*,size,{ free(ret); return NULL; }) ret->cmd = cmd; return ret; } //TODO check if command allready excists int tbl_exec_add(tbl_exec *tbl, tble_exec *cmd) { if (tbl == NULL || cmd == NULL) { return -1; } tbl->cmd[tbl->size] = cmd; if (tbl->size+1max_size) { tbl->size += 1; } else { return -1; } return 0; } int tbl_exec_in_s(tbl_exec *tbl, char *cmd) { int i; tble_exec *el=NULL; if ((tbl == NULL) || (cmd == NULL)) { PERM(); return -1; } for (i=0; isize; i++) { el = tbl->cmd[i]; //check first part of the string, and then check that after command there is whitespace if (strncmp(el->cmd, cmd, strlen(el->cmd))==0) { if (strlen(cmd)>strlen(el->cmd)) { if (cmd[strlen(el->cmd)]==' ') { return i; } } if (strlen(cmd)==strlen(el->cmd)) { return i; } } } return -1; } int tbl_exec_run(tbl_exec *tbl, char *cmd, char *user, char *mask, char *server, void **resp) { int ret = -1; void *clbk_data = NULL; char *char_iter = NULL; int i; tble_exec *el=NULL; //user,mask,server could be NULL if ((tbl == NULL) || (cmd == NULL) || (resp==NULL) || (*resp != NULL)) { PERM(); return -1; } for (i=0;isize;i++) { el = tbl->cmd[i]; //PRINT("CALLBACK CMD %s\n",cmd); if (strncmp(el->cmd, cmd, strlen(el->cmd))==0) { void *ret_resp=NULL; //execute callback //PRINT("EXEC CLB ID %d\n",i); //little hack need proper messaging system //for now pass pointer with data if (strlen(cmd)>strlen(el->cmd)) { if (cmd[strlen(el->cmd)]==' ') { char_iter = cmd; while ((*char_iter!=' ')&&(*char_iter!=0x00)) { char_iter++; } while ((*char_iter==' ')&&(*char_iter!=0x00)) { char_iter++; } clbk_data = char_iter; if (strlen(char_iter)==0) { clbk_data = NULL; } } } //PRINT("CALLBACK PARAMS %s\n", clbk_data); if (el->type == TBL_T_SIMPLE) { ret_resp = el->callback(clbk_data); //no params for now } else if (el->type == TBL_T_RPC) { rpc_call_request *req = NULL; rpc_call_response *resp = NULL; netbyte_store *nb_req=NULL, *nb_resp=NULL; char *buf_nb = NULL, *resp_buf=NULL; nb_resp = malloc(sizeof(netbyte_store)); nb_req = malloc(sizeof(netbyte_store)); nb_init(nb_resp); nb_init(nb_req); //create request req = rpc_call_req_new(el->name, cmd, 1); if (!req) PERM(); if (user != NULL) { PRINT("%s user\n", user); req->user = alloc_new_str(user); } if (mask != NULL) { PRINT("%s mask\n", mask); req->mask = alloc_new_str(mask); } if (server != NULL) { PRINT("%s server\n", server); req->server = alloc_new_str(server); } rpc_call_req_marsh(req, &nb_req); buf_nb = nb_create(nb_req); resp_buf = el->callback(buf_nb); if (resp_buf!=NULL) { nb_load(nb_resp, resp_buf); rpc_call_resp_unmarsh(nb_resp, &resp); ret_resp = alloc_new_str(resp->result); rpc_call_resp_free(resp); } else { ERROR("No response from RPC command\n"); } FREE(buf_nb); rpc_call_req_free(req); } else if (el->type == TBL_T_LUA) { ERROR("Not implemented\n"); rpc_call_request *req = NULL; rpc_call_response *resp = NULL; netbyte_store *nb_req=NULL, *nb_resp=NULL; char *buf_nb = NULL, *resp_buf=NULL; nb_resp = malloc(sizeof(netbyte_store)); nb_req = malloc(sizeof(netbyte_store)); nb_init(nb_resp); nb_init(nb_req); //create request req = rpc_call_req_new(el->name, cmd, 1); if (!req) PERM(); if (user != NULL) { PRINT("%s user\n", user); req->user = alloc_new_str(user); } if (mask != NULL) { PRINT("%s mask\n", mask); req->mask = alloc_new_str(mask); } if (server != NULL) { PRINT("%s server\n", server); req->server = alloc_new_str(server); } rpc_call_req_marsh(req, &nb_req); buf_nb = nb_create(nb_req); resp_buf = el->callback(buf_nb); if (resp_buf!=NULL) { nb_load(nb_resp, resp_buf); rpc_call_resp_unmarsh(nb_resp, &resp); ret_resp = alloc_new_str(resp->result); rpc_call_resp_free(resp); } else { ERROR("No response from RPC command\n"); } FREE(buf_nb); rpc_call_req_free(req); } //return if (ret_resp != NULL) { *resp = ret_resp; //return executed command id ret = i; } } } return ret; } tble_exec *tbl_exec_search_cmd(tbl_exec *tbl, tble_qcmd *cmd) { tble_exec *ret = NULL; tble_exec *cur_exec = NULL; int i; if ((tbl == NULL)||(cmd == NULL)) { PERM(); return NULL; } if (tbl->id != cmd->tid) { PERM(); return NULL; } for (i=0;imax_size;i++) { cur_exec = tbl->cmd[i]; //command match if ((strncmp(cur_exec->cmd, cmd->cmd, strlen(cmd->cmd)) == 0) && (strlen(cur_exec->cmd) == strlen(cmd->cmd))) // command id and exec id match if (cur_exec->id == cmd->tidx) { ret = cur_exec; break; } } return ret; } int tbl_exec_print(tble_exec *tble, int flags) { if (tble == NULL) { return -1; } if (flags&TBL_PF_EXEC_ID) { printf("ID:[%d] ", tble->id); } if (flags&TBL_PF_EXEC_NAME) { printf("NAME:[%s] ", tble->name); } if (flags&TBL_PF_EXEC_CMD) { printf("CMD:[%s] ", tble->cmd); } if (flags&TBL_PF_EXEC_TYPE) { printf("TYPE:[%d] ", tble->type); } printf("\n"); return 0; } int tbl_exec_tbl_free(tbl_exec *tbl) { int i; if (tbl == NULL) { return -1; } if (tbl->cmd != NULL) { for (i=0;isize;i++) { tbl_exec_tel_free(tbl->cmd[i]); } free(tbl->cmd); } free(tbl); return 0; } int tbl_exec_tel_free(tble_exec *tble) { if (tble == NULL) { return -1; } free(tble->name); tble->name = NULL; free(tble->cmd); tble->cmd = NULL; free(tble); tble = NULL; return 0; } int tbl_exec_print_tbl(tbl_exec *tbl, int flags) { int i; tble_exec *el=NULL; if (tbl == NULL) { return -1; } for (i=0; isize; i++) { el = tbl->cmd[i]; if (el != NULL) { printf(">%02d< ",i); tbl_exec_print(el, flags); } } return 0; } tble_qcmd *tbl_qcmd_cmd_c() { MVAR_ALLOC_STRC(ret,tble_qcmd,{ return NULL;}); return ret; } tbl_qcmd* tbl_qcmd_c(int size) { MVAR_ALLOC_STRC(ret,tbl_qcmd,{ return NULL;}); ret->id = uniq_id(); ret->size = 0; ret->max_size = size; //alloc array of (tble_qcmd*) pointers MVAR_ALLOC_ARR(cmd,tble_qcmd*,size,{ free(ret); return NULL; }) ret->cmd = cmd; return ret; } int tbl_qcmd_exec(tbl_qcmd *tcmd, tbl_exec *texec) { int i,j; if (tcmd == NULL) { PERM(); return -1; } if (texec == NULL) { PERM(); return -1; } //EFFICIENT CODE MATE //search for commands that are in NONE state for (i=0; isize; i++) { tble_qcmd *tc = tcmd->cmd[i]; if (tc->state == QCMD_INIT) for (j=0;jsize;j++) { tble_exec *e = texec->cmd[j]; if (strncmp(e->cmd, tc->cmd, strlen(e->cmd)) == 0) { tc->tid = texec->id; //save table id tc->tidx = e->id; //set executor id tc->state = QCMD_READY; //change state, that we ready to be executed } } } return 0; } int tbl_qcmd_add(tbl_qcmd *tbl, tble_qcmd *cmd) { if (tbl == NULL || cmd == NULL) return -1; cmd->id = uniq_id(); //all command that are just added will be in zero state //should match to some executot then can change state cmd->state = QCMD_INIT; tbl->cmd[tbl->size] = cmd; if (tbl->size+1max_size) { tbl->size += 1; } else { return -1; } return 0; } int tbl_qcmd_chk(tbl_qcmd *tbl) { int ret=-1; int i; if (tbl == NULL) { return -1; } for (i=0;imax_size;i++) { //if command in some state like segfaulted or // finished running then lets check if ((tbl->cmd[i]->state == QCMD_TIMEOUT)|| (tbl->cmd[i]->state == QCMD_DONE)) { return i; } } return ret; } //delete but dont free from list? well lets free int tbl_qcmd_del_by_idx(tbl_qcmd *tbl, int idx) { int ret = -1; tble_qcmd *replace_cmd = NULL; tble_qcmd *remove_cmd = NULL; if (tbl == NULL || idx < 0) { return -1; } if (idx >= tbl->size) { return -1; } if (tbl->size == 1) { tbl->size = 0; return 0; } //if last idx = size then will overwrite itself and decrease command counter replace_cmd = tbl->cmd[tbl->size]; //if tbl->size changed you get into troubles pal tbl->size -= 1; //free before replace remove_cmd = tbl->cmd[idx]; tbl_qcmd_destroy_cmd(remove_cmd); tbl->cmd[idx] = replace_cmd; //looks like no errors ret = 0; return ret; } /* 1 - command found and have been deleted 0 - nothing have been deleted -1 - someking of error happened */ int tbl_qcmd_del_by_id(tbl_qcmd *tbl, int id) { int i; tble_qcmd *replace_cmd = NULL; tble_qcmd *remove_cmd = NULL; if (tbl == NULL) { PERM(); return -1; } if (id < 0) { PERM(); return -1; } for (i=0;isize;i++) { tble_qcmd *iter = tbl->cmd[i]; if (iter->id == id) { //PRINT("Found id\n"); // if its just last element reduce size and no other logic if (i == tbl->size-1) { //PRINT("Remove last element\n"); tbl_qcmd_destroy_cmd(tbl->cmd[i]); tbl->cmd[i] = NULL; tbl->size -= 1; return 1; } else //if element not last one { replace_cmd = tbl->cmd[tbl->size-1]; tbl->cmd[tbl->size-1] = NULL; tbl->size -= 1; //free before replace remove_cmd = iter; tbl_qcmd_destroy_cmd(remove_cmd); tbl->cmd[i] = replace_cmd; return 1; //yea yea i know } } } return 0; } int tbl_qcmd_add_tok(tble_qcmd *tbl, irc_token *tk) { if (tbl == NULL) { PERM(); return -1; } if (tk == NULL) { PERM(); return -1; } //just copy inside new token tbl->tok = token_cpy_new(tk); return 0; } tble_qcmd* tbl_qcmd_match_id(tbl_qcmd *tbl, int idx) { int i; if (tbl == NULL) { PERM(); return NULL; } if (idx < 0) { PERM(); return NULL; } for (i=0;isize;i++) { tble_qcmd *iter = tbl->cmd[i]; if (iter->id == idx) { return iter; } } return NULL; } int tbl_qcmd_resp(tbl_qcmd *tbl, tble_cmd_resp *resp) { int ret = -1; tble_qcmd *single_cmd=NULL; int i; if ((tbl == NULL) || (resp == NULL)) { return -1; } for (i=0;isize;i++) { single_cmd = tbl->cmd[i]; //check this for particular checks if (single_cmd->cid == resp->qid) { return single_cmd->id; } } return ret; } tble_cmd_param* tbl_cmd_param(tble_qcmd *cmd) { if (cmd == NULL) { return NULL; } if (cmd->state != QCMD_READY) { PERM(); return NULL; } MVAR_ALLOC_STRC(ret,tble_cmd_param,{ PERM(); return NULL;}); ret->id = uniq_id(); ret->qid = cmd->id; ret->ircident = alloc_new_str(cmd->ircident); ret->cmd = alloc_new_str(cmd->cmd); ret->param = alloc_new_str(cmd->param); ret->out_q = cmd->out_q; return ret; } int tbl_cmd_param_free(tble_cmd_param *param) { if (param == NULL) { return -1; } PNL(); free(param->ircident); PNL(); free(param->cmd); PNL(); free(param->param); PNL(); free(param); return 0; } int tbl_cmd_param_print(tble_cmd_param *param) { if (param == NULL) return -1; printf("PARAM "); printf("ID:[%d] ", param->id); printf("QID:[%d] ", param->qid); printf("OUT_Q:[%d] ", param->out_q); printf("IRCIDENT:[%s] ", param->ircident); printf("CMD:[%s] ", param->cmd); printf("PARAM:[%s] ", param->param); printf("\n"); return 0; } tble_cmd_resp* tbl_cmd_resp_c(tble_cmd_param *param) { if (param == NULL) { PERM(); return NULL; } MVAR_ALLOC_STRC(ret, tble_cmd_resp, { PERM(); return NULL; }); ret->id = uniq_id(); ret->qid = param->qid; return ret; } int tbl_cmd_resp_free(tble_cmd_resp *resp) { if (resp == NULL) { return -1; } free(resp->resp); resp->resp = NULL; free(resp); resp = NULL; return 0; } int tbl_cmd_resp_print(tble_cmd_resp *resp) { if (resp == NULL) return -1; printf("RESP "); printf("ID:[%d] ", resp->id); printf("QID:[%d] ", resp->qid); printf("TYPE:[%d] ", resp->type); printf("RET_CODE:[%d] ", resp->ret_code); printf("RESP:[%s] ", resp->resp); printf("\n"); return 0; } //add to print token if its there int tbl_qcmd_print_cmd(tble_qcmd *tbl, int flags) { if (tbl == NULL) { return -1; } if (flags&TBL_PF_QCMD_ID) { printf("ID:[%d] ",tbl->id); } if (flags&TBL_PF_QCMD_CID) { printf("CID:[%d] ",tbl->cid); } if (flags&TBL_PF_QCMD_TIMESTAMP) { printf("TIMESTAMP:[%d] ", tbl->timestamp); } if (flags&TBL_PF_QCMD_STATE) { printf("STATE:[%d] ", tbl->state); } if (flags&TBL_PF_QCMD_TIMEOUT) { printf("TIMEOUT:[%d] ", tbl->timeout); } if (flags&TBL_PF_QCMD_IRCIDENT) { printf("IRCIDENT:[%s] ", tbl->ircident); } if (flags&TBL_PF_QCMD_CMD) { printf("CMD:[%s] ", tbl->cmd); } if (flags&TBL_PF_QCMD_PARAM) { printf("PARAM:[%s] ", tbl->param); } if (flags&TBL_PF_QCMD_OUT_Q) { printf("OUT_Q:[%d] ", tbl->out_q); } if (flags&TBL_PF_QCMD_IN_Q) { printf("IN_Q:[%d] ", tbl->in_q); } if (flags&TBL_PF_QCMD_TID) { printf("TID:[%d] ", tbl->tid); } if (flags&TBL_PF_QCMD_TIDX) { printf("TIDX:[%d] ", tbl->tidx); } printf("\n"); return 0; } int tbl_qcmd_print_tbl(tbl_qcmd *tbl, int flags) { int i = -1; tble_qcmd *el = NULL; if (tbl == NULL) { PERM(); return -1; } if (tbl->cmd == NULL) { PERM(); return -1; } for (i=0; isize; i++) { el = tbl->cmd[i]; printf(">%02d< ", i); tbl_qcmd_print_cmd(el, flags); } return 0; } int tbl_qcmd_destroy_cmd(tble_qcmd *tble) { if (tble == NULL ) { PERM(); return -1; } //? //Free token list TODO free(tble->ircident); tble->ircident = NULL; free(tble->cmd); tble->cmd = NULL; free(tble->param); tble->param = NULL; free(tble); tble=NULL; return 0; } int tbl_qcmd_destroy_table(tbl_qcmd *tbl) { int i; if (tbl == NULL) { PERM(); return -1; } for (i=0; isize;i++) { if (tbl->cmd[i] != NULL) tbl_qcmd_destroy_cmd(tbl->cmd[i]); } free(tbl->cmd); tbl->cmd = NULL; free(tbl); tbl = NULL; return 0; } //redo adding and deleteing logic, there is a bug int tbl_qcmd_mng_states(tbl_qcmd *tbl) { int i; if (tbl == NULL) { PERM(); return -1; } for (i=0;isize;i++) { tble_qcmd *iter = tbl->cmd[i]; //now there is no states used, so just ignore state if ((time(NULL) - iter->timestamp)>QCMD_DEFAULT_TIMEOUT) { iter->state = QCMD_TIMEOUT; } } //remove all timed out commands for (i=tbl->size-1; i>=0;i--) { tble_qcmd *iter = tbl->cmd[i]; if (iter->state == QCMD_TIMEOUT) { //can blow your balls tbl_qcmd_del_by_id(tbl, iter->id); //now iter becomes invalid iter = NULL; } } //add more complicated state machine execution //add more logging and more cases to log return 0; }