📄 ct.c
字号:
/* * =========================================================================== * PRODUCTION $Log: ct.c,v $ * PRODUCTION Revision 1000.0 2003/10/29 20:33:11 gouriano * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.1 * PRODUCTION * =========================================================================== *//* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998-1999 Brian Bruns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <tds_config.h>#include <stdlib.h>#include <unistd.h>#include <ctpublic.h>#include <ctlib.h>#include "tdsutil.h"static char software_version[] = "$Id: ct.c,v 1000.0 2003/10/29 20:33:11 gouriano Exp $";static void *no_unused_var_warn[] = {software_version, no_unused_var_warn};/** * Read a row of data * @return 0 on success */static int _ct_bind_data(CS_COMMAND *cmd);static int _ct_get_client_type(int datatype, int size);CS_RETCODE ct_exit(CS_CONTEXT *ctx, CS_INT unused){ tdsdump_log(TDS_DBG_FUNC, "%L inside ct_exit()\n"); return CS_SUCCEED;}CS_RETCODE ct_init(CS_CONTEXT *ctx, CS_INT version){ /* uncomment the next line to get pre-login trace */ /* tdsdump_open("/tmp/tds2.log"); */ tdsdump_log(TDS_DBG_FUNC, "%L inside ct_init()\n"); ctx->tds_ctx->msg_handler = ctlib_handle_info_message; ctx->tds_ctx->err_handler = ctlib_handle_err_message; return CS_SUCCEED;}CS_RETCODE ct_con_alloc(CS_CONTEXT *ctx, CS_CONNECTION **con){ tdsdump_log(TDS_DBG_FUNC, "%L inside ct_con_alloc()\n"); *con = (CS_CONNECTION *) malloc(sizeof(CS_CONNECTION)); memset(*con,'\0',sizeof(CS_CONNECTION)); (*con)->tds_login = (void *) tds_alloc_login(); /* so we know who we belong to */ (*con)->ctx = ctx; /* set default values */ tds_set_library((*con)->tds_login, "CT-Library"); /* tds_set_charset((*con)->tds_login, "iso_1"); */ /* tds_set_packet((*con)->tds_login, TDS_DEF_BLKSZ); */ return CS_SUCCEED;}CS_RETCODE ct_callback(CS_CONTEXT *ctx, CS_CONNECTION *con, CS_INT action, CS_INT type, CS_VOID *func){ int (*funcptr)(void*,void*,void*)=(int (*)(void*,void*,void*))func; tdsdump_log(TDS_DBG_FUNC, "%L inside ct_callback() action = %s\n", CS_GET ? "CS_GET" : "CS_SET"); /* one of these has to be defined */ if (!ctx && !con) return CS_FAIL; if (action==CS_GET) { switch(type) { case CS_CLIENTMSG_CB: *(void **)func = (CS_VOID *) (con ? con->_clientmsg_cb : ctx->_clientmsg_cb); return CS_SUCCEED; case CS_SERVERMSG_CB: *(void **)func = (CS_VOID *) (con ? con->_servermsg_cb : ctx->_servermsg_cb); return CS_SUCCEED; default: fprintf(stderr,"Unknown callback %d\n",type); *(void **)func = (CS_VOID *) NULL; return CS_SUCCEED; } } /* CS_SET */ switch(type) { case CS_CLIENTMSG_CB: if (con) con->_clientmsg_cb = funcptr; else ctx->_clientmsg_cb = funcptr; break; case CS_SERVERMSG_CB: if (con) con->_servermsg_cb = funcptr; else ctx->_servermsg_cb = funcptr; break; } return CS_SUCCEED;}CS_RETCODE ct_con_props(CS_CONNECTION *con, CS_INT action, CS_INT property,CS_VOID *buffer, CS_INT buflen, CS_INT *out_len){CS_INT intval = 0, maxcp;TDSSOCKET *tds;TDSLOGIN *tds_login;char *set_buffer = NULL; tdsdump_log(TDS_DBG_FUNC, "%L inside ct_con_props() action = %s property = %d\n", CS_GET ? "CS_GET" : "CS_SET", property); tds = con->tds_socket; tds_login = con->tds_login; if (action==CS_SET) { if (property == CS_USERNAME || property == CS_PASSWORD || property == CS_APPNAME || property == CS_HOSTNAME) { if (buflen == CS_NULLTERM) { maxcp = strlen(buffer); set_buffer = (char *)malloc(maxcp + 1); strcpy(set_buffer, buffer); } else if (buflen == CS_UNUSED) { return CS_SUCCEED; } else { set_buffer = (char *)malloc(buflen + 1); strncpy(set_buffer, buffer, buflen); set_buffer[buflen] = '\0'; } } /* XXX "login" properties shouldn't be set after * login. I don't know if it should fail silently * or return an error. */ switch (property) { case CS_USERNAME: tds_set_user(tds_login, set_buffer); break; case CS_PASSWORD: tds_set_passwd(tds_login, set_buffer); break; case CS_APPNAME: tds_set_app(tds_login, set_buffer); break; case CS_HOSTNAME: tds_set_host(tds_login, set_buffer); break; case CS_LOC_PROP: con->locale = (CS_LOCALE *)buffer; break; case CS_USERDATA: if (con->userdata) { free(con->userdata); } con->userdata = (void *)malloc(buflen+1); tdsdump_log(TDS_DBG_INFO2, "%L setting userdata orig %d new %d\n",buffer,con->userdata); con->userdata_len = buflen; memcpy(con->userdata, buffer, buflen); break; case CS_BULK_LOGIN: memcpy(&intval, buffer, sizeof(intval)); if (intval) tds_set_bulk(tds_login,1); else tds_set_bulk(tds_login,0); break; case CS_PACKETSIZE: memcpy(&intval, buffer, sizeof(intval)); tds_set_packet(tds_login, (short)intval); break; case CS_TDS_VERSION: /* FIX ME * (a) We don't support all versions in tds/login.c - * I tried to pick reasonable versions. * (b) Might need support outside of tds/login.c * (c) It's a "negotiated" property so probably * needs tds_process_env_chg() support * (d) Minor - we don't check against context * which should limit the acceptable values */ if (*(int *)buffer == CS_TDS_40) { tds_set_version(tds_login, 4, 2); } else if (*(int *)buffer == CS_TDS_42) { tds_set_version(tds_login, 4, 2); } else if (*(int *)buffer == CS_TDS_46) { tds_set_version(tds_login, 4, 6); } else if (*(int *)buffer == CS_TDS_495) { tds_set_version(tds_login, 4, 6); } else if (*(int *)buffer == CS_TDS_50) { tds_set_version(tds_login, 5, 0); } else if (*(int *)buffer == CS_TDS_70) { tds_set_version(tds_login, 7, 0); } else { return CS_FAIL; } break; default: tdsdump_log(TDS_DBG_ERROR, "%L Unknown property %d\n",property); break; } if (set_buffer) free(set_buffer); } else if (action==CS_GET) { switch (property) { case CS_USERNAME: maxcp = strlen(tds_login->user_name); if (out_len) *out_len=maxcp; if (maxcp>=buflen) maxcp = buflen-1; strncpy(buffer,tds_login->user_name,maxcp); ((char *)buffer)[maxcp]='\0'; break; case CS_PASSWORD: maxcp = strlen(tds_login->password); if (out_len) *out_len=maxcp; if (maxcp>=buflen) maxcp = buflen-1; strncpy(buffer,tds_login->password,maxcp); ((char *)buffer)[maxcp]='\0'; break; case CS_APPNAME: maxcp = strlen(tds_login->app_name); if (out_len) *out_len=maxcp; if (maxcp>=buflen) maxcp = buflen-1; strncpy(buffer,tds_login->app_name,maxcp); ((char *)buffer)[maxcp]='\0'; break; case CS_HOSTNAME: maxcp = strlen(tds_login->host_name); if (out_len) *out_len=maxcp; if (maxcp>=buflen) maxcp = buflen-1; strncpy(buffer,tds_login->host_name,maxcp); ((char *)buffer)[maxcp]='\0'; break; case CS_LOC_PROP: buffer = (CS_VOID *)con->locale; break; case CS_USERDATA: tdsdump_log(TDS_DBG_INFO2, "%L fetching userdata %d\n",con->userdata); maxcp = con->userdata_len; if (out_len) *out_len=maxcp; if (maxcp>buflen) maxcp = buflen; memcpy(buffer, con->userdata, maxcp); break; case CS_CON_STATUS: if (tds && tds->s) intval |= CS_CONSTAT_CONNECTED; else intval &= ~CS_CONSTAT_CONNECTED; if (tds && tds->state==TDS_DEAD) intval |= CS_CONSTAT_DEAD; else intval &= ~CS_CONSTAT_DEAD; memcpy(buffer, &intval, sizeof(intval)); break; case CS_BULK_LOGIN: if (tds_login->bulk_copy) intval=CS_FALSE; else intval=CS_TRUE; memcpy(buffer, &intval, sizeof(intval)); break; case CS_PACKETSIZE: if (tds && tds->env) intval = tds->env->block_size; else intval = tds_login->block_size; memcpy(buffer, &intval, sizeof(intval)); if (out_len) *out_len=sizeof(intval); break; default: tdsdump_log(TDS_DBG_ERROR, "%L Unknown property %d\n",property); break; } } return CS_SUCCEED;}CS_RETCODE ct_connect(CS_CONNECTION *con, CS_CHAR *servername, CS_INT snamelen){char *server;int needfree=0;CS_CONTEXT *ctx; tdsdump_log(TDS_DBG_FUNC, "%L inside ct_connect() servername = %s\n", servername); if (snamelen==0 || snamelen==CS_UNUSED) { server=NULL; } else if (snamelen==CS_NULLTERM) { server=(char *)servername; } else { server = (char *) malloc(snamelen+1); needfree++; strncpy(server,servername,snamelen); server[snamelen]='\0'; } tds_set_server(con->tds_login,server); ctx = con->ctx; if (!(con->tds_socket = (void *) tds_connect(con->tds_login, ctx->tds_ctx, (void *) con))) { if (needfree) free(server); tdsdump_log(TDS_DBG_FUNC, "%L leaving ct_connect() returning %d\n", CS_FAIL); return CS_FAIL; } /* tds_set_parent( con->tds_socket, con); */ if (needfree) free(server); tdsdump_log(TDS_DBG_FUNC, "%L leaving ct_connect() returning %d\n", CS_SUCCEED); return CS_SUCCEED;}CS_RETCODE ct_cmd_alloc(CS_CONNECTION *con, CS_COMMAND **cmd){ tdsdump_log(TDS_DBG_FUNC, "%L inside ct_cmd_alloc()\n"); *cmd = (CS_COMMAND *) malloc(sizeof(CS_COMMAND)); memset(*cmd,'\0',sizeof(CS_COMMAND)); /* so we know who we belong to */ (*cmd)->con = con; return CS_SUCCEED;}CS_RETCODE ct_command(CS_COMMAND *cmd, CS_INT type, CS_VOID *buffer, CS_INT buflen, CS_INT option){int query_len; tdsdump_log(TDS_DBG_FUNC, "%L inside ct_command()\n"); /* FIX ME -- will only work for type CS_LANG_CMD */ if (buflen==CS_NULLTERM) { query_len = strlen(buffer); } else { query_len = buflen; } if (cmd->query) free(cmd->query); cmd->query = (char *) malloc(query_len + 1); strncpy(cmd->query,(char *)buffer,query_len); cmd->query[query_len]='\0'; return CS_SUCCEED;}CS_RETCODE ct_send_dyn(CS_COMMAND *cmd){ if (cmd->dynamic_cmd==CS_PREPARE) { cmd->dynamic_cmd=0; if (tds_submit_prepare(cmd->con->tds_socket, cmd->query, cmd->dyn_id)==TDS_FAIL) return CS_FAIL; else return CS_SUCCEED; } else if (cmd->dynamic_cmd==CS_EXECUTE) { cmd->dynamic_cmd=0; if (tds_submit_execute(cmd->con->tds_socket, cmd->dyn_id)==TDS_FAIL) return CS_FAIL; else return CS_SUCCEED; } return CS_FAIL;}CS_RETCODE ct_send(CS_COMMAND *cmd){ tdsdump_log(TDS_DBG_FUNC, "%L inside ct_send()\n"); if (cmd->dynamic_cmd) return ct_send_dyn(cmd); if (tds_submit_query(cmd->con->tds_socket, cmd->query)==TDS_FAIL) { tdsdump_log(TDS_DBG_WARN, "%L ct_send() failed\n"); return CS_FAIL; } else { tdsdump_log(TDS_DBG_INFO2, "%L ct_send() succeeded\n"); return CS_SUCCEED; }}CS_RETCODE ct_results_dyn(CS_COMMAND *cmd, CS_INT *result_type){TDSRESULTINFO *resinfo;TDSSOCKET *tds;TDSDYNAMIC *dyn; tds = cmd->con->tds_socket; if (cmd->dynamic_cmd==CS_DESCRIBE_INPUT) { dyn = tds->dyns[tds->cur_dyn_elem]; if (dyn->dyn_state) { dyn->dyn_state = 0; return CS_END_RESULTS; } else { dyn->dyn_state++; *result_type = CS_DESCRIBE_RESULT; return CS_SUCCEED; } } return CS_FAIL;}CS_RETCODE ct_results(CS_COMMAND *cmd, CS_INT *result_type){TDSRESULTINFO *resinfo;TDSSOCKET *tds;int ret; tdsdump_log(TDS_DBG_FUNC, "%L inside ct_results()\n"); if (cmd->dynamic_cmd) { return ct_results_dyn(cmd, result_type); } if (cmd->cmd_done) { cmd->cmd_done = 0; *result_type = CS_CMD_DONE; return CS_SUCCEED; } tds = cmd->con->tds_socket; switch (ret = tds_process_result_tokens(tds)) { case TDS_SUCCEED: resinfo = tds->res_info; if (resinfo->rows_exist) { *result_type = CS_ROW_RESULT; cmd->cmd_done = 1; } else { *result_type = CS_CMD_SUCCEED; } return CS_SUCCEED; case TDS_NO_MORE_RESULTS: if (! tds->res_info) { if (cmd->empty_res_hack) { cmd->empty_res_hack=0; *result_type = CS_CMD_DONE; return CS_END_RESULTS; } else { cmd->empty_res_hack=1; *result_type = CS_CMD_SUCCEED; return CS_SUCCEED; } } if (tds->res_info && !tds->res_info->rows_exist) { if (cmd->empty_res_hack) { cmd->empty_res_hack=0; *result_type = CS_CMD_DONE; return CS_END_RESULTS; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -