1/* 2 * trace.c 3 * 4 * $Id: trace.c,v 1.21 2007/10/07 10:48:35 source Exp $ 5 * 6 * Trace functions 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com> 11 * All Rights Reserved. 12 * 13 * This software is released under the terms of either of the following 14 * licenses: 15 * 16 * - GNU Library General Public License (see LICENSE.LGPL) 17 * - The BSD License (see LICENSE.BSD). 18 * 19 * Note that the only valid version of the LGPL license as far as this 20 * project is concerned is the original GNU Library General Public License 21 * Version 2, dated June 1991. 22 * 23 * While not mandated by the BSD license, any patches you make to the 24 * iODBC source code may be contributed back into the iODBC project 25 * at your discretion. Contributions will benefit the Open Source and 26 * Data Access community as a whole. Submissions may be made at: 27 * 28 * http://www.iodbc.org 29 * 30 * 31 * GNU Library Generic Public License Version 2 32 * ============================================ 33 * This library is free software; you can redistribute it and/or 34 * modify it under the terms of the GNU Library General Public 35 * License as published by the Free Software Foundation; only 36 * Version 2 of the License dated June 1991. 37 * 38 * This library is distributed in the hope that it will be useful, 39 * but WITHOUT ANY WARRANTY; without even the implied warranty of 40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 41 * Library General Public License for more details. 42 * 43 * You should have received a copy of the GNU Library General Public 44 * License along with this library; if not, write to the Free 45 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 46 * 47 * 48 * The BSD License 49 * =============== 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in 58 * the documentation and/or other materials provided with the 59 * distribution. 60 * 3. Neither the name of OpenLink Software Inc. nor the names of its 61 * contributors may be used to endorse or promote products derived 62 * from this software without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 65 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 66 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 67 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR 68 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 69 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 70 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 71 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 72 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 73 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 74 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 */ 76 77 78#ifdef HAVE_CONFIG_H 79#include "config.h" 80#endif 81 82#include <stdlib.h> 83#include <stdio.h> 84#include <stdarg.h> 85#include <ctype.h> 86#include <pwd.h> 87#include <unistd.h> 88#include <fcntl.h> 89 90#include <time.h> 91#ifdef TIME_WITH_SYS_TIME 92#include <sys/time.h> 93#endif 94 95#include <sql.h> 96#include <sqlext.h> 97#include <sqlucode.h> 98 99#include "herr.h" 100#include "henv.h" 101#include "ithread.h" 102#include "trace.h" 103#include "unicode.h" 104 105#define NO_CARBON 1 106#if defined(macintosh) 107# include <Errors.h> 108# include <OSUtils.h> 109# include <Processes.h> 110#elif defined(__APPLE__) && !defined(NO_CARBON) 111# include <Carbon/Carbon.h> 112#endif 113 114 115/* 116 * Limit the size of the tracefile, to avoid a core dump when the 117 * the RLIMIT_FSIZE is reached. 118 */ 119#define MAX_TRACEFILE_LEN 1000000000L /* about 1GB */ 120 121 122/* 123 * Global trace flag 124 */ 125int ODBCSharedTraceFlag = SQL_OPT_TRACE_OFF; 126 127static char *trace_appname = NULL; 128static char *trace_fname = NULL; 129static FILE *trace_fp = NULL; 130static int trace_fp_close = 0; 131 132void trace_emit (char *fmt, ...); 133 134#ifdef HAVE_GETTIMEOFDAY 135static struct timeval starttime = {0}; 136#endif 137 138 139/* 140 * Internal functions 141 */ 142void 143trace_set_appname (char *appname) 144{ 145 MEM_FREE (trace_appname); 146 trace_appname = STRDUP (appname); 147} 148 149 150char * 151trace_get_filename (void) 152{ 153 return STRDUP (trace_fname); 154} 155 156 157static void 158trace_strftime_now (char *buf, size_t buflen, char *format) 159{ 160 time_t now; 161 struct tm *timeNow; 162#ifdef HAVE_LOCALTIME_R 163 struct tm keeptime; 164#endif 165 166 tzset (); 167 time (&now); 168 169#ifdef HAVE_LOCALTIME_R 170 timeNow = localtime_r (&now, &keeptime); 171#else 172 timeNow = localtime (&now); 173#endif 174 175 strftime (buf, buflen, format, timeNow); 176} 177 178 179 180 181void 182trace_set_filename (char *fname) 183{ 184 char *s, *p; 185 struct passwd *pwd; 186 char *buf; 187 size_t buf_len, buf_pos; 188 char tmp[255]; 189 190 /* Initialize */ 191 MEM_FREE (trace_fname); 192 trace_fname = NULL; 193 buf = (char *) malloc (buf_len = strlen (fname) + sizeof (tmp) + 1); 194 if (!buf) 195 return; /* No more memory */ 196 buf_pos = 0; 197 buf[0] = '\0'; 198 199 for (s = fname; *s;) 200 { 201 /* 202 * Make sure we can fit at least 1 more tmp buffer inside 203 */ 204 if (buf_len - buf_pos < sizeof (tmp)) 205 buf = realloc (buf, buf_len += sizeof (tmp) + 1); 206 if (!buf) 207 return; /* No more memory */ 208 209 if (*s != '$') 210 { 211 buf[buf_pos++] = *s++; 212 } 213 else 214 { 215 /* Handle Escape sequences */ 216 switch (*(s + 1)) 217 { 218 case '$': 219 { 220 buf[buf_pos++] = '$'; 221 break; 222 } 223 224 case 'p': 225 case 'P': 226 { 227#if defined (HAVE_SNPRINTF) 228 snprintf (tmp, sizeof (tmp), "%ld", (long) getpid ()); 229#else 230 sprintf (tmp, "%ld", (long) getpid ()); 231#endif 232 strcpy (&buf[buf_pos], tmp); 233 buf_pos += strlen (tmp); 234 break; 235 } 236 237 case 'u': 238 case 'U': 239 { 240 if ((pwd = getpwuid (getuid ())) != NULL) 241 { 242#if defined (HAVE_SNPRINTF) 243 snprintf (tmp, sizeof (tmp), "%s", pwd->pw_name); 244#else 245 sprintf (tmp, "%s", pwd->pw_name); 246#endif 247 strcpy (&buf[buf_pos], tmp); 248 buf_pos += strlen (tmp); 249 } 250 break; 251 } 252 253 case 'h': 254 case 'H': 255 { 256 p = NULL; 257 if ((p = getenv ("HOME")) == NULL) 258 { 259 if ((pwd = getpwuid (getuid ())) != NULL) 260 p = pwd->pw_dir; 261 } 262 263 if (p) 264 { 265#if defined (HAVE_SNPRINTF) 266 snprintf (tmp, sizeof (tmp), "%s", p); 267#else 268 sprintf (tmp, "%s", p); 269#endif 270 strcpy (&buf[buf_pos], tmp); 271 buf_pos += strlen (tmp); 272 } 273 break; 274 } 275 276 case 't': 277 case 'T': 278 { 279 trace_strftime_now (tmp, sizeof (tmp), "%Y%m%d-%H%M%S"); 280 strcpy (&buf[buf_pos], tmp); 281 buf_pos += strlen (tmp); 282 break; 283 } 284 285 default: 286 /* Skip unknown escapes */ 287 break; 288 } 289 s += 2; 290 } 291 } 292 293 buf[buf_pos] = '\0'; 294 trace_fname = buf; 295 296 return; 297} 298 299 300void 301trace_start(void) 302{ 303 /* 304 * First stop any previous trace 305 */ 306 trace_stop (); 307 308#ifdef HAVE_GETTIMEOFDAY 309 gettimeofday (&starttime, NULL); 310#endif 311 312 /* 313 * If no trace filename is specified, use the default 314 */ 315 if (!trace_fname) 316 trace_fname = STRDUP (SQL_OPT_TRACE_FILE_DEFAULT); 317 318#if defined (stderr) 319 else if (STRCASEEQ (trace_fname, "stderr")) 320 { 321 trace_fp = stderr; 322 } 323#endif 324 325 else 326 { 327 int fd; 328 int fd_flags = O_WRONLY | O_CREAT | O_TRUNC; 329 int fd_mode = 0644; 330 331 332#if defined (unix) 333 /* 334 * As this is a security risk, we do not allow root to overwrite a file 335 */ 336 if (geteuid () == 0) 337 { 338 fd_flags |= O_EXCL; 339 } 340#endif 341 342 fd = open (trace_fname, fd_flags, fd_mode); 343 if (fd < 0 || (trace_fp = fdopen (fd, "w")) == NULL) 344 { 345 return; /* no tracing */ 346 } 347 348 trace_fp_close = 1; 349 350 /* 351 * Set trace stream to line buffered 352 */ 353 setvbuf (trace_fp, NULL, _IOLBF, 0); 354 } 355 356 /* 357 * Initialize the debug stream 358 */ 359 if (trace_fp == NULL) 360 { 361 return; 362 } 363 else 364 { 365 char mesgBuf[200]; 366 367 trace_emit ("** iODBC Trace file\n"); 368 369 /* 370 * Show start time 371 */ 372 trace_strftime_now (mesgBuf, sizeof (mesgBuf), 373 "** Trace started on %a %b %d %H:%M:%S %Y"); 374 trace_emit ("%s\n", mesgBuf); 375 376 /* 377 * Show Driver Manager version similar to SQLGetInfo (SQL_DM_VER) 378 */ 379 sprintf ((char *) mesgBuf, "%02d.%02d.%04d.%04d", 380 SQL_SPEC_MAJOR, 381 SQL_SPEC_MINOR, IODBC_BUILD / 10000, IODBC_BUILD % 10000); 382 trace_emit ("** Driver Manager: %s\n\n", mesgBuf); 383 } 384 385#if defined (linux) 386 { 387 extern char *__progname; 388 trace_set_appname (__progname); 389 } 390#elif defined(macintosh) || (defined(__APPLE__) && !defined(NO_CARBON)) 391 { 392 ProcessSerialNumber PSN; 393 ProcessInfoRec prec; 394 unsigned char processName[40]; 395 396 GetCurrentProcess (&PSN); 397 398 prec.processInfoLength = sizeof (ProcessInfoRec); 399 prec.processName = processName; 400 prec.processAppSpec = NULL; 401 402 if (GetProcessInformation (&PSN, &prec) == noErr) 403 { 404 processName[processName[0] + 1] = '\0'; 405 trace_set_appname (processName + 1); 406 } 407 else 408 trace_set_appname ("{No Application Name}"); 409 } 410#elif defined(__APPLE__) 411#ifdef MACOSX102 412 { 413 trace_set_appname ("{No Application Name}"); 414 } 415#else 416 { 417 trace_set_appname ((char *) getprogname ()); 418 } 419#endif 420#endif 421 422 /* 423 * Turn on tracing flag 424 */ 425 ODBCSharedTraceFlag = SQL_OPT_TRACE_ON; 426 427 return; 428} 429 430 431void 432trace_stop(void) 433{ 434 char mesgBuf[200]; 435 time_t now; 436 struct tm *timeNow; 437 438 if (trace_fp) 439 { 440 /* 441 * Show end time 442 */ 443 trace_strftime_now (mesgBuf, sizeof (mesgBuf), 444 "** Trace finished on %a %b %d %H:%M:%S %Y"); 445 trace_emit ("\n%s\n", mesgBuf); 446 447 if (trace_fp_close) 448 fclose (trace_fp); 449 } 450 451 ODBCSharedTraceFlag = SQL_OPT_TRACE_OFF; 452 trace_fp = NULL; 453 trace_fp_close = 0; 454} 455 456 457void 458trace_emitc (char c) 459{ 460 /* 461 * Make sure tracing is enabled 462 */ 463 if (!trace_fp) 464 { 465 ODBCSharedTraceFlag = SQL_OPT_TRACE_OFF; 466 return; 467 } 468 469 fputc (c, trace_fp); 470} 471 472 473void 474trace_emit (char *fmt, ...) 475{ 476 va_list ap; 477 478 /* 479 * Make sure tracing is enabled 480 */ 481 if (!trace_fp) 482 { 483 ODBCSharedTraceFlag = SQL_OPT_TRACE_OFF; 484 return; 485 } 486 487 va_start (ap, fmt); 488 vfprintf (trace_fp, fmt, ap); 489 va_end (ap); 490} 491 492 493void 494trace_emit_string (SQLCHAR *str, int len, int is_utf8) 495{ 496 ssize_t length = len; 497 int i, j; 498 long col; 499 SQLCHAR *ptr; 500 int bytes; 501 int truncated = 0; 502 503 if (!str) 504 return; 505 506 if (len == SQL_NTS) 507 length = strlen ((char *) str); 508 else if (len <= 0) 509 return; 510 511 /* 512 * Guard against very long strings 513 */ 514 if (length > MAX_EMIT_STRING) 515 { 516 length = MAX_EMIT_STRING; 517 truncated = 1; 518 } 519 520 /* 521 * Dump the (optional UTF-8) string in chunks of 40 characters 522 */ 523 ptr = str; 524 col = 0; 525 for (i = 0; i < length; i += bytes) 526 { 527 register int c = *ptr; 528 529 /* 530 * Assume this is a nul-terminated string 531 */ 532 if (!c) 533 break; 534 535 /* 536 * Print prefix 537 */ 538 if (col == 0) 539 trace_emit ("\t\t\t\t | "); 540 541 /* 542 * Take care of UTF-8 encoding 543 */ 544 if (!is_utf8) 545 bytes = 1; 546 else if (c < 128) 547 bytes = 1; 548 else if ((c & 0xE0) == 0xC0) 549 bytes = 2; 550 else if ((c & 0xF0) == 0xE0) 551 bytes = 3; 552 else if ((c & 0xF8) == 0xF0) 553 bytes = 4; 554 else if ((c & 0xFC) == 0xF8) 555 bytes = 5; 556 else if ((c & 0xFE) == 0xFC) 557 bytes = 6; 558 else 559 bytes = -1; /* Wrong UTF8 character */ 560 561 if (bytes > 0) 562 { 563 /* 564 * Emit the number of bytes calculated 565 */ 566 for (j = 0; j < bytes; j++) 567 trace_emitc (*ptr++); 568 } 569 else 570 { 571 /* 572 * Skip this bogus UTF8 character sequence and emit a single # 573 */ 574 for (bytes = 1, ptr++; (*ptr & 0xC0) == 0x80; bytes++) 575 ptr++; 576 trace_emitc ('#'); 577 } 578 579 /* 580 * After 40 characters, start a new line 581 */ 582 if (++col >= 40) 583 { 584 trace_emit (" |\n"); 585 col = 0; 586 } 587 } 588 589 /* 590 * Pad the last part of the string with spaces 591 */ 592 if (col > 0) 593 { 594 for (i = col; i < 40; i++) 595 trace_emitc (' '); 596 trace_emit (" |\n"); 597 } 598 599 if (truncated) 600 trace_emit ("\t\t\t\t | %-40.40s |\n", "(truncated)"); 601} 602 603 604void 605trace_emit_binary (unsigned char *str, int len) 606{ 607 long length = len; 608 int i; 609 long col; 610 unsigned char *ptr; 611 int truncated = 0; 612 char buf[80]; 613 char *HEX = "0123456789ABCDEF"; 614 615 if (!str || len <= 0) 616 return; 617 618 /* 619 * Guard against very long binary buffers 620 */ 621 if (length > MAX_EMIT_BINARY) 622 { 623 length = MAX_EMIT_BINARY; 624 truncated = 1; 625 } 626 627 ptr = str; 628 col = 0; 629 memset (buf, ' ', sizeof (buf)); 630 buf[40] = '\0'; 631 for (i = 0; i < length; i++) 632 { 633 unsigned char c = *ptr++; 634 635 /* 636 * Put data into buffer 637 */ 638 buf[3 * col] = HEX[(c >> 4) & 0xF]; 639 buf[3 * col + 1] = HEX[c & 0xF]; 640 if (isprint (c)) 641 buf[30 + col] = c; 642 else 643 buf[30 + col] = '.'; 644 645 /* 646 * After 10 bytes, start a new line 647 */ 648 if (++col > 9) 649 { 650 trace_emit_string ((SQLCHAR *) buf, 40, 0); 651 col = 0; 652 memset (buf, ' ', sizeof (buf)); 653 } 654 } 655 656 /* 657 * Pad the last part of the string with spaces 658 */ 659 if (col > 0) 660 trace_emit_string ((SQLCHAR *) buf, 40, 0); 661 662 if (truncated) 663 trace_emit ("\t\t\t\t | %-40.40s |\n", "(truncated)"); 664} 665 666 667void 668_trace_print_function (int func, int trace_leave, int retcode) 669{ 670 extern char *odbcapi_symtab[]; 671 char *ptr = "invalid retcode"; 672#ifdef HAVE_GETTIMEOFDAY 673 struct timeval tv; 674#endif 675 676 /* 677 * Guard against tracefile getting too big 678 */ 679 if (trace_fp && ftell (trace_fp) > MAX_TRACEFILE_LEN) 680 { 681 trace_emit ("\n*** TRACEFILE LIMIT REACHED ***\n"); 682 trace_stop (); 683 return; 684 } 685 686 /* 687 * Calculate timestamp 688 */ 689#ifdef HAVE_GETTIMEOFDAY 690 gettimeofday (&tv, NULL); 691 tv.tv_sec -= starttime.tv_sec; 692 tv.tv_usec -= starttime.tv_usec; 693 if (tv.tv_usec < 0) 694 { 695 tv.tv_sec--; 696 tv.tv_usec += 1000000L; 697 } 698 trace_emit ("\n[%06ld.%06ld]\n", tv.tv_sec, tv.tv_usec); 699#else 700 trace_emit ("\n"); 701#endif 702 703 switch (retcode) 704 { 705 _S (SQL_SUCCESS); 706 _S (SQL_SUCCESS_WITH_INFO); 707 _S (SQL_NO_DATA_FOUND); 708 _S (SQL_NEED_DATA); 709 _S (SQL_INVALID_HANDLE); 710 _S (SQL_ERROR); 711 _S (SQL_STILL_EXECUTING); 712 } 713 714#ifndef THREAD_IDENT 715#define THREAD_IDENT 0UL 716#endif 717 718 if (trace_leave == TRACE_LEAVE) 719 trace_emit ("%-15.15s %08lX EXIT %s with return code %d (%s)\n", 720 trace_appname ? trace_appname : "Application", 721 THREAD_IDENT, odbcapi_symtab[func], retcode, ptr); 722 else 723 trace_emit ("%-15.15s %08lX ENTER %s\n", 724 trace_appname ? trace_appname : "Application", 725 THREAD_IDENT, odbcapi_symtab[func]); 726} 727 728 729static char *_trace_sym_handletype[] = { 730 "SQLHANDLE", 731 "SQLHENV", 732 "SQLHDBC", 733 "SQLHSTMT", 734 "SQLDESC", 735 "SQLSENV" 736}; 737 738 739void 740_trace_handletype (SQLSMALLINT type) 741{ 742 char *ptr = "invalid handle type"; 743 switch (type) 744 { 745 _S (SQL_HANDLE_ENV); 746 _S (SQL_HANDLE_DBC); 747 _S (SQL_HANDLE_STMT); 748#if ODBCVER >= 0x0300 749 _S (SQL_HANDLE_DESC); 750 _S (SQL_HANDLE_SENV); 751#endif 752 } 753 754 trace_emit ("\t\t%-15.15s %d (%s)\n", "SQLSMALLINT", (int) type, ptr); 755} 756 757 758void 759_trace_handle_p (SQLSMALLINT type, SQLHANDLE * handle, int output) 760{ 761 if (!handle) 762 trace_emit ("\t\t%-15.15s * 0x0 (%s)\n", 763 _trace_sym_handletype[type], "SQL_NULL_HANDLE"); 764 else if (output) 765 trace_emit ("\t\t%-15.15s * %p (%p)\n", 766 _trace_sym_handletype[type], handle, *handle); 767 else 768 trace_emit ("\t\t%-15.15s * %p\n", _trace_sym_handletype[type], handle); 769} 770 771 772void 773_trace_handle (SQLSMALLINT type, SQLHANDLE handle) 774{ 775 if (!handle) 776 trace_emit ("\t\t%-15.15s 0x0 (%s)\n", 777 _trace_sym_handletype[type], "SQL_NULL_HANDLE"); 778 else 779 trace_emit ("\t\t%-15.15s %p\n", _trace_sym_handletype[type], handle); 780} 781 782 783/* 784 * Trace basic data types 785 */ 786void 787_trace_smallint (SQLSMALLINT i) 788{ 789 trace_emit ("\t\t%-15.15s %ld\n", "SQLSMALLINT", (long) i); 790} 791 792 793void 794_trace_usmallint (SQLUSMALLINT i) 795{ 796 trace_emit ("\t\t%-15.15s %lu\n", "SQLUSMALLINT", (unsigned long) i); 797} 798 799 800void 801_trace_integer (SQLINTEGER i) 802{ 803 trace_emit ("\t\t%-15.15s %ld\n", "SQLINTEGER", (long) i); 804} 805 806 807void 808_trace_uinteger (SQLUINTEGER i) 809{ 810 trace_emit ("\t\t%-15.15s %lu\n", "SQLUINTEGER", (unsigned long) i); 811} 812 813 814void 815_trace_pointer (SQLPOINTER p) 816{ 817 if (!p) 818 trace_emit ("\t\t%-15.15s 0x0\n", "SQLPOINTER"); 819 else 820 trace_emit ("\t\t%-15.15s %p\n", "SQLPOINTER", p); 821} 822 823 824void 825_trace_smallint_p (SQLSMALLINT *p, int output) 826{ 827 if (!p) 828 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLSMALLINT"); 829 else if (output) 830 trace_emit ("\t\t%-15.15s * %p (%ld)\n", "SQLSMALLINT", p, (long) *p); 831 else 832 trace_emit ("\t\t%-15.15s * %p\n", "SQLSMALLINT", p); 833} 834 835 836void 837_trace_usmallint_p (SQLUSMALLINT *p, int output) 838{ 839 if (!p) 840 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLUSMALLINT"); 841 else if (output) 842 trace_emit ("\t\t%-15.15s * %p (%lu)\n", "SQLUSMALLINT", p, (unsigned long) *p); 843 else 844 trace_emit ("\t\t%-15.15s * %p\n", "SQLUSMALLINT", p); 845} 846 847 848void 849_trace_integer_p (SQLINTEGER *p, int output) 850{ 851 if (!p) 852 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLINTEGER"); 853 else if (output) 854 trace_emit ("\t\t%-15.15s * %p (%ld)\n", "SQLINTEGER", p, (long) *p); 855 else 856 trace_emit ("\t\t%-15.15s * %p\n", "SQLINTEGER", p); 857} 858 859 860void 861_trace_uinteger_p (SQLUINTEGER *p, int output) 862{ 863 if (!p) 864 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLUINTEGER"); 865 else if (output) 866 trace_emit ("\t\t%-15.15s * %p (%lu)\n", "SQLUINTEGER", p, (unsigned long) *p); 867 else 868 trace_emit ("\t\t%-15.15s * %p\n", "SQLUINTEGER", p); 869} 870 871 872void 873_trace_stringlen (char *type, SQLINTEGER len) 874{ 875 if (len == SQL_NTS) 876 trace_emit ("\t\t%-15.15s %ld (SQL_NTS)\n", type, (long) len); 877 else 878 trace_emit ("\t\t%-15.15s %ld\n", type, (long) len); 879} 880 881void 882_trace_len (SQLLEN i) 883{ 884#ifdef _WIN64 885 trace_emit ("\t\t%-15.15s %I64d\n", "SQLLEN", (INT64) i); 886#else 887 trace_emit ("\t\t%-15.15s %ld\n", "SQLLEN", (long) i); 888#endif 889} 890 891 892void 893_trace_ulen (SQLULEN i) 894{ 895#ifdef _WIN64 896 trace_emit ("\t\t%-15.15s %I64u\n", "SQLLEN", (UINT64) i); 897#else 898 trace_emit ("\t\t%-15.15s %ld\n", "SQLLEN", (unsigned long) i); 899#endif 900} 901 902 903void 904_trace_len_p (SQLLEN *p, int output) 905{ 906 if (!p) 907 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLLEN"); 908 else if (output) 909#ifdef _WIN64 910 trace_emit ("\t\t%-15.15s * %p (%I64d)\n", "SQLLEN", p, (INT64) *p); 911#else 912 trace_emit ("\t\t%-15.15s * %p (%ld)\n", "SQLLEN", p, (long) *p); 913#endif 914 else 915 trace_emit ("\t\t%-15.15s * %p\n", "SQLLEN", p); 916} 917 918 919void 920_trace_ulen_p (SQLULEN *p, int output) 921{ 922 if (!p) 923 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLULEN"); 924 else if (output) 925#ifdef _WIN64 926 trace_emit ("\t\t%-15.15s * %p (%I64u)\n", "SQLULEN", p, (UINT64) *p); 927#else 928 trace_emit ("\t\t%-15.15s * %p (%lu)\n", "SQLULEN", p, (unsigned long) *p); 929#endif 930 else 931 trace_emit ("\t\t%-15.15s * %p\n", "SQLULEN", p); 932} 933 934 935void 936_trace_string (SQLCHAR * str, SQLSMALLINT len, SQLSMALLINT * lenptr, int output) 937{ 938 long length; 939 940 if (!str) 941 { 942 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLCHAR"); 943 return; 944 } 945 946 trace_emit ("\t\t%-15.15s * %p\n", "SQLCHAR", str); 947 948 if (!output) 949 return; 950 951 /* 952 * Calculate length of string 953 */ 954 if (lenptr) 955 length = *lenptr; 956 else 957 length = len; 958 959 if (length == SQL_NTS) 960 length = STRLEN (str); 961 962 if (*str && length) 963 trace_emit_string (str, length, 0); 964 else 965 trace_emit_string ( (SQLCHAR *) "(empty string)", SQL_NTS, 0); 966 967 return; 968} 969 970 971void 972_trace_string_w (SQLWCHAR * str, SQLSMALLINT len, SQLSMALLINT * lenptr, 973 int output) 974{ 975 long length; 976 977 if (!str) 978 { 979 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLWCHAR"); 980 return; 981 } 982 983 trace_emit ("\t\t%-15.15s * %p\n", "SQLWCHAR", str); 984 985 if (!output) 986 return; 987 988 /* 989 * Calculate length of string 990 */ 991 if (lenptr) 992 length = *lenptr; 993 else 994 length = len; 995 996 if (length == SQL_NTS) 997 length = wcslen (str); 998 999 /* 1000 * Translate wide string into UTF-8 format and print it 1001 */ 1002 if (*str && length) 1003 { 1004 SQLCHAR *str_u8 = dm_SQL_W2A (str, length); 1005 trace_emit_string (str_u8, SQL_NTS, 1); 1006 free (str_u8); 1007 } 1008 else 1009 trace_emit_string ((SQLCHAR *)"(empty string)", SQL_NTS, 0); 1010 1011 return; 1012} 1013 1014 1015void 1016_trace_c_type (SQLSMALLINT type) 1017{ 1018 char *ptr = "unknown C type"; 1019 1020 switch (type) 1021 { 1022 _S (SQL_C_BINARY); 1023 _S (SQL_C_BIT); 1024 /* _S (SQL_C_BOOKMARK); */ 1025 _S (SQL_C_CHAR); 1026 _S (SQL_C_DATE); 1027 _S (SQL_C_DEFAULT); 1028 _S (SQL_C_DOUBLE); 1029 _S (SQL_C_FLOAT); 1030#if (ODBCVER >= 0x0350) 1031 _S (SQL_C_GUID); 1032#endif 1033#if ODBCVER >= 0x0300 1034 _S (SQL_C_INTERVAL_DAY); 1035 _S (SQL_C_INTERVAL_DAY_TO_HOUR); 1036 _S (SQL_C_INTERVAL_DAY_TO_MINUTE); 1037 _S (SQL_C_INTERVAL_DAY_TO_SECOND); 1038 _S (SQL_C_INTERVAL_HOUR); 1039 _S (SQL_C_INTERVAL_HOUR_TO_MINUTE); 1040 _S (SQL_C_INTERVAL_HOUR_TO_SECOND); 1041 _S (SQL_C_INTERVAL_MINUTE); 1042 _S (SQL_C_INTERVAL_MINUTE_TO_SECOND); 1043 _S (SQL_C_INTERVAL_MONTH); 1044 _S (SQL_C_INTERVAL_SECOND); 1045 _S (SQL_C_INTERVAL_YEAR); 1046 _S (SQL_C_INTERVAL_YEAR_TO_MONTH); 1047#endif 1048 _S (SQL_C_LONG); 1049#if ODBCVER >= 0x0300 1050 _S (SQL_C_NUMERIC); 1051 _S (SQL_C_SBIGINT); 1052#endif 1053 _S (SQL_C_SHORT); 1054 _S (SQL_C_SLONG); 1055 _S (SQL_C_SSHORT); 1056 _S (SQL_C_STINYINT); 1057 _S (SQL_C_TIME); 1058 _S (SQL_C_TIMESTAMP); 1059 _S (SQL_C_TINYINT); 1060#if ODBCVER >= 0x0300 1061 _S (SQL_C_TYPE_DATE); 1062 _S (SQL_C_TYPE_TIME); 1063 _S (SQL_C_TYPE_TIMESTAMP); 1064 _S (SQL_C_UBIGINT); 1065#endif 1066 _S (SQL_C_ULONG); 1067 _S (SQL_C_USHORT); 1068 _S (SQL_C_UTINYINT); 1069 /* _S (SQL_C_VARBOOKMARK); */ 1070 _S (SQL_C_WCHAR); 1071 1072#if ODBCVER >= 0x0300 1073 _S (SQL_ARD_TYPE); 1074#endif 1075 } 1076 1077 trace_emit ("\t\t%-15.15s %d (%s)\n", "SQLSMALLINT ", type, ptr); 1078} 1079 1080 1081void 1082_trace_inouttype (SQLSMALLINT type) 1083{ 1084 char *ptr = "unknown Input/Output type"; 1085 1086 switch (type) 1087 { 1088 _S (SQL_PARAM_INPUT); 1089 _S (SQL_PARAM_OUTPUT); 1090 _S (SQL_PARAM_INPUT_OUTPUT); 1091 } 1092 1093 trace_emit ("\t\t%-15.15s %d (%s)\n", "SQLSMALLINT ", type, ptr); 1094} 1095 1096 1097void 1098_trace_sql_type (SQLSMALLINT type) 1099{ 1100 char *ptr = "unknown SQL type"; 1101 1102 switch (type) 1103 { 1104 _S (SQL_UNKNOWN_TYPE); 1105 _S (SQL_BIGINT); 1106 _S (SQL_BINARY); 1107 _S (SQL_BIT); 1108 _S (SQL_CHAR); 1109#if (ODBCVER < 0x0300) 1110 _S (SQL_DATE); 1111#else 1112 _S (SQL_DATETIME); 1113#endif 1114 _S (SQL_DECIMAL); 1115 _S (SQL_DOUBLE); 1116 _S (SQL_FLOAT); 1117#if (ODBCVER >= 0x0350) 1118 _S (SQL_GUID); 1119#endif 1120 _S (SQL_INTEGER); 1121 _S (SQL_LONGVARBINARY); 1122 _S (SQL_LONGVARCHAR); 1123 _S (SQL_NUMERIC); 1124 _S (SQL_REAL); 1125 _S (SQL_SMALLINT); 1126#if (ODBCVER < 0x0300) 1127 _S (SQL_TIME); 1128#else 1129 _S (SQL_INTERVAL); 1130#endif 1131 _S (SQL_TIMESTAMP); 1132 _S (SQL_TINYINT); 1133#if ODBCVER >= 0x0300 1134 _S (SQL_TYPE_DATE); 1135 _S (SQL_TYPE_TIME); 1136 _S (SQL_TYPE_TIMESTAMP); 1137#endif 1138 _S (SQL_VARBINARY); 1139 _S (SQL_VARCHAR); 1140 _S (SQL_WCHAR); 1141 _S (SQL_WLONGVARCHAR); 1142 _S (SQL_WVARCHAR); 1143 } 1144 1145 trace_emit ("\t\t%-15.15s %d (%s)\n", "SQLSMALLINT", (int) type, ptr); 1146} 1147 1148 1149void 1150_trace_sql_type_p (SQLSMALLINT *p, int output) 1151{ 1152 char *ptr = "unknown SQL type"; 1153 1154 if (!p) 1155 { 1156 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLSMALLINT"); 1157 return; 1158 } 1159 1160 if (!output) 1161 { 1162 trace_emit ("\t\t%-15.15s * %p\n", "SQLSMALLINT", p); 1163 return; 1164 } 1165 1166 switch (*p) 1167 { 1168 _S (SQL_UNKNOWN_TYPE); 1169 _S (SQL_BIGINT); 1170 _S (SQL_BINARY); 1171 _S (SQL_BIT); 1172 _S (SQL_CHAR); 1173#if (ODBCVER < 0x0300) 1174 _S (SQL_DATE); 1175#else 1176 _S (SQL_DATETIME); 1177#endif 1178 _S (SQL_DECIMAL); 1179 _S (SQL_DOUBLE); 1180 _S (SQL_FLOAT); 1181 1182#if (ODBCVER >= 0x0350) 1183 _S (SQL_GUID); 1184#endif 1185 _S (SQL_INTEGER); 1186 _S (SQL_LONGVARBINARY); 1187 _S (SQL_LONGVARCHAR); 1188 _S (SQL_NUMERIC); 1189 _S (SQL_REAL); 1190 _S (SQL_SMALLINT); 1191#if (ODBCVER < 0x0300) 1192 _S (SQL_TIME); 1193#else 1194 _S (SQL_INTERVAL); 1195#endif 1196 _S (SQL_TIMESTAMP); 1197 _S (SQL_TINYINT); 1198#if ODBCVER >= 0x0300 1199 _S (SQL_TYPE_DATE); 1200 _S (SQL_TYPE_TIME); 1201 _S (SQL_TYPE_TIMESTAMP); 1202#endif 1203 _S (SQL_VARBINARY); 1204 _S (SQL_VARCHAR); 1205 _S (SQL_WCHAR); 1206 _S (SQL_WLONGVARCHAR); 1207 _S (SQL_WVARCHAR); 1208 } 1209 1210 trace_emit ("\t\t%-15.15s * %p (%s)\n", "SQLSMALLINT", p, ptr); 1211} 1212 1213 1214#if ODBCVER >= 0x0300 1215void 1216_trace_sql_subtype (SQLSMALLINT *type, SQLSMALLINT *sub, int output) 1217{ 1218 char *ptr = NULL; 1219 1220 if (!type || !sub) 1221 { 1222 trace_emit ("\t\t%-15.15s * 0x0\n", "SQLSMALLINT"); 1223 return; 1224 } 1225 1226 if (!output) 1227 { 1228 trace_emit ("\t\t%-15.15s * %p\n", "SQLSMALLINT", sub); 1229 return; 1230 } 1231 1232 if (*type == SQL_DATETIME) 1233 { 1234 switch (*sub) 1235 { 1236 _S (SQL_CODE_DATE); 1237 _S (SQL_CODE_TIME); 1238 _S (SQL_CODE_TIMESTAMP); 1239 } 1240 } 1241 else if (*type == SQL_INTERVAL) 1242 { 1243 switch (*sub) 1244 { 1245 _S (SQL_CODE_YEAR); 1246 _S (SQL_CODE_MONTH); 1247 _S (SQL_CODE_DAY); 1248 _S (SQL_CODE_HOUR); 1249 _S (SQL_CODE_MINUTE); 1250 _S (SQL_CODE_SECOND); 1251 _S (SQL_CODE_YEAR_TO_MONTH); 1252 _S (SQL_CODE_DAY_TO_HOUR); 1253 _S (SQL_CODE_DAY_TO_MINUTE); 1254 _S (SQL_CODE_DAY_TO_SECOND); 1255 _S (SQL_CODE_HOUR_TO_MINUTE); 1256 _S (SQL_CODE_HOUR_TO_SECOND); 1257 _S (SQL_CODE_MINUTE_TO_SECOND); 1258 } 1259 } 1260 1261 if (ptr) 1262 trace_emit ("\t\t%-15.15s * %p (%s)\n", "SQLSMALLINT", sub, ptr); 1263 else 1264 trace_emit ("\t\t%-15.15s * %p (%d)\n", "SQLSMALLINT", sub, *sub); 1265} 1266#endif 1267 1268 1269void 1270_trace_bufferlen (SQLINTEGER length) 1271{ 1272 char buf[255]; 1273 char *ptr = NULL; 1274 1275 switch (length) 1276 { 1277 _S (SQL_NTS); 1278#if ODBCVER >= 0x0300 1279 _S (SQL_IS_POINTER); 1280 _S (SQL_IS_UINTEGER); 1281 _S (SQL_IS_INTEGER); 1282 _S (SQL_IS_USMALLINT); 1283 _S (SQL_IS_SMALLINT); 1284#endif 1285 } 1286 1287 /* 1288 * Translate binary buffer length 1289 */ 1290 if (length <= SQL_LEN_BINARY_ATTR_OFFSET) 1291 { 1292 sprintf (buf, "SQL_LEN_BINARY_ATTR(%ld)", (long) SQL_LEN_BINARY_ATTR(length)); 1293 ptr = buf; 1294 } 1295 1296 if (ptr) 1297 trace_emit ("\t\t%-15.15s * %ld (%s)\n", "SQLINTEGER", length, ptr); 1298 else 1299 trace_emit ("\t\t%-15.15s * %ld\n", "SQLINTEGER", (long) length); 1300} 1301