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
shutdown_socket(DBPROCESS * dbproc)42 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 TDS_SYS_SOCKET socket = DBIOWDESC(dbproc);
53
54 if (fstat(socket, &file_stat))
55 return 0;
56 if ((file_stat.st_mode & S_IFSOCK) != S_IFSOCK)
57 return 0;
58
59 addrlen = sizeof(u);
60 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 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
65 return 0;
66
67 tds_socket_set_nosigpipe(sockets[0], 1);
68
69 /* substitute socket */
70 close(socket);
71 dup2(sockets[0], socket);
72
73 /* close connection */
74 close(sockets[0]);
75 end_socket = sockets[1];
76 return 1;
77 }
78
79 static int
test(int close_socket)80 test(int close_socket)
81 {
82 LOGINREC *login;
83 DBPROCESS *dbproc;
84 RETCODE ret;
85 int expected_error = -1;
86
87 printf("Starting %s\n", UNITTEST);
88
89 dbinit();
90
91 dberrhandle(syb_err_handler);
92 dbmsghandle(syb_msg_handler);
93
94 printf("About to logon\n");
95
96 login = dblogin();
97 DBSETLPWD(login, PASSWORD);
98 DBSETLUSER(login, USER);
99 DBSETLAPP(login, "t0020");
100
101 printf("About to open\n");
102
103 dbproc = dbopen(login, SERVER);
104 dbsetuserdata(dbproc, (BYTE*) &expected_error);
105 if (strlen(DATABASE))
106 dbuse(dbproc, DATABASE);
107 dbloginfree(login);
108
109 dbcmd(dbproc, "select * from sysobjects");
110 printf("dbsqlexec should not hang.\n");
111
112 ret = dbsettime(15);
113 if (ret != SUCCEED) {
114 fprintf(stderr, "Failed. Error setting timeout.\n");
115 return 1;
116 }
117
118 if (!shutdown_socket(dbproc)) {
119 fprintf(stderr, "Error shutting down connection\n");
120 return 1;
121 }
122 if (close_socket)
123 close(end_socket);
124
125 alarm(20);
126 expected_error = close_socket ? 20006 : 20003;
127 ret = dbsqlexec(dbproc);
128 alarm(0);
129 if (ret != FAIL) {
130 fprintf(stderr, "Failed. Expected FAIL to be returned.\n");
131 return 1;
132 }
133
134 dbsetuserdata(dbproc, NULL);
135 if (!close_socket)
136 close(end_socket);
137 dbexit();
138
139 printf("dblib okay on %s\n", __FILE__);
140 return 0;
141 }
142
143 int
main(int argc,char ** argv)144 main(int argc, char **argv)
145 {
146 UNITTEST = argv[0];
147 read_login_info(argc, argv);
148 if (test(0) || test(1))
149 return 1;
150 return 0;
151 }
152
153 #else
154 int
main(void)155 main(void)
156 {
157 fprintf(stderr, "Not possible for this platform.\n");
158 return 0;
159 }
160 #endif
161
162