/* internal function to check if a table exists in the database * takes an unescaped table name and returns an escaped one or null */ int db_unsafe_check_table(PGconn *pgsql, const char *table) { int status; char *query; char *db; PGresult *result; db = PQdb(pgsql); asprintf(&query, "SELECT \"table_name\" FROM information_schema.tables WHERE table_catalog = '%s' AND table_schema = current_schema() AND table_name = '%s'", db, table); db_debug(HIGH, "Query = %s\n", query); result = PQexec(pgsql, query); free(query); if (PQresultStatus(result) == PGRES_TUPLES_OK) { if (PQntuples(result) == 1) { debug(DEBUG, "%s found!\n", table); status = TRUE; } else { debug(DEBUG, "%s missing!\n", table); status = FALSE; } } else { db_debug(LOW, "%s", PQerrorMessage(pgsql)); status = FALSE; } (void)PQclear(result); return status; }
/* the oids table name is a compiled constant so we assume it's safe */ int __db_check_and_create_oids_table(const char *table) { PGconn *pgsql = getpgsql(); int status; char *query; const char *create = "CREATE TABLE \"%s\" (" "iid SERIAL PRIMARY KEY," "oid TEXT NOT NULL UNIQUE" ")"; if (db_unsafe_check_table(pgsql, table)) { status = TRUE; } else { asprintf(&query, create, table); db_debug(LOW, "oids table not found, creating\n"); db_debug(HIGH, "Query = %s\n", query); if (db_exec_command(pgsql, query)) { status = TRUE; } else { status = FALSE; } free(query); } return status; }
/* * insert a row into the db * this expects an escaped table name */ enum DB_RESULT __db_insert(const char *table_esc, unsigned long iid, struct timeval current_time, unsigned long long insert_val, double insert_rate) { PGconn *pgsql = getpgsql(); char *query; char *diag; char now[20]; enum DB_RESULT status; PGresult *result; if (pgsql == NULL) { debug(LOW, "No Postgres connection in db_insert\n"); return FALSE; } tv2iso8601(now, current_time); /* INSERT INTO %s (iid,dtime,counter,rate) VALUES (%d, NOW(), %llu, %.6f) */ /* don't include the rate column if it's not needed */ if (insert_rate > 0) { /* double columns have precision of at least 15 digits */ asprintf(&query, "INSERT INTO \"%s\" (iid,dtime,counter,rate) VALUES (%lu,\'%s\',%llu,%.15f)", table_esc, iid, now, insert_val, insert_rate); } else { asprintf(&query, "INSERT INTO \"%s\" (iid,dtime,counter) VALUES (%lu,\'%s\',%llu)", table_esc, iid, now, insert_val); } db_debug(HIGH, "Query = %s\n", query); result = PQexec(pgsql, query); if (PQresultStatus(result) == PGRES_COMMAND_OK) { status = DB_OK; } else { /* Note that by libpq convention, a non-empty PQerrorMessage will include a trailing newline. */ /* also errors start with 'ERROR:' so we don't need to */ db_debug(LOW, "(error code %s) %s", PQresultErrorField(result, PG_DIAG_SQLSTATE), PQerrorMessage(pgsql)); db_debug(LOW, "%s\n", query); diag = PQresultErrorField(result, PG_DIAG_SQLSTATE); if (diag && strncmp(diag, "22003", 5) == 0) { /* NUMERIC VALUE OUT OF RANGE */ /* this can happen because postgres doesn't have unsigned integers */ status = DB_OOR; } else { status = DB_RETRY; } } /* free the result */ (void)PQclear(result); free(query); return(status); }
/* * insert an (escaped) snmp oid into the database and update the iid */ int db_insert_oid(PGconn *pgsql, const char *oid_esc, unsigned long *iid) { int status = FALSE; char *query; PGresult *result; asprintf(&query, "INSERT INTO \"oids\" (oid) (SELECT \'%s\' AS oid WHERE NOT EXISTS (SELECT 1 FROM \"oids\" WHERE oid=\'%s\')) RETURNING iid", oid_esc, oid_esc); db_debug(HIGH, "Query = %s\n", query); result = PQexec(pgsql, "BEGIN"); (void)PQclear(result); result = PQexec(pgsql, query); if (PQresultStatus(result) == PGRES_TUPLES_OK) { if (PQntuples(result)) { *iid = strtoul(PQgetvalue(result, 0, 0), NULL, 0); status = TRUE; } else { /* no result so may have been a concurrent insert, do a select instead */ /* don't call db_lookup_oid because that calls back here */ free(query); asprintf(&query, "SELECT \"iid\" from \"oids\" WHERE \"oid\" = \'%s\'", oid_esc); db_debug(HIGH, "Query = %s\n", query); (void)PQclear(result); result = PQexec(pgsql, query); if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result)) { *iid = strtoul(PQgetvalue(result, 0, 0), NULL, 0); status = TRUE; } } } if (status == FALSE) { db_debug(LOW, "%s%s\n", PQerrorMessage(pgsql), query); status = FALSE; } (void)PQclear(result); result = PQexec(pgsql, "END"); (void)PQclear(result); free(query); return status; }
int __db_status() { PGconn *pgsql = getpgsql(); if (PQstatus(pgsql) == CONNECTION_OK) { return TRUE; } else { db_debug(LOW, "error: %s\n", PQerrorMessage(pgsql)); return FALSE; } }
/* lookup the iid of an snmp oid in the database */ int __db_lookup_oid(const char *oid, unsigned long *iid) { PGconn *pgsql = getpgsql(); int status; char *query; char *oid_esc; PGresult *result; oid_esc = escape_string(pgsql, oid); db_debug(DEBUG, "oid_esc = %s\n", oid_esc); asprintf(&query, "SELECT \"iid\" from \"oids\" WHERE \"oid\" = \'%s\'", oid_esc); db_debug(HIGH, "Query = %s\n", query); result = PQexec(pgsql, query); free(query); if (PQresultStatus(result) == PGRES_TUPLES_OK) { switch (PQntuples(result)) { case 1: *iid = strtoul(PQgetvalue(result, 0, 0), NULL, 0); db_debug(DEBUG, "iid = %lu\n", *iid); status = TRUE; break; case 0: status = db_insert_oid(pgsql, oid_esc, iid); break; default: /* this shouldn't happen */ db_debug(DEBUG, "oid '%s' ntuples = %i\n", oid_esc, PQntuples(result)); status = FALSE; } } else { db_debug(LOW, "%s", PQerrorMessage(pgsql)); status = FALSE; } (void)PQclear(result); free(oid_esc); return status; }
/* TODO check the table name length against NAMEDATALEN -1 (ie 63) */ char *__db_check_and_create_data_table(const char *table) { PGconn *pgsql = getpgsql(); char *query; char *table_esc; const char *create = "CREATE TABLE \"%s\" (" "iid int NOT NULL default '0'," "dtime timestamp NOT NULL," "counter bigint NOT NULL default '0'," "rate real NOT NULL default '0.0'" ")"; const char *index = "CREATE INDEX \"%s_idx\" ON \"%s\" (iid,dtime)"; table_esc = escape_string(pgsql, table); /* first check if it already exists */ if (!db_unsafe_check_table(pgsql, table_esc)) { asprintf(&query, create, table_esc); db_debug(LOW, "\'%s\' table not found, creating\n", table_esc); db_debug(HIGH, "Query = %s\n", query); if (db_exec_command(pgsql, query)) { free(query); asprintf(&query, index, table_esc, table_esc); db_debug(HIGH, "Query = %s\n", query); if (!db_exec_command(pgsql, query)) { free(table_esc); table_esc = NULL; } } else { free(table_esc); table_esc = NULL; } /* this will either be the create table query if that failed, or the index query if the create succeeded */ free(query); } return table_esc; }
/* execute a sql command (query) that doesn't return any rows */ int db_exec_command(PGconn *pgsql, const char *query) { PGresult *result; int status; result = PQexec(pgsql, query); if (PQresultStatus(result) == PGRES_COMMAND_OK) { status = TRUE; } else { db_debug(LOW, "%s", PQerrorMessage(pgsql)); status = FALSE; } (void)PQclear(result); return status; }
static int draw_testcases(void) { int i; struct item_data it_data; for (i = 0; i < total_testcases; i++) { memset(&it_data, 0, sizeof(struct item_data)); strcpy(it_data.name, base_info[i].name); strcpy(it_data.display_name, base_info[i].display_name); it_data.category = base_info[i].category; it_data.status = -1; db_debug("core: draw test case: %s, display name: %s, category: %s\n", it_data.name, it_data.display_name, it_data.category ? "manual" : "auto"); view_insert_item(base_info[i].id, &it_data); } return 0; }
/* utility function to safely escape table names */ char *escape_string(PGconn *pgsql, const char *input) { /* length of string */ size_t input_len = strlen(input); char *scratch; size_t scratch_len; char *output; /* worst case is every char escaped plus terminating NUL */ scratch = malloc(input_len*2+1); /* escape the string */ scratch_len = PQescapeStringConn(pgsql, scratch, input, input_len, NULL); if (scratch_len) { output = strndup(scratch, scratch_len); free(scratch); } else { output = NULL; } db_debug(DEBUG, "escape_string input = '%s' output = '%s'\n", input, output); return output; }
int main(int argc, char *argv[]) { char dev_path[64]; FILE *fp; char evt_path[32]; int fd; int version; unsigned short id[4]; char name[32]; unsigned long bit[EV_MAX][NBITS(KEY_MAX)]; int i, j, k; int abs[5]; struct input_event evt[64]; int rd; char buf[64]; char pre_key[64]; INIT_CMD_PIPE(); strncpy(dev_path, "/sys/class/input/event0/device/name", 64); for (i = 0; i < 5; i++) { dev_path[22] = '0' + i; if (access(dev_path, F_OK)) { db_error("can't access %s(%s)\n", dev_path, strerror(errno)); goto err; } fp = fopen(dev_path, "r"); if (fp == NULL) { db_error("can't open %s(%s)\n", dev_path, strerror(errno)); goto err; } if (fgets(evt_path, 32, fp) == NULL) { db_error("can't read %s(%s)\n", dev_path, strerror(errno)); goto err; } if (match_ir(evt_path) == 0) { fclose(fp); break; } fclose(fp); } if (i == 5) { db_error("NO!!! ir input found\n"); goto err; } strncpy(evt_path, "/dev/input/event0", 32); evt_path[16] = '0' + i; if ((fd = open(evt_path, O_RDONLY)) < 0) { db_error("can't open %s(%s)\n", evt_path, strerror(errno)); goto err; } if (ioctl(fd, EVIOCGVERSION, &version)) { db_error("can't get version\n"); goto err; } db_debug("Input driver version is %d.%d.%d\n", version >> 16, (version >> 8) & 0xff, version & 0xff); ioctl(fd, EVIOCGID, id); db_debug("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n", id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]); ioctl(fd, EVIOCGNAME(sizeof(name)), name); db_debug("Input device name: \"%s\"\n", name); memset(bit, 0, sizeof(bit)); ioctl(fd, EVIOCGBIT(0, sizeof(bit[0])), bit[0]); db_dump("Supported events:\n"); for (i = 0; i < EV_MAX; i++) { if (test_bit(i, bit[0])) { db_dump(" Event type %d (%s)\n", i, events[i] ? events[i] : "?"); if (!i) continue; ioctl(fd, EVIOCGBIT(i, sizeof(bit[0])), bit[i]); for (j = 0; j < KEY_MAX; j++) { if (test_bit(j, bit[i])) { db_dump(" Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?"); if (i == EV_ABS) { ioctl(fd, EVIOCGABS(j), abs); for (k = 0; k < 5; k++) { if ((k < 3) || abs[k]) printf("%s %6d\n", absval[k], abs[k]); } } } } } } memset(pre_key, 0, sizeof(pre_key)); while (1) { rd = read(fd, evt, sizeof(struct input_event) * 64); if (rd < (int)sizeof(struct input_event)) { db_error("error in reading\n"); goto err; } for (i = 0; i < rd / sizeof(struct input_event); i++) { if (evt[i].type == EV_SYN) { ; } else if (evt[i].type == EV_MSC && (evt[i].code == MSC_RAW || evt[i].code == MSC_SCAN)) { db_debug("%s, %s(%d, %02x)\n", events[evt[i].type] ? events[evt[i].type] : "?", names[evt[i].type] ? (names[evt[i].type][evt[i].code] ? names[evt[i].type][evt[i].code] : "?") : "?", evt[i].code, evt[i].value); if (evt[i].value) continue; if (pre_key[0]) { snprintf(buf, sizeof(buf), "%s, %s", names[evt[i].type] ? (names[evt[i].type][evt[i].code] ? names[evt[i].type][evt[i].code] : "?") : "?", pre_key); } else { snprintf(buf, sizeof(buf), "%s", names[evt[i].type] ? (names[evt[i].type][evt[i].code] ? names[evt[i].type][evt[i].code] : "?") : "?"); } snprintf(pre_key, sizeof(pre_key), "%s", buf); SEND_CMD_PIPE_OK_EX(buf); } else { db_debug("%s, %s(%d, %02x)\n", events[evt[i].type] ? events[evt[i].type] : "?", names[evt[i].type] ? (names[evt[i].type][evt[i].code] ? names[evt[i].type][evt[i].code] : "?") : "?", evt[i].code, evt[i].value); if (evt[i].value) continue; if (pre_key[0]) { snprintf(buf, sizeof(buf), "%s, %s", names[evt[i].type] ? (names[evt[i].type][evt[i].code] ? names[evt[i].type][evt[i].code] : "?") : "?", pre_key); } else { snprintf(buf, sizeof(buf), "%s", names[evt[i].type] ? (names[evt[i].type][evt[i].code] ? names[evt[i].type][evt[i].code] : "?") : "?"); } snprintf(pre_key, sizeof(pre_key), "%s", buf); SEND_CMD_PIPE_OK_EX(buf); } } } err: SEND_CMD_PIPE_FAIL(); EXIT_CMD_PIPE(); return 0; }