r23785: use the GPLv3 boilerplate as recommended by the FSF and the license text
[samba.git] / examples / libsmbclient / smbwrapper / select.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Samba select/poll implementation
5    Copyright (C) Andrew Tridgell 1992-1998
6    Copyright (C) Derrell Lipman 2003-2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  * WHY THIS FILE?
24  *
25  * This file implements the two functions in the select() family, as required
26  * by samba.  The samba native functions, though, implement a pipe to help
27  * alleviate a deadlock problem, but which creates problems of its own (the
28  * timeout stops working correctly).  Those functions also require that all
29  * signal handlers call a function which writes to the pipe -- a task which is
30  * difficult to do in the smbwrapper environment.
31  */
32
33
34 #include <sys/select.h>
35 #include <errno.h>
36 #include <stdio.h>
37
38 int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval)
39 {
40         int ret;
41         fd_set *readfds2, readfds_buf;
42
43         /* If readfds is NULL we need to provide our own set. */
44         if (readfds) {
45                 readfds2 = readfds;
46         } else {
47                 readfds2 = &readfds_buf;
48                 FD_ZERO(readfds2);
49         }
50
51         errno = 0;
52         ret = select(maxfd,readfds2,writefds,errorfds,tval);
53
54         if (ret <= 0) {
55                 FD_ZERO(readfds2);
56                 if (writefds)
57                         FD_ZERO(writefds);
58                 if (errorfds)
59                         FD_ZERO(errorfds);
60         }
61
62         return ret;
63 }
64
65 /*******************************************************************
66  Similar to sys_select() but catch EINTR and continue.
67  This is what sys_select() used to do in Samba.
68 ********************************************************************/
69
70 int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval)
71 {
72         int ret;
73         fd_set *readfds2, readfds_buf, *writefds2, writefds_buf, *errorfds2, errorfds_buf;
74         struct timeval tval2, *ptval, end_time, now_time;
75         extern void GetTimeOfDay(struct timeval *tval);
76
77         readfds2 = (readfds ? &readfds_buf : NULL);
78         writefds2 = (writefds ? &writefds_buf : NULL);
79         errorfds2 = (errorfds ? &errorfds_buf : NULL);
80         if (tval) {
81                 GetTimeOfDay(&end_time);
82                 end_time.tv_sec += tval->tv_sec;
83                 end_time.tv_usec += tval->tv_usec;
84                 end_time.tv_sec += end_time.tv_usec / 1000000;
85                 end_time.tv_usec %= 1000000;
86                 ptval = &tval2;
87         } else {
88                 ptval = NULL;
89         }
90
91         do {
92                 if (readfds)
93                         readfds_buf = *readfds;
94                 if (writefds)
95                         writefds_buf = *writefds;
96                 if (errorfds)
97                         errorfds_buf = *errorfds;
98                 if (tval) {
99                         GetTimeOfDay(&now_time);
100                         tval2.tv_sec = end_time.tv_sec - now_time.tv_sec;
101                         tval2.tv_usec = end_time.tv_usec - now_time.tv_usec;
102                         if ((signed long) tval2.tv_usec < 0) {
103                                 tval2.tv_usec += 1000000;
104                                 tval2.tv_sec--;
105                         }
106                         if ((signed long) tval2.tv_sec < 0) {
107                                 ret = 0;
108                                 break;          /* time has already elapsed */
109                         }
110                 }
111
112                 ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval);
113         } while (ret == -1 && errno == EINTR);
114
115         if (readfds)
116                 *readfds = readfds_buf;
117         if (writefds)
118                 *writefds = writefds_buf;
119         if (errorfds)
120                 *errorfds = errorfds_buf;
121
122         return ret;
123 }