Line data Source code
1 : /*
2 : * Purpose: Test for dbsqlexec on closed connection
3 : */
4 :
5 : #include "common.h"
6 :
7 : #if HAVE_UNISTD_H
8 : #include <unistd.h>
9 : #endif /* HAVE_UNISTD_H */
10 :
11 : #include <freetds/time.h>
12 :
13 : #if HAVE_SYS_SOCKET_H
14 : #include <sys/socket.h>
15 : #endif /* HAVE_SYS_SOCKET_H */
16 :
17 : #if HAVE_SYS_STAT_H
18 : #include <sys/stat.h>
19 : #endif /* HAVE_SYS_STAT_H */
20 :
21 : #if HAVE_SYS_IOCTL_H
22 : #include <sys/ioctl.h>
23 : #endif /* HAVE_SYS_IOCTL_H */
24 :
25 : #if HAVE_SYS_WAIT_H
26 : #include <sys/wait.h>
27 : #endif /* HAVE_SYS_WAIT_H */
28 :
29 : #if HAVE_NETINET_IN_H
30 : #include <netinet/in.h>
31 : #endif /* HAVE_NET_INET_IN_H */
32 :
33 : #include <freetds/utils.h>
34 :
35 : char *UNITTEST;
36 :
37 : #if HAVE_FSTAT && defined(S_IFSOCK)
38 :
39 : static int end_socket = -1;
40 :
41 : static int
42 16 : shutdown_socket(DBPROCESS *dbproc)
43 : {
44 : union {
45 : struct sockaddr sa;
46 : char data[256];
47 : } u;
48 : SOCKLEN_T addrlen;
49 : struct stat file_stat;
50 : TDS_SYS_SOCKET sockets[2];
51 :
52 16 : TDS_SYS_SOCKET socket = DBIOWDESC(dbproc);
53 :
54 16 : if (fstat(socket, &file_stat))
55 : return 0;
56 16 : if ((file_stat.st_mode & S_IFSOCK) != S_IFSOCK)
57 : return 0;
58 :
59 16 : addrlen = sizeof(u);
60 16 : if (tds_getsockname(socket, &u.sa, &addrlen) < 0 || (u.sa.sa_family != AF_INET && u.sa.sa_family != AF_INET6))
61 : return 0;
62 :
63 : /* replace socket with a new one */
64 16 : if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
65 : return 0;
66 :
67 16 : tds_socket_set_nosigpipe(sockets[0], 1);
68 :
69 : /* substitute socket */
70 16 : close(socket);
71 16 : dup2(sockets[0], socket);
72 :
73 : /* close connection */
74 16 : close(sockets[0]);
75 16 : end_socket = sockets[1];
76 16 : return 1;
77 : }
78 :
79 : static int
80 16 : test(int close_socket)
81 : {
82 : LOGINREC *login;
83 : DBPROCESS *dbproc;
84 : RETCODE ret;
85 16 : int expected_error = -1;
86 :
87 16 : printf("Starting %s\n", UNITTEST);
88 :
89 16 : dbinit();
90 :
91 16 : dberrhandle(syb_err_handler);
92 16 : dbmsghandle(syb_msg_handler);
93 :
94 16 : printf("About to logon\n");
95 :
96 16 : login = dblogin();
97 16 : DBSETLPWD(login, PASSWORD);
98 16 : DBSETLUSER(login, USER);
99 16 : DBSETLAPP(login, "t0020");
100 :
101 16 : printf("About to open\n");
102 :
103 16 : dbproc = dbopen(login, SERVER);
104 16 : dbsetuserdata(dbproc, (BYTE*) &expected_error);
105 16 : if (strlen(DATABASE))
106 16 : dbuse(dbproc, DATABASE);
107 16 : dbloginfree(login);
108 :
109 16 : dbcmd(dbproc, "select * from sysobjects");
110 16 : printf("dbsqlexec should not hang.\n");
111 :
112 16 : ret = dbsettime(15);
113 16 : if (ret != SUCCEED) {
114 0 : fprintf(stderr, "Failed. Error setting timeout.\n");
115 0 : return 1;
116 : }
117 :
118 16 : if (!shutdown_socket(dbproc)) {
119 0 : fprintf(stderr, "Error shutting down connection\n");
120 0 : return 1;
121 : }
122 16 : if (close_socket)
123 8 : close(end_socket);
124 :
125 16 : alarm(20);
126 16 : expected_error = close_socket ? 20006 : 20003;
127 16 : ret = dbsqlexec(dbproc);
128 16 : alarm(0);
129 16 : if (ret != FAIL) {
130 0 : fprintf(stderr, "Failed. Expected FAIL to be returned.\n");
131 0 : return 1;
132 : }
133 :
134 16 : dbsetuserdata(dbproc, NULL);
135 16 : if (!close_socket)
136 8 : close(end_socket);
137 16 : dbexit();
138 :
139 16 : printf("dblib okay on %s\n", __FILE__);
140 16 : return 0;
141 : }
142 :
143 : int
144 8 : main(int argc, char **argv)
145 : {
146 8 : UNITTEST = argv[0];
147 8 : read_login_info(argc, argv);
148 8 : if (test(0) || test(1))
149 : return 1;
150 : return 0;
151 : }
152 :
153 : #else
154 : int
155 : main(void)
156 : {
157 : fprintf(stderr, "Not possible for this platform.\n");
158 : return 0;
159 : }
160 : #endif
161 :
|