Line data Source code
1 : #include <config.h>
2 :
3 : #include <stdio.h>
4 :
5 : #if HAVE_STDLIB_H
6 : #include <stdlib.h>
7 : #endif /* HAVE_STDLIB_H */
8 :
9 : #if HAVE_STRING_H
10 : #include <string.h>
11 : #endif /* HAVE_STRING_H */
12 :
13 : #if HAVE_UNISTD_H
14 : #include <unistd.h>
15 : #endif
16 :
17 : #ifndef DBNTWIN32
18 : #include <freetds/replacements.h>
19 : #endif
20 :
21 : #include <ctpublic.h>
22 : #include "common.h"
23 : #ifdef TDS_STATIC_CAST
24 : #include "ctlib.h"
25 : #endif
26 :
27 : char USER[512];
28 : char SERVER[512];
29 : char PASSWORD[512];
30 : char DATABASE[512];
31 :
32 : COMMON_PWD common_pwd = {0};
33 :
34 : static char *DIRNAME = NULL;
35 : static const char *BASENAME = NULL;
36 :
37 : static const char *PWD = "../../../PWD";
38 :
39 :
40 : int cslibmsg_cb_invoked = 0;
41 : int clientmsg_cb_invoked = 0;
42 : int servermsg_cb_invoked = 0;
43 :
44 : static CS_RETCODE continue_logging_in(CS_CONTEXT ** ctx, CS_CONNECTION ** conn, CS_COMMAND ** cmd, int verbose);
45 :
46 : #if defined(__MINGW32__) || defined(_MSC_VER)
47 : static char *
48 : tds_dirname(char* path)
49 : {
50 : char *p, *p2;
51 :
52 : for (p = path + strlen(path); --p > path && (*p == '/' || *p == '\\');)
53 : *p = '\0';
54 :
55 : p = strrchr(path, '/');
56 : if (!p)
57 : p = path;
58 : p2 = strrchr(p, '\\');
59 : if (p2)
60 : p = p2;
61 : *p = 0;
62 : return path;
63 : }
64 : #define dirname tds_dirname
65 :
66 : #endif
67 :
68 : CS_RETCODE
69 1048 : read_login_info(void)
70 : {
71 1048 : FILE *in = NULL;
72 : char line[512];
73 : char *s1, *s2;
74 :
75 1048 : if (common_pwd.initialized) {
76 0 : strcpy(USER, common_pwd.USER);
77 0 : strcpy(PASSWORD, common_pwd.PASSWORD);
78 0 : strcpy(SERVER, common_pwd.SERVER);
79 0 : strcpy(DATABASE, common_pwd.DATABASE);
80 0 : return CS_SUCCEED;
81 : }
82 :
83 1048 : s1 = getenv("TDSPWDFILE");
84 1048 : if (s1 && s1[0])
85 0 : in = fopen(s1, "r");
86 0 : if (!in)
87 1048 : in = fopen(PWD, "r");
88 1048 : if (!in) {
89 0 : fprintf(stderr, "Can not open PWD file \"%s\"\n\n", PWD);
90 0 : return CS_FAIL;
91 : }
92 :
93 19912 : while (fgets(line, sizeof(line), in)) {
94 18864 : s1 = strtok(line, "=");
95 18864 : s2 = strtok(NULL, "\n");
96 18864 : if (!s1 || !s2) {
97 11266 : continue;
98 : }
99 7598 : if (!strcmp(s1, "UID")) {
100 1048 : strcpy(USER, s2);
101 6550 : } else if (!strcmp(s1, "SRV")) {
102 1048 : strcpy(SERVER, s2);
103 5502 : } else if (!strcmp(s1, "PWD")) {
104 1048 : strcpy(PASSWORD, s2);
105 4454 : } else if (!strcmp(s1, "DB")) {
106 1048 : strcpy(DATABASE, s2);
107 : }
108 : }
109 1048 : fclose(in);
110 1048 : return CS_SUCCEED;
111 : }
112 :
113 : static CS_RETCODE
114 16 : establish_login(int argc, char **argv)
115 : {
116 : extern char *optarg;
117 : extern int optind;
118 16 : COMMON_PWD options = {0};
119 : #if !defined(__MINGW32__) && !defined(_MSC_VER)
120 : int ch;
121 : #endif
122 :
123 16 : BASENAME = basename((char *)argv[0]);
124 16 : DIRNAME = dirname((char *)argv[0]);
125 :
126 : #if !defined(__MINGW32__) && !defined(_MSC_VER)
127 : /* process command line options (handy for manual testing) */
128 32 : while ((ch = getopt(argc, argv, "U:P:S:D:f:m:v")) != -1) {
129 0 : switch (ch) {
130 0 : case 'U':
131 0 : strcpy(options.USER, optarg);
132 0 : break;
133 0 : case 'P':
134 0 : strcpy(options.PASSWORD, optarg);
135 0 : break;
136 0 : case 'S':
137 0 : strcpy(options.SERVER, optarg);
138 0 : break;
139 0 : case 'D':
140 0 : strcpy(options.DATABASE, optarg);
141 0 : break;
142 0 : case 'f': /* override default PWD file */
143 0 : PWD = strdup(optarg);
144 0 : break;
145 0 : case 'm':
146 0 : common_pwd.maxlength = strtol(optarg, NULL, 10);
147 0 : case 'v':
148 0 : common_pwd.fverbose = 1;
149 0 : break;
150 0 : case '?':
151 : default:
152 0 : fprintf(stderr, "usage: %s [-v] [-f PWD]\n"
153 : " [-U username] [-P password]\n"
154 : " [-S servername] [-D database]\n"
155 : , BASENAME);
156 0 : exit(1);
157 : }
158 : }
159 : #endif
160 16 : read_login_info();
161 :
162 : /* override PWD file with command-line options */
163 :
164 16 : if (*options.USER)
165 0 : strcpy(USER, options.USER);
166 16 : if (*options.PASSWORD)
167 0 : strcpy(PASSWORD, options.PASSWORD);
168 16 : if (*options.SERVER)
169 0 : strcpy(SERVER, options.SERVER);
170 16 : if (*options.DATABASE)
171 0 : strcpy(DATABASE, options.DATABASE);
172 :
173 16 : return (*USER && *SERVER && *DATABASE)? CS_SUCCEED : CS_FAIL;
174 : }
175 :
176 : CS_RETCODE
177 16 : try_ctlogin_with_options(int argc, char **argv, CS_CONTEXT ** ctx, CS_CONNECTION ** conn, CS_COMMAND ** cmd, int verbose)
178 : {
179 : CS_RETCODE ret;
180 :
181 16 : if ((ret = establish_login(argc, argv)) != CS_SUCCEED) {
182 0 : if (verbose) {
183 0 : fprintf(stderr, "read_login_info() failed!\n");
184 : }
185 : return ret;
186 : }
187 16 : return continue_logging_in(ctx, conn, cmd, verbose);
188 : }
189 :
190 : /* old way: because I'm too lazy to change every unit test */
191 : CS_RETCODE
192 1024 : try_ctlogin(CS_CONTEXT ** ctx, CS_CONNECTION ** conn, CS_COMMAND ** cmd, int verbose)
193 : {
194 : CS_RETCODE ret;
195 :
196 1024 : if ((ret = read_login_info()) != CS_SUCCEED) {
197 0 : if (verbose) {
198 0 : fprintf(stderr, "read_login_info() failed!\n");
199 : }
200 : return ret;
201 : }
202 1024 : return continue_logging_in(ctx, conn, cmd, verbose);
203 : }
204 :
205 : CS_RETCODE
206 1040 : continue_logging_in(CS_CONTEXT ** ctx, CS_CONNECTION ** conn, CS_COMMAND ** cmd, int verbose)
207 : {
208 : CS_RETCODE ret;
209 : char query[512+10];
210 : #ifdef TDS_STATIC_CAST
211 : TDSCONTEXT *tds_ctx;
212 : #endif
213 :
214 1040 : ret = cs_ctx_alloc(CS_VERSION_100, ctx);
215 1040 : if (ret != CS_SUCCEED) {
216 0 : if (verbose) {
217 0 : fprintf(stderr, "Context Alloc failed!\n");
218 : }
219 : return ret;
220 : }
221 :
222 : #ifdef TDS_STATIC_CAST
223 : /* Force default date format, some tests rely on it */
224 1040 : tds_ctx = (TDSCONTEXT *) (*ctx)->tds_ctx;
225 1040 : if (tds_ctx && tds_ctx->locale && tds_ctx->locale->datetime_fmt) {
226 1040 : free(tds_ctx->locale->datetime_fmt);
227 1040 : tds_ctx->locale->datetime_fmt = strdup("%b %d %Y %I:%M%p");
228 : }
229 : #endif
230 :
231 1040 : ret = ct_init(*ctx, CS_VERSION_100);
232 1040 : if (ret != CS_SUCCEED) {
233 0 : if (verbose) {
234 0 : fprintf(stderr, "Library Init failed!\n");
235 : }
236 : return ret;
237 : }
238 1040 : if ((ret = ct_callback(*ctx, NULL, CS_SET, CS_CLIENTMSG_CB,
239 : (CS_VOID*) clientmsg_cb)) != CS_SUCCEED) {
240 0 : fprintf(stderr, "ct_callback() failed\n");
241 0 : return ret;
242 : }
243 1040 : if ((ret = ct_callback(*ctx, NULL, CS_SET, CS_SERVERMSG_CB, servermsg_cb)) != CS_SUCCEED) {
244 0 : fprintf(stderr, "ct_callback() failed\n");
245 0 : return ret;
246 : }
247 1040 : ret = ct_con_alloc(*ctx, conn);
248 1040 : if (ret != CS_SUCCEED) {
249 0 : if (verbose) {
250 0 : fprintf(stderr, "Connect Alloc failed!\n");
251 : }
252 : return ret;
253 : }
254 1040 : ret = ct_con_props(*conn, CS_SET, CS_USERNAME, USER, CS_NULLTERM, NULL);
255 1040 : if (ret != CS_SUCCEED) {
256 0 : if (verbose) {
257 0 : fprintf(stderr, "ct_con_props() SET USERNAME failed!\n");
258 : }
259 : return ret;
260 : }
261 1040 : ret = ct_con_props(*conn, CS_SET, CS_PASSWORD, PASSWORD, CS_NULLTERM, NULL);
262 1040 : if (ret != CS_SUCCEED) {
263 0 : if (verbose) {
264 0 : fprintf(stderr, "ct_con_props() SET PASSWORD failed!\n");
265 : }
266 : return ret;
267 : }
268 :
269 1040 : printf("connecting as %s to %s.%s\n", USER, SERVER, DATABASE);
270 :
271 1040 : ret = ct_connect(*conn, SERVER, CS_NULLTERM);
272 1040 : if (ret != CS_SUCCEED) {
273 0 : if (verbose) {
274 0 : fprintf(stderr, "Connection failed!\n");
275 : }
276 0 : ct_con_drop(*conn);
277 0 : *conn = NULL;
278 0 : cs_ctx_drop(*ctx);
279 0 : *ctx = NULL;
280 0 : return ret;
281 : }
282 1040 : ret = ct_cmd_alloc(*conn, cmd);
283 1040 : if (ret != CS_SUCCEED) {
284 0 : if (verbose) {
285 0 : fprintf(stderr, "Command Alloc failed!\n");
286 : }
287 0 : ct_con_drop(*conn);
288 0 : *conn = NULL;
289 0 : cs_ctx_drop(*ctx);
290 0 : *ctx = NULL;
291 0 : return ret;
292 : }
293 :
294 1040 : sprintf(query, "use %s", DATABASE);
295 :
296 1040 : ret = run_command(*cmd, query);
297 1040 : if (ret != CS_SUCCEED)
298 : return ret;
299 :
300 1040 : return CS_SUCCEED;
301 : }
302 :
303 :
304 : CS_RETCODE
305 1040 : try_ctlogout(CS_CONTEXT * ctx, CS_CONNECTION * conn, CS_COMMAND * cmd, int verbose)
306 : {
307 : CS_RETCODE ret;
308 :
309 1040 : ret = ct_cancel(conn, NULL, CS_CANCEL_ALL);
310 1040 : if (ret != CS_SUCCEED) {
311 0 : if (verbose) {
312 0 : fprintf(stderr, "ct_cancel() failed!\n");
313 : }
314 : return ret;
315 : }
316 1040 : ct_cmd_drop(cmd);
317 1040 : ct_close(conn, CS_UNUSED);
318 1040 : ct_con_drop(conn);
319 1040 : ct_exit(ctx, CS_UNUSED);
320 1040 : cs_ctx_drop(ctx);
321 :
322 1040 : return CS_SUCCEED;
323 : }
324 :
325 : /* Run commands from which we expect no results returned */
326 : CS_RETCODE
327 1884 : run_command(CS_COMMAND * cmd, const char *sql)
328 : {
329 : CS_RETCODE ret, results_ret;
330 : CS_INT result_type;
331 :
332 1884 : if (cmd == NULL) {
333 : return CS_FAIL;
334 : }
335 :
336 1884 : ret = ct_command(cmd, CS_LANG_CMD, sql, CS_NULLTERM, CS_UNUSED);
337 1884 : if (ret != CS_SUCCEED) {
338 0 : fprintf(stderr, "ct_command() failed\n");
339 0 : return ret;
340 : }
341 1884 : ret = ct_send(cmd);
342 1884 : if (ret != CS_SUCCEED) {
343 2 : fprintf(stderr, "ct_send() failed\n");
344 2 : return ret;
345 : }
346 5766 : while ((results_ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
347 3884 : switch ((int) result_type) {
348 : case CS_CMD_SUCCEED:
349 : break;
350 : case CS_CMD_DONE:
351 : break;
352 46 : case CS_CMD_FAIL:
353 46 : fprintf(stderr, "ct_results() result_type CS_CMD_FAIL.\n");
354 : /* return CS_FAIL; */
355 46 : break;
356 0 : default:
357 0 : fprintf(stderr, "ct_results() unexpected result_type.\n");
358 0 : return CS_FAIL;
359 : }
360 : }
361 1882 : switch ((int) results_ret) {
362 : case CS_END_RESULTS:
363 : break;
364 0 : case CS_FAIL:
365 0 : fprintf(stderr, "ct_results() failed.\n");
366 0 : return CS_FAIL;
367 : break;
368 0 : default:
369 0 : fprintf(stderr, "ct_results() unexpected return.\n");
370 0 : return CS_FAIL;
371 : }
372 :
373 : return CS_SUCCEED;
374 : }
375 :
376 : CS_INT
377 24 : cslibmsg_cb(CS_CONTEXT * connection, CS_CLIENTMSG * errmsg)
378 : {
379 24 : cslibmsg_cb_invoked++;
380 24 : fprintf(stderr, "\nCS-Library Message:\n");
381 96 : fprintf(stderr, "number %d layer %d origin %d severity %d number %d\n",
382 : errmsg->msgnumber,
383 24 : CS_LAYER(errmsg->msgnumber),
384 72 : CS_ORIGIN(errmsg->msgnumber), CS_SEVERITY(errmsg->msgnumber), CS_NUMBER(errmsg->msgnumber));
385 24 : fprintf(stderr, "msgstring: %s\n", errmsg->msgstring);
386 24 : fprintf(stderr, "osstring: %s\n", (errmsg->osstringlen > 0)
387 : ? errmsg->osstring : "(null)");
388 24 : return CS_SUCCEED;
389 : }
390 :
391 :
392 :
393 : CS_RETCODE
394 16 : clientmsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_CLIENTMSG * errmsg)
395 : {
396 16 : clientmsg_cb_invoked++;
397 16 : fprintf(stderr, "\nOpen Client Message:\n");
398 64 : fprintf(stderr, "number %d layer %d origin %d severity %d number %d\n",
399 : errmsg->msgnumber,
400 16 : CS_LAYER(errmsg->msgnumber),
401 48 : CS_ORIGIN(errmsg->msgnumber), CS_SEVERITY(errmsg->msgnumber), CS_NUMBER(errmsg->msgnumber));
402 16 : fprintf(stderr, "msgstring: %s\n", errmsg->msgstring);
403 16 : fprintf(stderr, "osstring: %s\n", (errmsg->osstringlen > 0)
404 : ? errmsg->osstring : "(null)");
405 16 : return CS_SUCCEED;
406 : }
407 :
408 : CS_RETCODE
409 3180 : servermsg_cb(CS_CONTEXT * context, CS_CONNECTION * connection, CS_SERVERMSG * srvmsg)
410 : {
411 3180 : servermsg_cb_invoked++;
412 :
413 3180 : if (srvmsg->msgnumber == 5701 || srvmsg->msgnumber == 5703) {
414 2860 : fprintf(stderr, "%s\n", srvmsg->text);
415 2860 : return CS_SUCCEED;
416 : }
417 :
418 640 : fprintf(stderr, "%s Message %d severity %d state %d line %d:\n",
419 320 : srvmsg->svrnlen > 0? srvmsg->svrname : "Server",
420 : srvmsg->msgnumber, srvmsg->severity, srvmsg->state, srvmsg->line);
421 320 : if (srvmsg->proclen > 0)
422 8 : fprintf(stderr, "proc %s: ", srvmsg->proc);
423 320 : fprintf(stderr, "\t\"%s\"\n", srvmsg->text);
424 :
425 320 : return CS_SUCCEED;
426 : }
427 :
428 : const char *
429 380 : res_type_str(CS_RETCODE ret)
430 : {
431 : static char str[64];
432 :
433 : #define S(s) case s: return #s;
434 380 : switch ((int) ret) {
435 : S(CS_ROW_RESULT)
436 0 : S(CS_PARAM_RESULT)
437 64 : S(CS_STATUS_RESULT)
438 0 : S(CS_MSG_RESULT)
439 64 : S(CS_CMD_SUCCEED)
440 142 : S(CS_CMD_DONE)
441 0 : S(CS_CMD_FAIL)
442 24 : S(CS_COMPUTE_RESULT)
443 : #undef S
444 : }
445 :
446 0 : sprintf(str, "?? (%d)", (int) ret);
447 0 : return str;
448 : }
|