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