1 /*
2
3 Copyright (C) 2019 Olaf Till <i7tiol@t-online.de>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; If not, see <http://www.gnu.org/licenses/>.
17
18 */
19
20 #define EXTERNAL_BINARY
21 #include "config.h"
22
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <sys/socket.h>
26 #include <netdb.h>
27 #include <poll.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/select.h>
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <signal.h>
34 #include <math.h>
35 #include <string.h>
36 #include <stdint.h>
37
gnulib_close(int fd)38 int gnulib_close (int fd)
39 {
40 return close (fd);
41 }
42
gnulib_socket_pfinet_sockstream(int protocol)43 int gnulib_socket_pfinet_sockstream (int protocol)
44 {
45 return socket (PF_INET, SOCK_STREAM, protocol);
46 }
47
gnulib_recv(int sockfd,void * buf,size_t len,int flags)48 ssize_t gnulib_recv (int sockfd, void *buf, size_t len, int flags)
49 {
50 return recv (sockfd, buf, len, flags);
51 }
52
gnulib_send(int sockfd,const void * buf,size_t len,int flags)53 ssize_t gnulib_send (int sockfd, const void *buf, size_t len, int flags)
54 {
55 return send (sockfd, buf, len, flags);
56 }
57
gnulib_malloc(size_t size)58 void *gnulib_malloc (size_t size)
59 {
60 return malloc (size);
61 }
62
63 static
get_canonname_hints(void)64 const struct addrinfo *get_canonname_hints (void)
65 {
66 static struct addrinfo hints;
67
68 if (! hints.ai_socktype) // ai_socktype == 0 means "any type", so it
69 // should be distinct from SOCK_STREAM
70 {
71 hints.ai_family = AF_INET;
72 hints.ai_socktype = SOCK_STREAM;
73 hints.ai_protocol = 0;
74 hints.ai_flags = AI_CANONNAME;
75 }
76
77 return &hints;
78 }
79
80 static
get_set_port_hints(void)81 const struct addrinfo *get_set_port_hints (void)
82 {
83 static struct addrinfo hints;
84
85 if (! hints.ai_socktype) // ai_socktype == 0 means "any type", so it
86 // should be distinct from SOCK_STREAM
87 {
88 hints.ai_family = AF_INET;
89 hints.ai_socktype = SOCK_STREAM;
90 hints.ai_protocol = 0;
91 hints.ai_flags = 0;
92 }
93
94 return &hints;
95 }
96
97 inline static
get_ai(void)98 struct addrinfo **get_ai (void)
99 {
100 static struct addrinfo *ai;
101
102 return &ai;
103 }
104
gnulib_freeaddrinfo(void)105 void gnulib_freeaddrinfo (void)
106 {
107 freeaddrinfo (*get_ai ());
108 }
109
gnulib_get_canonname(const char * hostname)110 const char *gnulib_get_canonname (const char *hostname)
111 {
112 struct addrinfo **ai_p = get_ai ();
113
114 if (getaddrinfo (hostname, NULL, get_canonname_hints (), ai_p))
115 return "";
116 else
117 return (*ai_p)->ai_canonname;
118 }
119
gnulib_set_port(const char * hostname,const char * port)120 int gnulib_set_port (const char *hostname, const char *port)
121 {
122 struct addrinfo **ai_p = get_ai ();
123
124 if (getaddrinfo (hostname, port, get_set_port_hints (), ai_p))
125 return 1;
126 else
127 return 0;
128 }
129
gnulib_connect(int sockfd)130 int gnulib_connect (int sockfd)
131 {
132 struct addrinfo **ai_p = get_ai ();
133
134 return connect (sockfd, (*ai_p)->ai_addr, (*ai_p)->ai_addrlen);
135 }
136
137 // 'poll'-related stuff
138
gnulib_alloc_pollfds(int n)139 void *gnulib_alloc_pollfds (int n)
140 {
141 return calloc (n, sizeof (struct pollfd));
142 }
143
gnulib_poll_in_wrapper(int * in_out,void * pfds_arg,int nfds,int timeout)144 int gnulib_poll_in_wrapper (int *in_out, void *pfds_arg, int nfds, int timeout)
145 {
146 struct pollfd *pfds = pfds_arg;
147
148 for (int id = 0; id < nfds; id++)
149 {
150 pfds[id].fd = in_out[id];
151
152 pfds[id].events = POLLIN;
153
154 pfds[id].revents = 0;
155 }
156
157 int ret;
158
159 ret = poll (pfds, nfds, timeout);
160
161 for (int id = 0; id < nfds; id++)
162 {
163 in_out[id] = pfds[id].revents;
164 }
165
166 return ret;
167 }
168
gnulib_pollin_1_noblock(int fd)169 int gnulib_pollin_1_noblock (int fd)
170 {
171 struct pollfd pfd;
172
173 pfd.fd = fd;
174 pfd.events = POLLIN;
175 pfd.revents = 0;
176
177 return poll (&pfd, 1, 0);
178 }
179
gnulib_pollin_2_block(int fd1,int fd2,int * rev1,int * rev2)180 int gnulib_pollin_2_block (int fd1, int fd2, int *rev1, int *rev2)
181 {
182 struct pollfd pfd[2];
183
184 pfd[0].fd = fd1;
185 pfd[0].events = POLLIN;
186 pfd[0].revents = 0;
187
188 pfd[1].fd = fd2;
189 pfd[1].events = POLLIN;
190 pfd[1].revents = 0;
191
192 int ret;
193
194 ret = poll (pfd, 2, -1);
195
196 *rev1 = pfd[0].revents;
197
198 *rev2 = pfd[1].revents;
199
200 return ret;
201 }
202
203 // 'select'-related stuff
204
gnulib_get_fd_setsize(void)205 int gnulib_get_fd_setsize (void)
206 {
207 return FD_SETSIZE;
208 }
209
210 static
gnulib_select_wrapper(int nfds,void * rfds,void * wfds,void * efds,double dtimeout,char ** err_msg)211 int gnulib_select_wrapper (int nfds, void *rfds, void *wfds, void *efds,
212 double dtimeout, char **err_msg)
213 {
214 // make a pointer already here for convenience (so it can be set to
215 // NULL)
216 struct timeval timeout;
217 struct timeval *timeout_p = &timeout;
218
219 if (dtimeout < 0)
220 timeout_p = NULL;
221 else
222 {
223 double ipart, fpart;
224 fpart = modf (dtimeout, &ipart);
225 timeout.tv_sec = lrint (ipart);
226 timeout.tv_usec = lrint (fpart * 1000);
227 }
228
229 int ret = select (nfds,
230 (fd_set *) rfds,
231 (fd_set *) wfds,
232 (fd_set *) efds,
233 timeout_p);
234
235 if (ret == -1)
236 switch (errno)
237 {
238 case EBADF:
239 *err_msg = "EBADF";
240 break;
241 case EINTR:
242 *err_msg = "EINTR";
243 break;
244 case EINVAL:
245 *err_msg = "EINVAL";
246 break;
247 default:
248 *err_msg = "unknown error";
249 }
250
251 return ret;
252 }
253
254 inline static
get_rfds(void)255 fd_set *get_rfds (void)
256 {
257 static fd_set rfds;
258
259 return &rfds;
260 }
261
262 inline static
get_wfds(void)263 fd_set *get_wfds (void)
264 {
265 static fd_set wfds;
266
267 return &wfds;
268 }
269
270 inline static
get_efds(void)271 fd_set *get_efds (void)
272 {
273 static fd_set efds;
274
275 return &efds;
276 }
277
gnulib_fd_zero_all(void)278 void gnulib_fd_zero_all (void)
279 {
280 FD_ZERO (get_rfds ());
281 FD_ZERO (get_wfds ());
282 FD_ZERO (get_efds ());
283 }
284
gnulib_add_to_rfds(int fd)285 void gnulib_add_to_rfds (int fd)
286 {
287 FD_SET (fd, get_rfds ());
288 }
289
gnulib_add_to_wfds(int fd)290 void gnulib_add_to_wfds (int fd)
291 {
292 FD_SET (fd, get_wfds ());
293 }
294
gnulib_add_to_efds(int fd)295 void gnulib_add_to_efds (int fd)
296 {
297 FD_SET (fd, get_efds ());
298 }
299
gnulib_select(int nfds,double dtimeout,char ** err_msg)300 int gnulib_select (int nfds, double dtimeout, char **err_msg)
301 {
302
303 return gnulib_select_wrapper (nfds, get_rfds (), get_wfds (), get_efds (),
304 dtimeout, err_msg);
305 }
306
gnulib_fd_isset_rfds(int fd)307 int gnulib_fd_isset_rfds (int fd)
308 {
309 return FD_ISSET (fd, get_rfds ());
310 }
311
gnulib_fd_isset_wfds(int fd)312 int gnulib_fd_isset_wfds (int fd)
313 {
314 return FD_ISSET (fd, get_wfds ());
315 }
316
gnulib_fd_isset_efds(int fd)317 int gnulib_fd_isset_efds (int fd)
318 {
319 return FD_ISSET (fd, get_efds ());
320 }
321
322 // end of 'select'-related stuff
323
gnulib_fstat_reg_exec_nonsuid(int fd)324 int gnulib_fstat_reg_exec_nonsuid (int fd)
325 {
326 struct stat statbuf;
327
328 return (fstat (fd, &statbuf)
329 || ! S_ISREG (statbuf.st_mode)
330 || ! (statbuf.st_mode & S_IXUSR)
331 || statbuf.st_mode & S_ISUID);
332 }
333
gnulib_perror(const char * s)334 void gnulib_perror (const char *s)
335 {
336 perror (s);
337 }
338
339 // 'sigset'-related stuff
340
gnulib_alloc_sigset(void)341 void *gnulib_alloc_sigset (void)
342 {
343 return gnulib_malloc (sizeof (sigset_t));
344 }
345
gnulib_get_sigmask(void * dest)346 int gnulib_get_sigmask (void *dest)
347 {
348 return pthread_sigmask (SIG_SETMASK, NULL, (sigset_t *)dest);
349 }
350
gnulib_set_sigmask(void * src)351 int gnulib_set_sigmask (void *src)
352 {
353 return pthread_sigmask (SIG_SETMASK, (sigset_t *)src, NULL);
354 }
355
gnulib_sigismember(const void * sig_set,int signum)356 int gnulib_sigismember (const void *sig_set, int signum)
357 {
358 return sigismember ((sigset_t *)sig_set, signum);
359 }
360
gnulib_set_newset_one_signal(void * sig_set,int signum)361 void gnulib_set_newset_one_signal (void *sig_set, int signum)
362 {
363 sigemptyset ((sigset_t *)sig_set);
364
365 sigaddset ((sigset_t *)sig_set, signum);
366 }
367
gnulib_unblock(void * sig_set)368 int gnulib_unblock (void *sig_set)
369 {
370 return pthread_sigmask (SIG_UNBLOCK, (sigset_t *)sig_set, NULL);
371 }
372
373 // 'sigaction'-related stuff
374
gnulib_alloc_sigaction(void)375 void *gnulib_alloc_sigaction (void)
376 {
377 return gnulib_malloc (sizeof (struct sigaction));
378 }
379
gnulib_getsigaction(int signum,void * dest)380 int gnulib_getsigaction (int signum, void *dest)
381 {
382 return sigaction (signum, NULL, (struct sigaction *)dest);
383 }
384
gnulib_setsigaction(int signum,void * src)385 int gnulib_setsigaction (int signum, void *src)
386 {
387 return sigaction (signum, (struct sigaction *)src, NULL);
388 }
389
gnulib_copy_sigaction(void * dest,const void * src)390 void gnulib_copy_sigaction (void *dest, const void *src)
391 {
392 memcpy (dest, src, sizeof (struct sigaction));
393 }
394
gnulib_remove_sa_restart(void * sig_action)395 void gnulib_remove_sa_restart (void *sig_action)
396 {
397 ((struct sigaction *)sig_action)->sa_flags &= ~ SA_RESTART;
398 }
399
gnulib_install_sighandler(int signum,void (* handler)(int))400 int gnulib_install_sighandler (int signum, void (*handler) (int))
401 {
402 struct sigaction sa;
403
404 sa.sa_handler = handler;
405
406 sa.sa_flags = 0;
407
408 if (sigemptyset (&sa.sa_mask)
409 || sigaction (signum, &sa, NULL))
410 return -1;
411 else
412 return 0;
413 }
414
415 // end of 'sigaction'-related stuff
416
417 // these are probably defined at Windows as macros in winsock.h or
418 // winsock2.h
gnulib_htonl(uint32_t hostlong)419 uint32_t gnulib_htonl (uint32_t hostlong)
420 {
421 return htonl (hostlong);
422 }
gnulib_ntohl(uint32_t netlong)423 uint32_t gnulib_ntohl (uint32_t netlong)
424 {
425 return ntohl (netlong);
426 }
427
gnulib_mkdir_mode_0700(const char * pathname)428 int gnulib_mkdir_mode_0700 (const char *pathname)
429 {
430 mkdir (pathname, 0700);
431 }
432
gnulib_getpass(const char * prompt)433 char* gnulib_getpass (const char *prompt)
434 {
435 return getpass (prompt);
436 }
437