/** * Open and read the file 'file' searching for a logical server * by the name of 'host'. If one is found then lookup * the IP address and port number and store them in 'login' * * \param dir name of base directory for interface file * \param file name of the interface file * \param host logical host to search for * \return 0 if not fount 1 if found */ static int search_interface_file(TDSLOGIN * login, const char *dir, const char *file, const char *host) { char *pathname; char line[255]; char tmp_ip[sizeof(line)]; char tmp_port[sizeof(line)]; char tmp_ver[sizeof(line)]; FILE *in; char *field; int found = 0; int server_found = 0; char *lasts; line[0] = '\0'; tmp_ip[0] = '\0'; tmp_port[0] = '\0'; tmp_ver[0] = '\0'; tdsdump_log(TDS_DBG_INFO1, "Searching interfaces file %s/%s.\n", dir, file); pathname = (char *) malloc(strlen(dir) + strlen(file) + 10); if (!pathname) return 0; /* * create the full pathname to the interface file */ if (file[0] == '\0') { pathname[0] = '\0'; } else { if (dir[0] == '\0') { pathname[0] = '\0'; } else { strcpy(pathname, dir); strcat(pathname, TDS_SDIR_SEPARATOR); } strcat(pathname, file); } /* * parse the interfaces file and find the server and port */ if ((in = fopen(pathname, "r")) == NULL) { tdsdump_log(TDS_DBG_INFO1, "Couldn't open %s.\n", pathname); free(pathname); return 0; } tdsdump_log(TDS_DBG_INFO1, "Interfaces file %s opened.\n", pathname); while (fgets(line, sizeof(line) - 1, in)) { if (line[0] == '#') continue; /* comment */ if (!TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (!strcmp(field, host)) { found = 1; tdsdump_log(TDS_DBG_INFO1, "Found matching entry for host %s.\n", host); } else found = 0; } else if (found && TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (field != NULL && !strcmp(field, "query")) { field = strtok_r(NULL, "\n\t ", &lasts); /* tcp or tli */ if (!strcmp(field, "tli")) { tdsdump_log(TDS_DBG_INFO1, "TLI service.\n"); field = strtok_r(NULL, "\n\t ", &lasts); /* tcp */ field = strtok_r(NULL, "\n\t ", &lasts); /* device */ field = strtok_r(NULL, "\n\t ", &lasts); /* host/port */ if (strlen(field) >= 18) { sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8])); sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]), hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16])); tdsdump_log(TDS_DBG_INFO1, "tmp_port = %s. tmp_ip = %s.\n", tmp_port, tmp_ip); } } else { field = strtok_r(NULL, "\n\t ", &lasts); /* ether */ strcpy(tmp_ver, field); field = strtok_r(NULL, "\n\t ", &lasts); /* host */ strcpy(tmp_ip, field); tdsdump_log(TDS_DBG_INFO1, "host field %s.\n", tmp_ip); field = strtok_r(NULL, "\n\t ", &lasts); /* port */ strcpy(tmp_port, field); } /* else */ server_found = 1; } /* if */ } /* else if */ } /* while */ fclose(in); free(pathname); /* * Look up the host and service */ if (server_found) { if (TDS_SUCCEED(tds_lookup_host_set(tmp_ip, &login->ip_addrs))) { struct addrinfo *addrs; if (!tds_dstr_copy(&login->server_host_name, tmp_ip)) return 0; for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) { tdsdump_log(TDS_DBG_INFO1, "Resolved IP as '%s'.\n", tds_addrinfo2str(login->ip_addrs, line, sizeof(line))); } } else { tdsdump_log(TDS_DBG_WARN, "Name resolution failed for IP '%s'.\n", tmp_ip); } if (tmp_port[0]) login->port = tds_lookup_port(tmp_port); if (tmp_ver[0]) tds_config_verstr(tmp_ver, login); } return server_found; } /* search_interface_file() */
/** * Read a section of configuration file (INI style file) * @param in configuration file * @param section section to read * @param tds_conf_parse callback that receive every entry in section * @param param parameter to pass to callback function */ int tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *param) { char line[256], *value; #define option line char *s; char p; int i; int insection = 0; int found = 0; tdsdump_log(TDS_DBG_INFO1, "Looking for section %s.\n", section); while (fgets(line, sizeof(line), in)) { s = line; /* skip leading whitespace */ while (*s && TDS_ISSPACE(*s)) s++; /* skip it if it's a comment line */ if (*s == ';' || *s == '#') continue; /* read up to the = ignoring duplicate spaces */ p = 0; i = 0; while (*s && *s != '=') { if (!TDS_ISSPACE(*s)) { if (TDS_ISSPACE(p)) option[i++] = ' '; option[i++] = tolower((unsigned char) *s); } p = *s; s++; } /* skip if empty option */ if (!i) continue; /* skip the = */ if (*s) s++; /* terminate the option, must be done after skipping = */ option[i] = '\0'; /* skip leading whitespace */ while (*s && TDS_ISSPACE(*s)) s++; /* read up to a # ; or null ignoring duplicate spaces */ value = s; p = 0; i = 0; while (*s && *s != ';' && *s != '#') { if (!TDS_ISSPACE(*s)) { if (TDS_ISSPACE(p)) value[i++] = ' '; value[i++] = *s; } p = *s; s++; } value[i] = '\0'; if (option[0] == '[') { s = strchr(option, ']'); if (s) *s = '\0'; tdsdump_log(TDS_DBG_INFO1, "\tFound section %s.\n", &option[1]); if (!strcasecmp(section, &option[1])) { tdsdump_log(TDS_DBG_INFO1, "Got a match.\n"); insection = 1; found = 1; } else { insection = 0; } } else if (insection) { tds_conf_parse(option, value, param); } } tdsdump_log(TDS_DBG_INFO1, "\tReached EOF\n"); return found; #undef option }
static int prepared_rpc(struct _hstmt *stmt, int compute_row) { int nparam = stmt->params ? stmt->params->num_cols : 0; const char *p = stmt->prepared_pos - 1; TDSCONNECTION *conn = stmt->dbc->tds_socket->conn; for (;;) { TDSPARAMINFO *temp_params; TDSCOLUMN *curcol; TDS_SERVER_TYPE type; const char *start; while (TDS_ISSPACE(*++p)); if (!*p) return SQL_SUCCESS; /* we have certainly a parameter */ if (!(temp_params = tds_alloc_param_result(stmt->params))) { odbc_errs_add(&stmt->errs, "HY001", NULL); return SQL_ERROR; } stmt->params = temp_params; curcol = temp_params->columns[nparam]; switch (*p) { case ',': if (IS_TDS7_PLUS(conn)) { tds_set_param_type(conn, curcol, SYBVOID); curcol->column_size = curcol->column_cur_size = 0; } else { /* TODO is there a better type ? */ tds_set_param_type(conn, curcol, SYBINTN); curcol->column_size = curcol->on_server.column_size = 4; curcol->column_cur_size = -1; } if (compute_row) if (!tds_alloc_param_data(curcol)) { tds_free_param_result(temp_params); return SQL_ERROR; } --p; break; default: /* add next parameter to list */ start = p; if (!(p = parse_const_param(p, &type))) { tds_free_param_result(temp_params); return SQL_ERROR; } tds_set_param_type(conn, curcol, type); switch (type) { case SYBVARCHAR: curcol->column_size = p - start; break; case SYBVARBINARY: curcol->column_size = (p - start) / 2 -1; break; default: assert(0); case SYBINT4: case SYBFLT8: curcol->column_cur_size = curcol->column_size; break; } curcol->on_server.column_size = curcol->column_size; /* TODO support other type other than VARCHAR, do not strip escape in prepare_call */ if (compute_row) { char *dest; int len; CONV_RESULT cr; if (!tds_alloc_param_data(curcol)) { tds_free_param_result(temp_params); return SQL_ERROR; } dest = (char *) curcol->column_data; switch (type) { case SYBVARCHAR: if (*start != '\'') { memcpy(dest, start, p - start); curcol->column_cur_size = p - start; } else { ++start; for (;;) { if (*start == '\'') ++start; if (start >= p) break; *dest++ = *start++; } curcol->column_cur_size = dest - (char *) curcol->column_data; } break; case SYBVARBINARY: cr.cb.len = curcol->column_size; cr.cb.ib = dest; len = tds_convert(NULL, SYBVARCHAR, start, p - start, TDS_CONVERT_BINARY, &cr); if (len >= 0 && len <= curcol->column_size) curcol->column_cur_size = len; break; case SYBINT4: *((TDS_INT *) dest) = strtol(start, NULL, 10); break; case SYBFLT8: *((TDS_FLOAT *) dest) = strtod(start, NULL); break; default: break; } } --p; break; case '?': /* find binded parameter */ if (stmt->param_num > stmt->apd->header.sql_desc_count || stmt->param_num > stmt->ipd->header.sql_desc_count) { tds_free_param_result(temp_params); /* TODO set error */ return SQL_ERROR; } switch (odbc_sql2tds (stmt, &stmt->ipd->records[stmt->param_num - 1], &stmt->apd->records[stmt->param_num - 1], curcol, compute_row, stmt->apd, stmt->curr_param_row)) { case SQL_ERROR: return SQL_ERROR; case SQL_NEED_DATA: return SQL_NEED_DATA; } ++stmt->param_num; break; } ++nparam; while (TDS_ISSPACE(*++p)); if (!*p || *p != ',') return SQL_SUCCESS; stmt->prepared_pos = (char *) p + 1; } }
/* ========================= search_interface_file() ========================= * * Def: Open and read the file 'file' searching for a logical server * by the name of 'host'. If one is found then lookup * the IP address and port number and store them in 'ip_addr', and * 'ip_port'. * * Ret: void * * =========================================================================== */ static int search_interface_file(TDSCONNECTINFO * connect_info, const char *dir, /* (I) Name of base directory for interface file */ const char *file, /* (I) Name of the interface file */ const char *host /* (I) Logical host to search for */ ) { char *pathname; char line[255]; char tmp_ip[sizeof(line)]; char tmp_port[sizeof(line)]; char tmp_ver[sizeof(line)]; FILE *in; char *field; int found = 0; int server_found = 0; char *lasts; line[0] = '\0'; tmp_ip[0] = '\0'; tmp_port[0] = '\0'; tmp_ver[0] = '\0'; tdsdump_log(TDS_DBG_INFO1, "%L Searching interfaces file %s/%s.\n", dir, file); pathname = (char *) malloc(strlen(dir) + strlen(file) + 10); if (!pathname) return 0; /* * * create the full pathname to the interface file */ if (file[0] == '\0') { pathname[0] = '\0'; } else { if (dir[0] == '\0') { pathname[0] = '\0'; } else { strcpy(pathname, dir); strcat(pathname, "/"); } strcat(pathname, file); } /* * * parse the interfaces file and find the server and port */ if ((in = fopen(pathname, "r")) == NULL) { tdsdump_log(TDS_DBG_INFO1, "%L Couldn't open %s.\n", pathname); free(pathname); return 0; } tdsdump_log(TDS_DBG_INFO1, "%L Interfaces file %s opened.\n", pathname); while (fgets(line, sizeof(line) - 1, in)) { if (line[0] == '#') continue; /* comment */ if (!TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (!strcmp(field, host)) { found = 1; tdsdump_log(TDS_DBG_INFO1, "%L Found matching entry for host %s.\n", host); } else found = 0; } else if (found && TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (field != NULL && !strcmp(field, "query")) { field = strtok_r(NULL, "\n\t ", &lasts); /* tcp or tli */ if (!strcmp(field, "tli")) { tdsdump_log(TDS_DBG_INFO1, "%L TLI service.\n"); field = strtok_r(NULL, "\n\t ", &lasts); /* tcp */ field = strtok_r(NULL, "\n\t ", &lasts); /* device */ field = strtok_r(NULL, "\n\t ", &lasts); /* host/port */ if (strlen(field) >= 18) { sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8])); sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]), hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16])); tdsdump_log(TDS_DBG_INFO1, "%L tmp_port = %d.mtp_ip = %s.\n", tmp_port, tmp_ip); } } else { field = strtok_r(NULL, "\n\t ", &lasts); /* ether */ strcpy(tmp_ver, field); field = strtok_r(NULL, "\n\t ", &lasts); /* host */ strcpy(tmp_ip, field); tdsdump_log(TDS_DBG_INFO1, "%L host field %s.\n", tmp_ip); field = strtok_r(NULL, "\n\t ", &lasts); /* port */ strcpy(tmp_port, field); } /* else */ server_found = 1; } /* if */ } /* else if */ } /* while */ fclose(in); free(pathname); /* * Look up the host and service */ if (server_found) { tds_lookup_host(tmp_ip, line); tdsdump_log(TDS_DBG_INFO1, "%L Resolved IP as '%s'.\n", line); tds_dstr_copy(&connect_info->ip_addr, line); if (tmp_port[0]) connect_info->port = tds_lookup_port(tmp_port); if (tmp_ver[0]) tds_config_verstr(tmp_ver, connect_info); } return server_found; } /* search_interface_file() */
/** * Read a section of configuration file (INI style file) * @param in configuration file * @param section section to read * @param tds_conf_parse callback that receive every entry in section * @param param parameter to pass to callback function */ int tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *param) { char line[256], option[256], value[256]; char *s; char p; int i; int insection = 0; int found = 0; tdsdump_log(TDS_DBG_INFO1, "%L Looking for section %s.\n", section); while (fgets(line, 256, in)) { s = line; /* skip leading whitespace */ while (*s && TDS_ISSPACE(*s)) s++; /* skip it if it's a comment line */ if (*s == ';' || *s == '#') continue; /* read up to the = ignoring duplicate spaces */ p = 0; i = 0; while (*s && *s != '=') { if (!TDS_ISSPACE(*s) && TDS_ISSPACE(p)) option[i++] = ' '; if (!TDS_ISSPACE(*s)) option[i++] = tolower((unsigned char) *s); p = *s; s++; } option[i] = '\0'; /* skip the = */ if (*s) s++; /* skip leading whitespace */ while (*s && TDS_ISSPACE(*s)) s++; /* read up to a # ; or null ignoring duplicate spaces */ p = 0; i = 0; while (*s && *s != ';' && *s != '#') { if (!TDS_ISSPACE(*s) && TDS_ISSPACE(p)) value[i++] = ' '; if (!TDS_ISSPACE(*s)) value[i++] = *s; p = *s; s++; } value[i] = '\0'; if (!strlen(option)) continue; if (option[0] == '[') { s = &option[1]; while (*s) { if (*s == ']') *s = '\0'; *s = tolower((unsigned char) *s); s++; } tdsdump_log(TDS_DBG_INFO1, "%L ... Found section %s.\n", &option[1]); if (!strcasecmp(section, &option[1])) { tdsdump_log(TDS_DBG_INFO1, "%L Got a match.\n"); insection = 1; found = 1; } else { insection = 0; } } else if (insection) { tds_conf_parse(option, value, param); } } return found; }
/* * Function transformation (from ODBC to Sybase) * String functions * ASCII(string) -> ASCII(string) * BIT_LENGTH(string) -> 8*OCTET_LENGTH(string) * CHAR_LENGTH(string_exp) -> CHAR_LENGTH(string_exp) * CHARACTER_LENGTH(string_exp) -> CHAR_LENGTH(string_exp) * CONCAT(string_exp1, string_exp2) -> string_exp1 + string_exp2 * DIFFERENCE(string_exp1, string_exp2) -> DIFFERENCE(string_exp1, string_exp2) * INSERT(string_exp1, start, length, string_exp2) -> STUFF(sameparams) * LCASE(string_exp) -> LOWER(string) * LEFT(string_exp, count) -> SUBSTRING(string, 1, count) * LENGTH(string_exp) -> CHAR_LENGTH(RTRIM(string_exp)) * LOCATE(string, string [,start]) -> CHARINDEX(string, string) * (SQLGetInfo should return third parameter not possible) * LTRIM(String) -> LTRIM(String) * OCTET_LENGTH(string_exp) -> OCTET_LENGTH(string_exp) * POSITION(character_exp IN character_exp) ??? * REPEAT(string_exp, count) -> REPLICATE(same) * REPLACE(string_exp1, string_exp2, string_exp3) -> ?? * RIGHT(string_exp, count) -> RIGHT(string_exp, count) * RTRIM(string_exp) -> RTRIM(string_exp) * SOUNDEX(string_exp) -> SOUNDEX(string_exp) * SPACE(count) (ODBC 2.0) -> SPACE(count) (ODBC 2.0) * SUBSTRING(string_exp, start, length) -> SUBSTRING(string_exp, start, length) * UCASE(string_exp) -> UPPER(string) * * Numeric * Nearly all function use same parameters, except: * ATAN2 -> ATN2 * TRUNCATE -> ?? */ static SQLRETURN to_native(struct _hdbc *dbc, struct _hstmt *stmt, DSTR *str) { char *d, *s; int nest_syntax = 0; char *buf = tds_dstr_buf(str); /* list of bit, used as stack, is call ? FIXME limites size... */ unsigned long is_calls = 0; int server_scalar; assert(dbc); server_scalar = TDS_IS_MSSQL(dbc->tds_socket) && dbc->tds_socket->conn->product_version >= TDS_MS_VER(7, 0, 0); /* * we can do it because result string will be * not bigger than source string */ d = s = buf; while (*s) { if (*s == '-' || *s == '/') { size_t len_comment = tds_skip_comment(s) - s; memmove(d, s, len_comment); s += len_comment; d += len_comment; continue; } /* TODO: test syntax like "select 1 as [pi]]p)p{?=call]]]]o], 2" on mssql7+ */ if (*s == '"' || *s == '\'' || *s == '[') { size_t len_quote = tds_skip_quoted(s) - s; memmove(d, s, len_quote); s += len_quote; d += len_quote; continue; } if (*s == '{') { char *pcall; while (TDS_ISSPACE(*++s)) continue; pcall = s; /* FIXME if nest_syntax > 0 problems */ if (server_scalar && strncasecmp(pcall, "fn ", 3) == 0) { *d++ = '{'; continue; } if (*pcall == '?') { /* skip spaces after ? */ while (TDS_ISSPACE(*++pcall)) continue; if (*pcall == '=') { while (TDS_ISSPACE(*++pcall)) continue; } else { /* avoid {?call ... syntax */ pcall = s; } } if (strncasecmp(pcall, "call ", 5) != 0) pcall = NULL; if (stmt) stmt->prepared_query_is_rpc = 1; ++nest_syntax; is_calls <<= 1; if (!pcall) { /* assume syntax in the form {type ...} */ while (TDS_ISALPHA(*s)) ++s; while (TDS_ISSPACE(*s)) ++s; } else { if (*s == '?' && stmt) stmt->prepared_query_is_func = 1; memcpy(d, "exec ", 5); d += 5; s = pcall + 5; is_calls |= 1; } } else if (nest_syntax > 0) { /* do not copy close syntax */ if (*s == '}') { --nest_syntax; is_calls >>= 1; ++s; continue; /* convert parenthesis in call to spaces */ } else if ((is_calls & 1) && (*s == '(' || *s == ')')) { *d++ = ' '; s++; } else { *d++ = *s++; } } else {