LDPRELOAD: Add ioctl, fcntl, and setsockopt support
[vpp.git] / extras / vcl-ldpreload / src / libvcl-ldpreload / vcom.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <dlfcn.h>
19 #include <pthread.h>
20 #include <time.h>
21 #include <stdarg.h>
22
23 #include <libvcl-ldpreload/vcom_socket_wrapper.h>
24 #include <libvcl-ldpreload/vcom.h>
25 #include <sys/time.h>
26
27 #include <uri/vppcom.h>
28 #include <libvcl-ldpreload/vcom_socket.h>
29
30 /* GCC have printf type attribute check. */
31 #ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
32 #define PRINTF_ATTRIBUTE(a,b)                       \
33     __attribute__ ((__format__ (__printf__, a, b)))
34 #else
35 #define PRINTF_ATTRIBUTE(a,b)
36 #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
37
38 #define HAVE_CONSTRUCTOR_ATTRIBUTE
39 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
40 #define CONSTRUCTOR_ATTRIBUTE                       \
41     __attribute__ ((constructor))
42 #else
43 #define CONSTRUCTOR_ATTRIBUTE
44 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
45
46 #define HAVE_DESTRUCTOR_ATTRIBUTE
47 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
48 #define DESTRUCTOR_ATTRIBUTE                        \
49     __attribute__ ((destructor))
50 #else
51 #define DESTRUCTOR_ATTRIBUTE
52 #endif
53
54 #define HAVE_ADDRESS_SANITIZER_ATTRIBUTE
55 #ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
56 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE           \
57     __attribute__((no_sanitize_address))
58 #else
59 #define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
60 #endif
61
62 #define VCOM_SOCKET_FD_MAX  0x10000
63
64 static char vcom_app_name[MAX_VCOM_APP_NAME];
65
66 /*
67  * RETURN:  0 on success or -1 on error.
68  * */
69 int
70 vcom_set_app_name (char *__app_name)
71 {
72   return snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-%s-%d",
73                    __app_name, getpid ()) < 0 ? -1 : 0;
74 }
75
76 static char *
77 vcom_get_app_name ()
78 {
79   if (vcom_app_name[0] == '\0')
80     {
81       snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-app-%d", getpid ());
82     }
83   return vcom_app_name;
84 }
85
86 /*
87  * 1 if init, 0 otherwise
88  */
89 static int is_vcom_init;
90
91 /*
92  * TBD: Make it thread safe
93  */
94
95 /*
96  * constructor function called before main is called
97  * RETURN: 0 on success -1 on failure
98  * */
99 static inline int
100 vcom_init ()
101 {
102   pid_t pid = getpid ();
103
104   if (!is_vcom_init)
105     {
106       if (vppcom_app_create (vcom_get_app_name ()) != 0)
107         {
108           printf ("\n[%d] vcom_init...failed!\n", pid);
109           if (VCOM_DEBUG > 0)
110             fprintf (stderr,
111                      "[%d] vcom_init: vppcom_app_create failed!\n", pid);
112           return -1;
113         }
114       if (vcom_socket_main_init () != 0)
115         {
116           printf ("\n[%d] vcom_init...failed!\n", pid);
117           if (VCOM_DEBUG > 0)
118             fprintf (stderr,
119                      "[%d] vcom_init: vcom_socket_main_init failed!\n", pid);
120           return -1;
121         }
122
123       is_vcom_init = 1;
124       printf ("\n[%d] vcom_init...done!\n", pid);
125     }
126   return 0;
127 }
128
129 static inline void
130 vcom_destroy (void)
131 {
132   pid_t pid = getpid ();
133
134   if (is_vcom_init)
135     {
136       vcom_socket_main_destroy ();
137       vppcom_app_destroy ();
138       is_vcom_init = 0;
139       fprintf (stderr, "\n[%d] vcom_destroy...done!\n", pid);
140     }
141 }
142
143 static inline int
144 is_vcom_socket_fd (int fd)
145 {
146   return vcom_socket_is_vcom_fd (fd);
147 }
148
149 static inline int
150 is_vcom_epfd (int epfd)
151 {
152   return vcom_socket_is_vcom_epfd (epfd);
153 }
154
155
156 /*
157  *
158  * Generic glibc fd api
159  *
160  */
161
162 /* Close the file descriptor FD.
163
164    This function is a cancellation point and therefore
165    not marked with __THROW.  */
166 /*
167  * PRE:     is_vcom_socket_fd(__fd) == 1
168  * RETURN:  0 on success and -1 for errors.
169  * */
170 int
171 vcom_close (int __fd)
172 {
173   if (vcom_init () != 0)
174     {
175       return -1;
176     }
177
178   if (vcom_socket_close (__fd) != 0)
179     {
180       return -1;
181     }
182
183   return 0;
184 }
185
186 /*
187  * RETURN:  0 on success, or -1 on error
188  */
189 int
190 close (int __fd)
191 {
192   int rv;
193   pid_t pid = getpid ();
194
195   if (is_vcom_socket_fd (__fd) || is_vcom_epfd (__fd))
196     {
197       if (VCOM_DEBUG > 0)
198         vcom_socket_main_show ();
199       rv = vcom_close (__fd);
200       if (VCOM_DEBUG > 0)
201         fprintf (stderr, "[%d] close: " "'%04d'='%04d'\n", pid, rv, __fd);
202       if (VCOM_DEBUG > 0)
203         vcom_socket_main_show ();
204       if (rv != 0)
205         {
206           errno = -rv;
207           return -1;
208         }
209       return 0;
210     }
211   return libc_close (__fd);
212 }
213
214 /* Read NBYTES into BUF from FD.  Return the
215    number read, -1 for errors or 0 for EOF.
216
217    This function is a cancellation point and therefore
218    not marked with __THROW.  */
219 ssize_t
220 vcom_read (int __fd, void *__buf, size_t __nbytes)
221 {
222   if (vcom_init () != 0)
223     {
224       return -1;
225     }
226
227   return vcom_socket_read (__fd, __buf, __nbytes);
228 }
229
230 ssize_t
231 read (int __fd, void *__buf, size_t __nbytes)
232 {
233   ssize_t size = 0;
234   pid_t pid = getpid ();
235   pthread_t tid = pthread_self ();
236
237   if (is_vcom_socket_fd (__fd))
238     {
239       if (VCOM_DEBUG > 0)
240         fprintf (stderr,
241                  "[%d][%lu (0x%lx)] read:1 "
242                  "'%04d'='%04d', '%p', '%04d'\n",
243                  pid, (unsigned long) tid, (unsigned long) tid,
244                  (int) size, __fd, __buf, (int) __nbytes);
245       size = vcom_read (__fd, __buf, __nbytes);
246       if (VCOM_DEBUG > 0)
247         fprintf (stderr,
248                  "[%d][%lu (0x%lx)] read:2 "
249                  "'%04d'='%04d', '%p', '%04d'\n",
250                  pid, (unsigned long) tid, (unsigned long) tid,
251                  (int) size, __fd, __buf, (int) __nbytes);
252       if (size < 0)
253         {
254           errno = -size;
255           return -1;
256         }
257       return size;
258     }
259   return libc_read (__fd, __buf, __nbytes);
260 }
261
262 ssize_t
263 vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt)
264 {
265   if (vcom_init () != 0)
266     {
267       return -1;
268     }
269
270   return vcom_socket_readv (__fd, __iov, __iovcnt);
271 }
272
273 ssize_t
274 readv (int __fd, const struct iovec * __iov, int __iovcnt)
275 {
276   ssize_t size = 0;
277
278   if (is_vcom_socket_fd (__fd))
279     {
280       size = vcom_readv (__fd, __iov, __iovcnt);
281       if (size < 0)
282         {
283           errno = -size;
284           return -1;
285         }
286       return size;
287     }
288   else
289     return libc_readv (__fd, __iov, __iovcnt);
290 }
291
292 /* Write N bytes of BUF to FD.  Return the number written, or -1.
293
294    This function is a cancellation point and therefore
295    not marked with __THROW.  */
296 ssize_t
297 vcom_write (int __fd, const void *__buf, size_t __n)
298 {
299   if (vcom_init () != 0)
300     {
301       return -1;
302     }
303
304   return vcom_socket_write (__fd, (void *) __buf, __n);
305 }
306
307 ssize_t
308 write (int __fd, const void *__buf, size_t __n)
309 {
310   ssize_t size = 0;
311   pid_t pid = getpid ();
312   pthread_t tid = pthread_self ();
313
314   if (is_vcom_socket_fd (__fd))
315     {
316       if (VCOM_DEBUG > 0)
317         fprintf (stderr,
318                  "[%d][%lu (0x%lx)] write:1 "
319                  "'%04d'='%04d', '%p', '%04d'\n",
320                  pid, (unsigned long) tid, (unsigned long) tid,
321                  (int) size, __fd, __buf, (int) __n);
322       size = vcom_write (__fd, __buf, __n);
323       if (VCOM_DEBUG > 0)
324         fprintf (stderr,
325                  "[%d][%lu (0x%lx)] write:2 "
326                  "'%04d'='%04d', '%p', '%04d'\n",
327                  pid, (unsigned long) tid, (unsigned long) tid,
328                  (int) size, __fd, __buf, (int) __n);
329       if (size < 0)
330         {
331           errno = -size;
332           return -1;
333         }
334       return size;
335     }
336   return libc_write (__fd, __buf, __n);
337 }
338
339 ssize_t
340 vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt)
341 {
342   if (vcom_init () != 0)
343     {
344       return -1;
345     }
346
347   return vcom_socket_writev (__fd, __iov, __iovcnt);
348 }
349
350 ssize_t
351 writev (int __fd, const struct iovec * __iov, int __iovcnt)
352 {
353   ssize_t size = 0;
354
355   if (is_vcom_socket_fd (__fd))
356     {
357       size = vcom_writev (__fd, __iov, __iovcnt);
358       if (size < 0)
359         {
360           errno = -size;
361           return -1;
362         }
363       return size;
364     }
365   else
366     return libc_writev (__fd, __iov, __iovcnt);
367 }
368
369 /* Do the file control operation described by CMD on FD.
370    The remaining arguments are interpreted depending on CMD.
371
372    This function is a cancellation point and therefore
373    not marked with __THROW.  */
374 int
375 vcom_fcntl_va (int __fd, int __cmd, va_list __ap)
376 {
377   if (vcom_init () != 0)
378     {
379       return -1;
380     }
381
382   return vcom_socket_fcntl_va (__fd, __cmd, __ap);
383 }
384
385 int
386 vcom_fcntl (int __fd, int __cmd, ...)
387 {
388   int rv = -1;
389   va_list ap;
390
391   if (is_vcom_socket_fd (__fd))
392     {
393       va_start (ap, __cmd);
394       rv = vcom_fcntl_va (__fd, __cmd, ap);
395       va_end (ap);
396     }
397   return rv;
398 }
399
400 int
401 fcntl (int __fd, int __cmd, ...)
402 {
403   int rv;
404   va_list ap;
405   pid_t pid = getpid ();
406
407   va_start (ap, __cmd);
408   if (is_vcom_socket_fd (__fd))
409     {
410       rv = vcom_fcntl_va (__fd, __cmd, ap);
411       if (VCOM_DEBUG > 0)
412         fprintf (stderr,
413                  "[%d] fcntl: "
414                  "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __cmd);
415       if (rv < 0)
416         {
417           errno = -rv;
418           rv = -1;
419         }
420       goto out;
421     }
422   rv = libc_vfcntl (__fd, __cmd, ap);
423
424 out:
425   va_end (ap);
426   return rv;
427 }
428
429 int
430 vcom_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
431 {
432   if (vcom_init () != 0)
433     {
434       return -1;
435     }
436
437   return vcom_socket_ioctl_va (__fd, __cmd, __ap);
438 }
439
440 int
441 vcom_ioctl (int __fd, unsigned long int __cmd, ...)
442 {
443   int rv = -1;
444   va_list ap;
445
446   if (is_vcom_socket_fd (__fd))
447     {
448       va_start (ap, __cmd);
449       rv = vcom_ioctl_va (__fd, __cmd, ap);
450       va_end (ap);
451     }
452   return rv;
453 }
454
455 int
456 ioctl (int __fd, unsigned long int __cmd, ...)
457 {
458   int rv;
459   va_list ap;
460   pid_t pid = getpid ();
461
462   va_start (ap, __cmd);
463   if (is_vcom_socket_fd (__fd))
464     {
465       rv = vcom_ioctl_va (__fd, __cmd, ap);
466       if (VCOM_DEBUG > 0)
467         fprintf (stderr,
468                  "[%d] ioctl: "
469                  "'%04d'='%04d', '%04ld'\n", pid, rv, __fd, __cmd);
470       if (rv < 0)
471         {
472           errno = -rv;
473           rv = -1;
474         }
475       goto out;
476     }
477   rv = libc_vioctl (__fd, __cmd, ap);
478
479 out:
480   va_end (ap);
481   return rv;
482 }
483
484 /*
485  * Check the first NFDS descriptors each in READFDS (if not NULL) for
486  *  read readiness, in WRITEFDS (if not NULL) for write readiness,
487  *  and in EXCEPTFDS (if not NULL) for exceptional conditions.
488  *  If TIMEOUT is not NULL, time out after waiting the interval
489  *  specified therein.  Returns the number of ready descriptors,
490  *  or -1 for errors.
491  *
492  * This function is a cancellation point and therefore not marked
493  * with __THROW.
494  * */
495
496 /*
497  * clear all vcom FDs from fd_sets __readfds, __writefds and
498  * __exceptfds and update the new nfds
499  *
500  * new nfds is the highest-numbered file descriptor
501  * in any of the three sets, plus 1
502  *
503  * Return the number of file descriptors contained in the
504  * three descriptor sets. ie. the total number of the bits
505  * that are set in  __readfds, __writefds and __exceptfds
506  */
507 static inline int
508 vcom_fd_clear (int __nfds,
509                int *__new_nfds,
510                fd_set * __restrict __readfds,
511                fd_set * __restrict __writefds,
512                fd_set * __restrict __exceptfds)
513 {
514   int fd;
515   /* invalid max_fd is -1 */
516   int max_fd = -1;
517   int nfd = 0;
518
519
520   /* clear all vcom fd from the sets */
521   for (fd = 0; fd < __nfds; fd++)
522     {
523
524       /* clear vcom fd from set */
525       /*
526        * F fd set
527        */
528 #define _(F)                                    \
529       if ((F) && FD_ISSET (fd, (F)))            \
530         {                                       \
531           if (is_vcom_socket_fd (fd))           \
532             {                                   \
533               FD_CLR (fd, (F));                 \
534             }                                   \
535         }
536
537
538       _(__readfds);
539       _(__writefds);
540       _(__exceptfds);
541 #undef _
542     }
543
544   /*
545    *  compute nfd and __new_nfds
546    */
547   for (fd = 0; fd < __nfds; fd++)
548     {
549
550       /*
551        * F fd set
552        */
553 #define _(F)                                    \
554       if ((F) && FD_ISSET (fd, (F)))            \
555         {                                       \
556           if (fd > max_fd)                      \
557             {                                   \
558               max_fd = fd;                      \
559             }                                   \
560           ++nfd;                                \
561         }
562
563
564       _(__readfds);
565       _(__writefds);
566       _(__exceptfds);
567 #undef _
568     }
569
570   *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
571   return nfd;
572 }
573
574 /*
575  * Return the number of file descriptors contained in the
576  * three descriptor sets. ie. the total number of the bits
577  * that are set in  __readfds, __writefds and __exceptfds
578  */
579 static inline int
580 vcom_fd_set (int __nfds,
581              /* dest */
582              int *__new_nfds,
583              fd_set * __restrict __readfds,
584              fd_set * __restrict __writefds, fd_set * __restrict __exceptfds,
585              /* src */
586              fd_set * __restrict __saved_readfds,
587              fd_set * __restrict __saved_writefds,
588              fd_set * __restrict __saved_exceptfds)
589 {
590   int fd;
591   /* invalid max_fd is -1 */
592   int max_fd = -1;
593   int nfd = 0;
594
595   for (fd = 0; fd < __nfds; fd++)
596     {
597       /*
598        * F fd set
599        * S saved fd set
600        */
601 #define _(S,F)                                  \
602       if ((F) && (S) && FD_ISSET (fd, (S)))     \
603         {                                       \
604           if (is_vcom_socket_fd (fd))           \
605             {                                   \
606               FD_SET (fd, (F));                 \
607             }                                   \
608         }
609
610
611       _(__saved_readfds, __readfds);
612       _(__saved_writefds, __writefds);
613 #undef _
614     }
615
616
617   /*
618    *  compute nfd and __new_nfds
619    */
620   for (fd = 0; fd < __nfds; fd++)
621     {
622
623       /*
624        * F fd set
625        */
626 #define _(F)                                    \
627       if ((F) && FD_ISSET (fd, (F)))            \
628         {                                       \
629           if (fd > max_fd)                      \
630             {                                   \
631               max_fd = fd;                      \
632             }                                   \
633           ++nfd;                                \
634         }
635
636
637       _(__readfds);
638       _(__writefds);
639       _(__exceptfds);
640 #undef _
641     }
642
643   *__new_nfds = max_fd != -1 ? max_fd + 1 : 0;
644   return nfd;
645 }
646
647 /*
648  * split select sets(src) into
649  * vcom sets(dest1) and libc sets(dest2)
650  */
651 static inline void
652 vcom_fd_set_split (
653                     /* src, select sets */
654                     int nfds,
655                     fd_set * __restrict readfds,
656                     fd_set * __restrict writefds,
657                     fd_set * __restrict exceptfds,
658                     /* dest1, vcom sets */
659                     int *vcom_nfds,
660                     fd_set * __restrict vcom_readfds,
661                     fd_set * __restrict vcom_writefds,
662                     fd_set * __restrict vcom_exceptfds, int *vcom_nfd,
663                     /* dest2, libc sets */
664                     int *libc_nfds,
665                     fd_set * __restrict libc_readfds,
666                     fd_set * __restrict libc_writefds,
667                     fd_set * __restrict libc_exceptfds, int *libc_nfd)
668 {
669   int fd;
670
671   /* vcom */
672   /* invalid max_fd is -1 */
673   int vcom_max_fd = -1;
674   int vcom_nfd2 = 0;
675
676   /* libc */
677   /* invalid max_fd is -1 */
678   int libc_max_fd = -1;
679   int libc_nfd2 = 0;
680
681
682   for (fd = 0; fd < nfds; fd++)
683     {
684       /*
685        * S select fd set
686        * V vcom fd set
687        * L libc fd set
688        */
689 #define _(S,V,L)                            \
690       if ((S) && FD_ISSET (fd, (S)))        \
691         {                                   \
692           if (is_vcom_socket_fd (fd))       \
693             {                               \
694               if ((V))                      \
695                 {                           \
696                   FD_SET(fd, (V));          \
697                   if (fd > vcom_max_fd)     \
698                     {                       \
699                       vcom_max_fd = fd;     \
700                     }                       \
701                   ++vcom_nfd2;              \
702                 }                           \
703             }                               \
704           else                              \
705             {                               \
706               if ((L))                      \
707                 {                           \
708                   FD_SET(fd, (L));          \
709                   if (fd > libc_max_fd)     \
710                     {                       \
711                       libc_max_fd = fd;     \
712                     }                       \
713                   ++libc_nfd2;              \
714                 }                           \
715             }                               \
716         }
717
718
719       _(readfds, vcom_readfds, libc_readfds);
720       _(writefds, vcom_writefds, libc_writefds);
721       _(exceptfds, vcom_exceptfds, libc_exceptfds);
722 #undef _
723     }
724
725   if (vcom_nfds)
726     *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0;
727   if (vcom_nfd)
728     *vcom_nfd = vcom_nfd2;
729   if (libc_nfds)
730     *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0;
731   if (libc_nfd)
732     *libc_nfd = libc_nfd2;
733 }
734
735 /*
736  * merge vcom sets(src1) and libc sets(src2)
737  * into select sets(dest)
738  */
739 static inline void
740 vcom_fd_set_merge (
741                     /* dest, select sets */
742                     int *nfds,
743                     fd_set * __restrict readfds,
744                     fd_set * __restrict writefds,
745                     fd_set * __restrict exceptfds, int *nfd,
746                     /* src1, vcom sets */
747                     int vcom_nfds,
748                     fd_set * __restrict vcom_readfds,
749                     fd_set * __restrict vcom_writefds,
750                     fd_set * __restrict vcom_exceptfds, int vcom_nfd,
751                     /* src2, libc sets */
752                     int libc_nfds,
753                     fd_set * __restrict libc_readfds,
754                     fd_set * __restrict libc_writefds,
755                     fd_set * __restrict libc_exceptfds, int libc_nfd)
756 {
757   int fd;
758   /* invalid max_fd is -1 */
759   int max_fd = -1;
760   int nfd2 = 0;
761
762
763   /* FD_BIT_OR
764    *
765    * dest |= src at current bit index
766    * update MAX and NFD of dest fd set
767    *
768    *
769    * FS source fd set
770    * FD dest fd set
771    * BI bit index
772    * MAX current max_fd of dest fd sets
773    * NFD current nfd of dest fd sets
774    * N  nfds of source fd set
775    */
776 #define FD_BIT_OR(FD,FS,BI,          \
777                   MAX,NFD)           \
778   if ((FS) && (FD) && FD_ISSET ((BI), (FS)))    \
779     {                                           \
780       FD_SET ((BI), (FD));                      \
781       if ((BI) > (MAX))                         \
782         {                                       \
783           (MAX) = (BI);                         \
784         }                                       \
785       ++(NFD);                                  \
786     }
787
788
789   /* FD_RWE_SET_OR */
790   /*
791    * SR,SW,SE source RWE fd sets
792    * DR,DW,DE dest RWE fd sets
793    * BI bit index
794    * NFDS  nfds of source fd sets
795    * MAX current max_fd of dest fd sets
796    * NFD current nfd of dest fd sets
797    */
798 #define FD_RWE_SETS_OR(DR,DW,DE,      \
799                       SR,SW,SE,       \
800                       BI,NFDS,        \
801                       MAX,NFD)        \
802   do                                                      \
803     {                                                     \
804       for ((BI) = 0; (BI) < (NFDS); (BI)++)               \
805         {                                                 \
806           FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD));      \
807           FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD));      \
808           FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD));      \
809         }                                                 \
810       }                                                   \
811     while (0);
812
813
814   /* source(vcom) to dest(select) rwe fd sets */
815   FD_RWE_SETS_OR (readfds, writefds, exceptfds,
816                   vcom_readfds, vcom_writefds, vcom_exceptfds,
817                   fd, vcom_nfds, max_fd, nfd2);
818
819   /* source(libc) to dest(select) rwe fd sets */
820   FD_RWE_SETS_OR (readfds, writefds, exceptfds,
821                   libc_readfds, libc_writefds, libc_exceptfds,
822                   fd, libc_nfds, max_fd, nfd2);
823
824 #undef FD_RWE_SETS_OR
825 #undef FD_BIT_OR
826
827   if (nfds)
828     *nfds = max_fd != -1 ? max_fd + 1 : 0;
829   if (nfd)
830     *nfd = nfd2;
831 }
832
833 /*
834  * RETURN 1 if fds is NULL or empty. 0 otherwise
835  */
836 static inline int
837 fd_set_iszero (fd_set * __restrict fds)
838 {
839   int fd;
840
841   /* NULL fds */
842   if (!fds)
843     return 1;
844
845   for (fd = 0; fd < FD_SETSIZE; fd++)
846     {
847       if (FD_ISSET (fd, fds))
848         {
849           /* non-empty fds */
850           return 0;
851         }
852     }
853   /* empty fds */
854   return 1;
855 }
856
857
858 /*
859  * ################
860  * kernel time64.h
861  * ################
862  * */
863 typedef long int s64;
864 typedef unsigned long int u64;
865
866 typedef long long int __s64;
867 typedef unsigned long long int __u64;
868
869 typedef __s64 time64_t;
870 typedef __u64 timeu64_t;
871
872 /* Parameters used to convert the timespec values: */
873 #define MSEC_PER_SEC    1000L
874 #define USEC_PER_MSEC   1000L
875 #define NSEC_PER_USEC   1000L
876 #define NSEC_PER_MSEC   1000000L
877 #define USEC_PER_SEC    1000000L
878 #define NSEC_PER_SEC    1000000000L
879 #define FSEC_PER_SEC    1000000000000000LL
880
881
882 /*
883  * ################
884  * kernel time.h
885  * ################
886  * */
887
888
889 #define TIME_T_MAX      (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
890
891 static inline int
892 timespec_equal (const struct timespec *a, const struct timespec *b)
893 {
894   return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
895 }
896
897 /*
898  * lhs < rhs:  return <0
899  * lhs == rhs: return 0
900  * lhs > rhs:  return >0
901  */
902 static inline int
903 timespec_compare (const struct timespec *lhs, const struct timespec *rhs)
904 {
905   if (lhs->tv_sec < rhs->tv_sec)
906     return -1;
907   if (lhs->tv_sec > rhs->tv_sec)
908     return 1;
909   return lhs->tv_nsec - rhs->tv_nsec;
910 }
911
912 static inline int
913 timeval_compare (const struct timeval *lhs, const struct timeval *rhs)
914 {
915   if (lhs->tv_sec < rhs->tv_sec)
916     return -1;
917   if (lhs->tv_sec > rhs->tv_sec)
918     return 1;
919   return lhs->tv_usec - rhs->tv_usec;
920 }
921
922 extern void set_normalized_timespec (struct timespec *ts, time_t sec,
923                                      s64 nsec);
924
925
926 static inline struct timespec
927 timespec_add (struct timespec lhs, struct timespec rhs)
928 {
929   struct timespec ts_delta;
930   set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec,
931                            lhs.tv_nsec + rhs.tv_nsec);
932   return ts_delta;
933 }
934
935 /*
936  * sub = lhs - rhs, in normalized form
937  */
938 static inline struct timespec
939 timespec_sub (struct timespec lhs, struct timespec rhs)
940 {
941   struct timespec ts_delta;
942   set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec,
943                            lhs.tv_nsec - rhs.tv_nsec);
944   return ts_delta;
945 }
946
947 /*
948  * ################
949  * kernel time.c
950  * ################
951  * */
952
953
954 /**
955  * set_normalized_timespec - set timespec sec and nsec parts and normalize
956  *
957  * @ts:         pointer to timespec variable to be set
958  * @sec:        seconds to set
959  * @nsec:       nanoseconds to set
960  *
961  * Set seconds and nanoseconds field of a timespec variable and
962  * normalize to the timespec storage format
963  *
964  * Note: The tv_nsec part is always in the range of
965  *      0 <= tv_nsec < NSEC_PER_SEC
966  * For negative values only the tv_sec field is negative !
967  */
968 void
969 set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec)
970 {
971   while (nsec >= NSEC_PER_SEC)
972     {
973       /*
974        * The following asm() prevents the compiler from
975        * optimising this loop into a modulo operation. See
976        * also __iter_div_u64_rem() in include/linux/time.h
977        */
978     asm ("":"+rm" (nsec));
979       nsec -= NSEC_PER_SEC;
980       ++sec;
981     }
982   while (nsec < 0)
983     {
984     asm ("":"+rm" (nsec));
985       nsec += NSEC_PER_SEC;
986       --sec;
987     }
988   ts->tv_sec = sec;
989   ts->tv_nsec = nsec;
990 }
991
992 #define vcom_timerisvalid(tvp)        (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0))
993
994 /* Macros for converting between `struct timeval' and `struct timespec'.  */
995 #define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) {                             \
996         (ts)->tv_sec = (tv)->tv_sec;                                    \
997         (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
998 }
999 #define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) {                             \
1000         (tv)->tv_sec = (ts)->tv_sec;                                    \
1001         (tv)->tv_usec = (ts)->tv_nsec / 1000;                           \
1002 }
1003
1004 static inline int
1005 vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds,
1006                   fd_set * __restrict vcom_writefds,
1007                   fd_set * __restrict vcom_exceptfds,
1008                   struct timeval *__restrict timeout)
1009 {
1010   return vcom_socket_select (vcom_nfds, vcom_readfds,
1011                              vcom_writefds, vcom_exceptfds, timeout);
1012 }
1013
1014 int
1015 vcom_select (int __nfds, fd_set * __restrict __readfds,
1016              fd_set * __restrict __writefds,
1017              fd_set * __restrict __exceptfds,
1018              struct timeval *__restrict __timeout)
1019 {
1020   int rv;
1021   int rv2 = 0;
1022   pid_t pid = getpid ();
1023
1024   int timedout = 0;
1025   /* block indefinitely */
1026   int no_timeout = 0;
1027   int first_clock_gettime_failed = 0;
1028   /* timeout value in units of timespec */
1029   struct timespec timeout_ts;
1030   struct timespec start_time, now, end_time;
1031
1032   /* select sets attributes - after merge */
1033   int new_nfds = 0;
1034   int new_nfd = -1;
1035
1036   /* vcom */
1037   int vcom_nfds = 0;
1038   fd_set vcom_readfds;
1039   fd_set vcom_writefds;
1040   fd_set vcom_exceptfds;
1041   int vcom_nfd = -1;
1042
1043   /* libc */
1044   int libc_nfds = 0;
1045   fd_set libc_readfds;
1046   fd_set libc_writefds;
1047   fd_set libc_exceptfds;
1048   int libc_nfd = -1;
1049
1050   /* for polling */
1051   struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
1052
1053   /* validate __timeout */
1054   if (__timeout)
1055     {
1056       /* validate tv_sec */
1057       /* bogus */
1058       if (!vcom_timerisvalid (__timeout))
1059         {
1060           rv = -EINVAL;
1061           goto select_done;
1062         }
1063
1064       /* validate tv_usec */
1065       /* TBD: */
1066       /* init timeout_ts */
1067       VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts);
1068       set_normalized_timespec (&timeout_ts,
1069                                timeout_ts.tv_sec, timeout_ts.tv_nsec);
1070     }
1071
1072   rv = clock_gettime (CLOCK_MONOTONIC, &start_time);
1073   if (rv == -1)
1074     {
1075       rv = -errno;
1076       first_clock_gettime_failed = 1;
1077       goto select_done;
1078     }
1079
1080   /* init end_time */
1081   if (__timeout)
1082     {
1083       if (timerisset (__timeout))
1084         {
1085           end_time = timespec_add (start_time, timeout_ts);
1086         }
1087       else
1088         {
1089           /*
1090            * if both fields of the timeout structure are zero,
1091            * then select returns immediately
1092            * */
1093           end_time = start_time;
1094         }
1095     }
1096   else
1097     {
1098       /* block indefinitely */
1099       no_timeout = 1;
1100     }
1101
1102
1103
1104   if (vcom_init () != 0)
1105     {
1106       rv = -1;
1107       goto select_done;
1108     }
1109
1110   /* validate __nfds */
1111   if (__nfds < 0 || __nfds > FD_SETSIZE)
1112     {
1113       rv = -EINVAL;
1114       goto select_done;
1115     }
1116
1117
1118   /*
1119    * usleep(3) emulation
1120    * */
1121
1122   /* call libc_select() with a finite timeout and
1123    * no file descriptors or empty fd sets and
1124    * zero nfds */
1125   if (__nfds == 0 &&
1126       (!__readfds || fd_set_iszero (__readfds)) &&
1127       (!__writefds || fd_set_iszero (__writefds)) &&
1128       (!__exceptfds || fd_set_iszero (__exceptfds)))
1129     {
1130       if (__timeout)
1131         {
1132           rv = libc_select (__nfds,
1133                             __readfds, __writefds, __exceptfds, __timeout);
1134           if (rv == -1)
1135             rv = -errno;
1136         }
1137       else
1138         {
1139           /* TBD: block indefinitely or return -EINVAL */
1140           rv = -EINVAL;
1141         }
1142       goto select_done;
1143     }
1144
1145   /* init once before the polling loop */
1146
1147   /* zero vcom and libc fd sets */
1148   /*
1149    * S select fd set
1150    * V vcom fd set
1151    * L libc fd set
1152    */
1153 #define _(S,V,L)      \
1154   if ((S))            \
1155     {                 \
1156       FD_ZERO ((V));  \
1157       FD_ZERO ((L));  \
1158     }
1159
1160
1161   _(__readfds, &vcom_readfds, &libc_readfds);
1162   _(__writefds, &vcom_writefds, &libc_writefds);
1163   _(__exceptfds, &vcom_exceptfds, &libc_exceptfds);
1164 #undef _
1165   new_nfds = 0;
1166   new_nfd = -1;
1167
1168   vcom_nfds = 0;
1169   vcom_nfd = -1;
1170   libc_nfds = 0;
1171   libc_nfd = -1;
1172
1173   vcom_fd_set_split (
1174                       /* src, select sets */
1175                       __nfds, __readfds, __writefds, __exceptfds,
1176                       /* dest1, vcom sets */
1177                       __readfds || __writefds || __exceptfds ?
1178                       &vcom_nfds : NULL,
1179                       __readfds ? &vcom_readfds : NULL,
1180                       __writefds ? &vcom_writefds : NULL,
1181                       __exceptfds ? &vcom_exceptfds : NULL,
1182                       __readfds || __writefds || __exceptfds ?
1183                       &vcom_nfd : NULL,
1184                       /* dest2, libc sets */
1185                       __readfds || __writefds || __exceptfds ?
1186                       &libc_nfds : NULL,
1187                       __readfds ? &libc_readfds : NULL,
1188                       __writefds ? &libc_writefds : NULL,
1189                       __exceptfds ? &libc_exceptfds : NULL,
1190                       __readfds || __writefds || __exceptfds ?
1191                       &libc_nfd : NULL);
1192
1193   /*
1194    * polling loop
1195    * */
1196   do
1197     {
1198       new_nfd = -1;
1199       vcom_nfd = -1;
1200       libc_nfd = -1;
1201
1202       /*
1203        * if both fields of timeval structure are zero,
1204        * vcom_select_impl and libc_select returns immediately.
1205        * useful for polling and ensure fairness among
1206        * file descriptors watched.
1207        */
1208
1209       /* for polling */
1210       tv.tv_sec = 0;
1211       tv.tv_usec = 0;
1212
1213       /* select on vcom fds */
1214       if (vcom_nfds)
1215         {
1216           vcom_nfd = vcom_select_impl (vcom_nfds,
1217                                        __readfds ? &vcom_readfds : NULL,
1218                                        __writefds ? &vcom_writefds : NULL,
1219                                        __exceptfds ? &vcom_exceptfds : NULL,
1220                                        &tv);
1221           if (VCOM_DEBUG > 0)
1222             fprintf (stderr,
1223                      "[%d] select vcom: "
1224                      "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds);
1225
1226           if (vcom_nfd < 0)
1227             {
1228               rv = vcom_nfd;
1229               goto select_done;
1230             }
1231         }
1232       /* select on libc fds */
1233       if (libc_nfds)
1234         {
1235           libc_nfd = libc_select (libc_nfds,
1236                                   __readfds ? &libc_readfds : NULL,
1237                                   __writefds ? &libc_writefds : NULL,
1238                                   __exceptfds ? &libc_exceptfds : NULL, &tv);
1239           if (VCOM_DEBUG > 0)
1240             fprintf (stderr,
1241                      "[%d] select libc: "
1242                      "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds);
1243
1244           if (libc_nfd < 0)
1245             {
1246               /* tv becomes undefined */
1247               libc_nfd = errno;
1248               rv = libc_nfd;
1249               goto select_done;
1250             }
1251         }
1252
1253       /* check if any file descriptors changed status */
1254       if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0))
1255         {
1256           /* zero the sets before merge and exit */
1257
1258           /*
1259            * F fd set
1260            */
1261 #define _(F)                  \
1262           if ((F))            \
1263             {                 \
1264               FD_ZERO ((F));  \
1265             }
1266
1267
1268           _(__readfds);
1269           _(__writefds);
1270           _(__exceptfds);
1271 #undef _
1272           new_nfds = 0;
1273           new_nfd = -1;
1274
1275           /*
1276            * on exit, sets are modified in place to indicate which
1277            * file descriptors actually changed status
1278            * */
1279           vcom_fd_set_merge (
1280                               /* dest, select sets */
1281                               __readfds || __writefds || __exceptfds ?
1282                               &new_nfds : NULL,
1283                               __readfds,
1284                               __writefds,
1285                               __exceptfds,
1286                               __readfds || __writefds || __exceptfds ?
1287                               &new_nfd : NULL,
1288                               /* src1, vcom sets */
1289                               vcom_nfds,
1290                               __readfds ? &vcom_readfds : NULL,
1291                               __writefds ? &vcom_writefds : NULL,
1292                               __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd,
1293                               /* src2, libc sets */
1294                               libc_nfds,
1295                               __readfds ? &libc_readfds : NULL,
1296                               __writefds ? &libc_writefds : NULL,
1297                               __exceptfds ? &libc_exceptfds : NULL, libc_nfd);
1298           /*
1299            * return the number of file descriptors contained in the
1300            * three returned sets
1301            * */
1302           rv = 0;
1303           /*
1304            * for documentation
1305            *
1306            * if(vcom_nfd > 0)
1307            *   rv += vcom_nfd;
1308            * if(libc_nfd > 0)
1309            *   rv += libc_nfd;
1310            */
1311
1312           rv = new_nfd == -1 ? 0 : new_nfd;
1313           goto select_done;
1314         }
1315
1316       rv = clock_gettime (CLOCK_MONOTONIC, &now);
1317       if (rv == -1)
1318         {
1319           rv = -errno;
1320           goto select_done;
1321         }
1322     }
1323   while (no_timeout || timespec_compare (&now, &end_time) < 0);
1324
1325   /* timeout expired before anything interesting happened */
1326   timedout = 1;
1327   rv = 0;
1328
1329 select_done:
1330   if (VCOM_DEBUG > 0)
1331     fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1332   /*
1333    * modify timeout parameter to reflect the amount of time not slept
1334    * */
1335   if (__timeout)
1336     {
1337       if (vcom_timerisvalid (__timeout))
1338         {
1339           /* timeout expired */
1340           if (timedout)
1341             {
1342               timerclear (__timeout);
1343             }
1344           else if (!first_clock_gettime_failed)
1345             {
1346               rv2 = clock_gettime (CLOCK_MONOTONIC, &now);
1347               if (rv2 == -1)
1348                 {
1349                   rv = -errno;
1350                 }
1351               else
1352                 {
1353                   struct timespec ts_delta;
1354                   ts_delta = timespec_sub (end_time, now);
1355                   VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta);
1356                 }
1357             }
1358         }
1359     }
1360   if (VCOM_DEBUG > 0)
1361     fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds);
1362
1363   return rv;
1364 }
1365
1366 int
1367 vcom_select_internal (int __nfds, fd_set * __restrict __readfds,
1368                       fd_set * __restrict __writefds,
1369                       fd_set * __restrict __exceptfds,
1370                       struct timeval *__restrict __timeout)
1371 {
1372   int rv;
1373   int new_nfds = 0;
1374   int nfd = 0;
1375   pid_t pid = getpid ();
1376
1377   fd_set saved_readfds;
1378   fd_set saved_writefds;
1379   fd_set saved_exceptfds;
1380
1381   /* validate __nfds */
1382   if (__nfds < 0)
1383     {
1384       errno = EINVAL;
1385       return -1;
1386     }
1387
1388   /* validate __timeout */
1389   if (__timeout)
1390     {
1391       /* validate tv_sec */
1392       /* bogus */
1393       if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0)
1394         {
1395           errno = EINVAL;
1396           return -1;
1397         }
1398
1399       /* validate tv_usec */
1400       /* TBD: */
1401     }
1402
1403   /* init saved_x fds */
1404   if (__readfds)
1405     {
1406       saved_readfds = *__readfds;
1407       /*
1408          memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1409        */
1410     }
1411   else
1412     {
1413       FD_ZERO (&saved_readfds);
1414     }
1415
1416   if (__writefds)
1417     {
1418       saved_writefds = *__writefds;
1419       /*
1420          memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1421        */
1422
1423     }
1424   else
1425     {
1426       FD_ZERO (&saved_writefds);
1427     }
1428
1429   if (__exceptfds)
1430     {
1431       saved_exceptfds = *__exceptfds;
1432       /*
1433          memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1434        */
1435
1436     }
1437   else
1438     {
1439       FD_ZERO (&saved_exceptfds);
1440     }
1441
1442   /* clear vcom fds */
1443   nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1444
1445   /* set to an invalid value */
1446   rv = -2;
1447   /* have kernel fds */
1448   if (new_nfds)
1449     rv = libc_select (new_nfds, __readfds,
1450                       __writefds, __exceptfds, __timeout);
1451
1452   if (new_nfds && rv == -1)
1453     {
1454       /* on error, the file descriptor sets are unmodified */
1455       if (__readfds)
1456         *__readfds = saved_readfds;
1457       if (__writefds)
1458         *__writefds = saved_writefds;
1459       if (__exceptfds)
1460         *__exceptfds = saved_exceptfds;
1461       return rv;
1462     }
1463   else if ((new_nfds && rv != -1) || (rv == -2))
1464     {
1465       /* restore vcom fds */
1466       nfd = vcom_fd_set (__nfds,
1467                          &new_nfds,
1468                          __readfds,
1469                          __writefds,
1470                          __exceptfds,
1471                          &saved_readfds, &saved_writefds, &saved_exceptfds);
1472       rv = nfd;
1473     }
1474
1475   if (VCOM_DEBUG > 0)
1476     fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds);
1477   return rv;
1478 }
1479
1480 int
1481 select (int __nfds, fd_set * __restrict __readfds,
1482         fd_set * __restrict __writefds,
1483         fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout)
1484 {
1485   int rv = 0;
1486   pid_t pid = getpid ();
1487
1488   if (VCOM_DEBUG > 0)
1489     fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds);
1490   rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout);
1491   if (VCOM_DEBUG > 0)
1492     fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds);
1493   if (rv < 0)
1494     {
1495       errno = -rv;
1496       return -1;
1497     }
1498   return rv;
1499 }
1500
1501 #ifdef __USE_XOPEN2K
1502 /*
1503  * Same as above only that the TIMEOUT value is given with higher
1504  * resolution and a sigmask which is been set temporarily.  This
1505  * version should be used.
1506  *
1507  * This function is a cancellation point and therefore not marked
1508  * with __THROW.
1509  * */
1510 int
1511 vcom_pselect (int __nfds, fd_set * __restrict __readfds,
1512               fd_set * __restrict __writefds,
1513               fd_set * __restrict __exceptfds,
1514               const struct timespec *__restrict __timeout,
1515               const __sigset_t * __restrict __sigmask)
1516 {
1517   int fd;
1518   int vcom_nfds = 0;
1519
1520   for (fd = 0; fd < __nfds; fd++)
1521     {
1522       if (__readfds && FD_ISSET (fd, __readfds))
1523         {
1524           if (is_vcom_socket_fd (fd))
1525             {
1526               vcom_nfds++;
1527             }
1528         }
1529
1530       if (__writefds && FD_ISSET (fd, __writefds))
1531         {
1532           if (is_vcom_socket_fd (fd))
1533             {
1534               vcom_nfds++;
1535             }
1536         }
1537       if (__exceptfds && FD_ISSET (fd, __exceptfds))
1538         {
1539           if (is_vcom_socket_fd (fd))
1540             {
1541               FD_CLR (fd, __exceptfds);
1542             }
1543         }
1544     }
1545   return vcom_nfds;
1546 }
1547
1548 int
1549 pselect (int __nfds, fd_set * __restrict __readfds,
1550          fd_set * __restrict __writefds,
1551          fd_set * __restrict __exceptfds,
1552          const struct timespec *__restrict __timeout,
1553          const __sigset_t * __restrict __sigmask)
1554 {
1555   int rv;
1556   int new_nfds = 0;
1557   int nfd = 0;
1558   pid_t pid = getpid ();
1559
1560   fd_set saved_readfds;
1561   fd_set saved_writefds;
1562   fd_set saved_exceptfds;
1563
1564   /* validate __nfds */
1565   if (__nfds < 0)
1566     {
1567       errno = EINVAL;
1568       return -1;
1569     }
1570
1571   /* validate __timeout */
1572   if (__timeout)
1573     {
1574       /* validate tv_sec */
1575       /* bogus */
1576       if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0)
1577         {
1578           errno = EINVAL;
1579           return -1;
1580         }
1581
1582       /* validate tv_usec */
1583       /* TBD: */
1584     }
1585
1586   /* init saved fds */
1587   if (__readfds)
1588     {
1589       saved_readfds = *__readfds;
1590       /*
1591          memcpy (&saved_readfds, __readfds, sizeof (*__readfds));
1592        */
1593     }
1594   else
1595     {
1596       FD_ZERO (&saved_readfds);
1597     }
1598
1599   if (__writefds)
1600     {
1601       saved_writefds = *__writefds;
1602       /*
1603          memcpy (&saved_writefds, __writefds, sizeof (*__writefds));
1604        */
1605
1606     }
1607   else
1608     {
1609       FD_ZERO (&saved_writefds);
1610     }
1611
1612   if (__exceptfds)
1613     {
1614       saved_exceptfds = *__exceptfds;
1615       /*
1616          memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds));
1617        */
1618
1619     }
1620   else
1621     {
1622       FD_ZERO (&saved_exceptfds);
1623     }
1624
1625   /* clear vcom fds */
1626   nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds);
1627
1628   /* set to an invalid value */
1629   rv = -2;
1630   if (new_nfds)
1631     rv = libc_pselect (new_nfds,
1632                        __readfds,
1633                        __writefds, __exceptfds, __timeout, __sigmask);
1634
1635   if (new_nfds && rv == -1)
1636     {
1637       /* on error, the file descriptor sets are unmodified */
1638       if (__readfds)
1639         *__readfds = saved_readfds;
1640       if (__writefds)
1641         *__writefds = saved_writefds;
1642       if (__exceptfds)
1643         *__exceptfds = saved_exceptfds;
1644       return rv;
1645     }
1646   else if ((new_nfds && rv != -1) || (rv == -2))
1647     {
1648       /* restore vcom fds */
1649       nfd = vcom_fd_set (__nfds,
1650                          &new_nfds,
1651                          __readfds,
1652                          __writefds,
1653                          __exceptfds,
1654                          &saved_readfds, &saved_writefds, &saved_exceptfds);
1655       rv = nfd;
1656     }
1657
1658   if (VCOM_DEBUG > 0)
1659     fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds);
1660   return rv;
1661 }
1662 #endif
1663
1664 /*
1665  *
1666  * Socket specific glibc api
1667  *
1668  */
1669
1670 /* Create a new socket of type TYPE in domain DOMAIN, using
1671  * protocol PROTOCOL.  If PROTOCOL is zero, one is chosen
1672  * automatically. Returns a file descriptor for the new socket,
1673  * or -1 for errors.
1674  * RETURN:  a valid file descriptor for the new socket,
1675  * or -1 for errors.
1676  * */
1677
1678 int
1679 vcom_socket (int __domain, int __type, int __protocol)
1680 {
1681   if (vcom_init () != 0)
1682     {
1683       return -1;
1684     }
1685
1686   return vcom_socket_socket (__domain, __type, __protocol);
1687 }
1688
1689 int
1690 socket (int __domain, int __type, int __protocol)
1691 {
1692   int rv;
1693   pid_t pid = getpid ();
1694   pthread_t tid = pthread_self ();
1695
1696   /* handle domains implemented by vpp */
1697   switch (__domain)
1698     {
1699     case AF_INET:
1700     case AF_INET6:
1701       /* handle types implemented by vpp */
1702       switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1703         {
1704         case SOCK_STREAM:
1705         case SOCK_DGRAM:
1706           if (VCOM_DEBUG > 0)
1707             vcom_socket_main_show ();
1708           rv = vcom_socket (__domain, __type, __protocol);
1709           if (VCOM_DEBUG > 0)
1710             fprintf (stderr,
1711                      "[%d][%lu (0x%lx)] socket: "
1712                      "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1713                      pid, (unsigned long) tid, (unsigned long) tid,
1714                      rv, __domain, __type, __protocol);
1715           if (VCOM_DEBUG > 0)
1716             vcom_socket_main_show ();
1717           if (rv < 0)
1718             {
1719               errno = -rv;
1720               return -1;
1721             }
1722           return rv;
1723           break;
1724
1725         default:
1726           goto CALL_GLIBC_SOCKET_API;
1727           break;
1728         }
1729
1730       break;
1731
1732     default:
1733       goto CALL_GLIBC_SOCKET_API;
1734       break;
1735     }
1736
1737 CALL_GLIBC_SOCKET_API:
1738   return libc_socket (__domain, __type, __protocol);
1739 }
1740
1741 /*
1742  * Create two new sockets, of type TYPE in domain DOMAIN and using
1743  * protocol PROTOCOL, which are connected to each other, and put file
1744  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
1745  * one will be chosen automatically.
1746  * Returns 0 on success, -1 for errors.
1747  * */
1748 int
1749 vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2])
1750 {
1751   if (vcom_init () != 0)
1752     {
1753       return -1;
1754     }
1755
1756   return vcom_socket_socketpair (__domain, __type, __protocol, __fds);
1757 }
1758
1759 int
1760 socketpair (int __domain, int __type, int __protocol, int __fds[2])
1761 {
1762   int rv;
1763   pid_t pid = getpid ();
1764
1765   /* handle domains implemented by vpp */
1766   switch (__domain)
1767     {
1768     case AF_INET:
1769     case AF_INET6:
1770       /* handle types implemented by vpp */
1771       switch (__type)
1772         {
1773         case SOCK_STREAM:
1774         case SOCK_DGRAM:
1775           rv = vcom_socketpair (__domain, __type, __protocol, __fds);
1776           if (VCOM_DEBUG > 0)
1777             fprintf (stderr,
1778                      "[%d] socketpair: "
1779                      "'%04d'= D='%04d', T='%04d', P='%04d'\n",
1780                      pid, rv, __domain, __type, __protocol);
1781           if (rv < 0)
1782             {
1783               errno = -rv;
1784               return -1;
1785             }
1786           return 0;
1787           break;
1788
1789         default:
1790           goto CALL_GLIBC_SOCKET_API;
1791           break;
1792         }
1793
1794       break;
1795
1796     default:
1797       goto CALL_GLIBC_SOCKET_API;
1798       break;
1799     }
1800
1801 CALL_GLIBC_SOCKET_API:
1802   return libc_socketpair (__domain, __type, __protocol, __fds);
1803 }
1804
1805 /*
1806  * Give the socket FD the local address ADDR
1807  * (which is LEN bytes long).
1808  * */
1809 int
1810 vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1811 {
1812   int rv;
1813
1814   if (vcom_init () != 0)
1815     {
1816       return -1;
1817     }
1818
1819   /* validate __len */
1820   switch (__addr->sa_family)
1821     {
1822     case AF_INET:
1823       if (__len != sizeof (struct sockaddr_in))
1824         return -EINVAL;
1825       break;
1826     case AF_INET6:
1827       if (__len != sizeof (struct sockaddr_in6))
1828         return -EINVAL;
1829       break;
1830
1831     default:
1832       return -1;
1833       break;
1834     }
1835
1836   /* handle domains implemented by vpp */
1837   switch (__addr->sa_family)
1838     {
1839     case AF_INET:
1840     case AF_INET6:
1841       rv = vcom_socket_bind (__fd, __addr, __len);
1842       return rv;
1843       break;
1844
1845     default:
1846       return -1;
1847       break;
1848     }
1849
1850   return -1;
1851 }
1852
1853 int
1854 bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1855 {
1856   int rv;
1857   pid_t pid = getpid ();
1858
1859   if (is_vcom_socket_fd (__fd))
1860     {
1861
1862       rv = vcom_bind (__fd, __addr, __len);
1863       if (VCOM_DEBUG > 0)
1864         fprintf (stderr,
1865                  "[%d] bind: "
1866                  "'%04d'='%04d', '%p', '%04d'\n",
1867                  pid, rv, __fd, __addr, __len);
1868       if (rv != 0)
1869         {
1870           errno = -rv;
1871           return -1;
1872         }
1873       return 0;
1874     }
1875   return libc_bind (__fd, __addr, __len);
1876 }
1877
1878 /*
1879  * Put the local address of FD into *ADDR and its length in *LEN.
1880  * */
1881 int
1882 vcom_getsockname (int __fd, __SOCKADDR_ARG __addr,
1883                   socklen_t * __restrict __len)
1884 {
1885   if (vcom_init () != 0)
1886     {
1887       return -1;
1888     }
1889
1890   return vcom_socket_getsockname (__fd, __addr, __len);
1891 }
1892
1893 int
1894 getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
1895 {
1896   int rv;
1897   pid_t pid = getpid ();
1898
1899   if (is_vcom_socket_fd (__fd))
1900     {
1901       rv = vcom_getsockname (__fd, __addr, __len);
1902       if (VCOM_DEBUG > 0)
1903         fprintf (stderr,
1904                  "[%d] getsockname: "
1905                  "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
1906       if (rv != 0)
1907         {
1908           errno = -rv;
1909           return -1;
1910         }
1911       return 0;
1912     }
1913   return libc_getsockname (__fd, __addr, __len);
1914 }
1915
1916 /*
1917  * Open a connection on socket FD to peer at ADDR
1918  * (which LEN bytes long). For connectionless socket types, just set
1919  * the default address to send to and the only address from which to
1920  * accept transmissions. Return 0 on success, -1 for errors.
1921  * This function is a cancellation point and therefore not marked
1922  * with __THROW.
1923  * */
1924 int
1925 vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1926 {
1927   int rv = -1;
1928
1929   if (vcom_init () != 0)
1930     {
1931       return -1;
1932     }
1933
1934   /* validate __len */
1935   switch (__addr->sa_family)
1936     {
1937     case AF_INET:
1938       if (__len != INET_ADDRSTRLEN)
1939         return -1;
1940       break;
1941     case AF_INET6:
1942       if (__len != INET6_ADDRSTRLEN)
1943         return -1;
1944       break;
1945
1946     default:
1947       return -1;
1948       break;
1949     }
1950
1951   /* handle domains implemented by vpp */
1952   switch (__addr->sa_family)
1953     {
1954     case AF_INET:
1955     case AF_INET6:
1956       rv = vcom_socket_connect (__fd, __addr, __len);
1957       break;
1958
1959     default:
1960       return -1;
1961       break;
1962     }
1963
1964   return rv;
1965 }
1966
1967 int
1968 connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1969 {
1970   int rv;
1971   pid_t pid = getpid ();
1972   pthread_t tid = pthread_self ();
1973
1974   if (is_vcom_socket_fd (__fd))
1975     {
1976       rv = vcom_connect (__fd, __addr, __len);
1977       if (VCOM_DEBUG > 0)
1978         fprintf (stderr,
1979                  "[%d][%lu (0x%lx)] connect: "
1980                  "'%04d'='%04d', '%p', '%04d'\n",
1981                  pid, (unsigned long) tid, (unsigned long) tid,
1982                  rv, __fd, __addr, __len);
1983       if (rv != 0)
1984         {
1985           errno = -rv;
1986           return -1;
1987         }
1988       return 0;
1989     }
1990
1991   return libc_connect (__fd, __addr, __len);
1992 }
1993
1994 /*
1995  * Put the address of the peer connected to socket FD into *ADDR
1996  * (which is *LEN bytes long), and its actual length into *LEN.
1997  * */
1998 int
1999 vcom_getpeername (int __fd, __SOCKADDR_ARG __addr,
2000                   socklen_t * __restrict __len)
2001 {
2002   if (vcom_init () != 0)
2003     {
2004       return -1;
2005     }
2006
2007   return vcom_socket_getpeername (__fd, __addr, __len);
2008 }
2009
2010 int
2011 getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len)
2012 {
2013   int rv;
2014   pid_t pid = getpid ();
2015
2016   if (is_vcom_socket_fd (__fd))
2017     {
2018       rv = vcom_getpeername (__fd, __addr, __len);
2019       if (VCOM_DEBUG > 0)
2020         fprintf (stderr,
2021                  "[%d] getpeername: "
2022                  "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len);
2023       if (rv != 0)
2024         {
2025           errno = -rv;
2026           return -1;
2027         }
2028       return 0;
2029     }
2030   return libc_getpeername (__fd, __addr, __len);
2031 }
2032
2033 /*
2034  * Send N bytes of BUF to socket FD.  Returns the number sent or -1.
2035  * This function is a cancellation point and therefore not marked
2036  * with __THROW.
2037  * */
2038 ssize_t
2039 vcom_send (int __fd, const void *__buf, size_t __n, int __flags)
2040 {
2041
2042   if (vcom_init () != 0)
2043     {
2044       return -1;
2045     }
2046
2047   return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags);
2048 }
2049
2050 ssize_t
2051 send (int __fd, const void *__buf, size_t __n, int __flags)
2052 {
2053   ssize_t size;
2054   pid_t pid = getpid ();
2055
2056   if (is_vcom_socket_fd (__fd))
2057     {
2058       size = vcom_send (__fd, __buf, __n, __flags);
2059       if (VCOM_DEBUG > 0)
2060         fprintf (stderr,
2061                  "[%d] send: "
2062                  "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2063                  pid, (int) size, __fd, __buf, (int) __n, __flags);
2064       if (size < 0)
2065         {
2066           errno = -size;
2067           return -1;
2068         }
2069       return size;
2070     }
2071   return libc_send (__fd, __buf, __n, __flags);
2072 }
2073
2074 /*
2075  * Read N bytes into BUF from socket FD.
2076  * Returns the number read or -1 for errors.
2077  * This function is a cancellation point and therefore not marked
2078  *  with __THROW.
2079  *  */
2080 ssize_t
2081 vcom_recv (int __fd, void *__buf, size_t __n, int __flags)
2082 {
2083   if (vcom_init () != 0)
2084     {
2085       return -1;
2086     }
2087
2088   return vcom_socket_recv (__fd, __buf, __n, __flags);
2089 }
2090
2091 ssize_t
2092 recv (int __fd, void *__buf, size_t __n, int __flags)
2093 {
2094   ssize_t size;
2095   pid_t pid = getpid ();
2096
2097   if (is_vcom_socket_fd (__fd))
2098     {
2099       size = vcom_recv (__fd, __buf, __n, __flags);
2100       if (VCOM_DEBUG > 0)
2101         fprintf (stderr,
2102                  "[%d] recv: "
2103                  "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2104                  pid, (int) size, __fd, __buf, (int) __n, __flags);
2105       if (size < 0)
2106         {
2107           errno = -size;
2108           return -1;
2109         }
2110       return size;
2111     }
2112   return libc_recv (__fd, __buf, __n, __flags);
2113 }
2114
2115 /*
2116  * Send N bytes of BUF on socket FD to peer at address ADDR (which is
2117  * ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.
2118  * This function is a cancellation point and therefore not marked
2119  * with __THROW.
2120  * */
2121 ssize_t
2122 vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags,
2123              __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2124 {
2125   if (vcom_init () != 0)
2126     {
2127       return -1;
2128     }
2129
2130   return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2131 }
2132
2133 ssize_t
2134 sendto (int __fd, const void *__buf, size_t __n, int __flags,
2135         __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len)
2136 {
2137   ssize_t size;
2138   pid_t pid = getpid ();
2139
2140   if (is_vcom_socket_fd (__fd))
2141     {
2142       size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2143       if (VCOM_DEBUG > 0)
2144         fprintf (stderr,
2145                  "[%d] sendto: "
2146                  "'%04d'='%04d', '%p', '%04d', '%04x', "
2147                  "'%p', '%04d'\n",
2148                  pid, (int) size, __fd, __buf, (int) __n, __flags,
2149                  __addr, __addr_len);
2150       if (size < 0)
2151         {
2152           errno = -size;
2153           return -1;
2154         }
2155       return size;
2156     }
2157   return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len);
2158 }
2159
2160 /*
2161  * Read N bytes into BUF through socket FD.
2162  * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the
2163  * address of the sender, and store the actual size of the address
2164  * in *ADDR_LEN.
2165  * Returns the number of bytes read or -1 for errors.
2166  * This function is a cancellation point and therefore not marked
2167  * with __THROW.
2168  * */
2169 ssize_t
2170 vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n,
2171                int __flags,
2172                __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2173 {
2174   if (vcom_init () != 0)
2175     {
2176       return -1;
2177     }
2178
2179   return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2180 }
2181
2182 ssize_t
2183 recvfrom (int __fd, void *__restrict __buf, size_t __n,
2184           int __flags,
2185           __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2186 {
2187   ssize_t size;
2188   pid_t pid = getpid ();
2189
2190   if (is_vcom_socket_fd (__fd))
2191     {
2192       size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2193       if (VCOM_DEBUG > 0)
2194         fprintf (stderr,
2195                  "[%d] recvfrom: "
2196                  "'%04d'='%04d', '%p', '%04d', '%04x', "
2197                  "'%p', '%p'\n",
2198                  pid, (int) size, __fd, __buf, (int) __n, __flags,
2199                  __addr, __addr_len);
2200       if (size < 0)
2201         {
2202           errno = -size;
2203           return -1;
2204         }
2205       return size;
2206     }
2207   return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len);
2208 }
2209
2210 /*
2211  * Send a message described MESSAGE on socket FD.
2212  * Returns the number of bytes sent, or -1 for errors.
2213  * This function is a cancellation point and therefore not marked
2214  * with __THROW.
2215  * */
2216 ssize_t
2217 vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags)
2218 {
2219   if (vcom_init () != 0)
2220     {
2221       return -1;
2222     }
2223
2224   return vcom_socket_sendmsg (__fd, __message, __flags);
2225 }
2226
2227 ssize_t
2228 sendmsg (int __fd, const struct msghdr * __message, int __flags)
2229 {
2230   ssize_t size;
2231   pid_t pid = getpid ();
2232
2233   if (is_vcom_socket_fd (__fd))
2234     {
2235       size = vcom_sendmsg (__fd, __message, __flags);
2236       if (VCOM_DEBUG > 0)
2237         fprintf (stderr,
2238                  "[%d] sendmsg: "
2239                  "'%04d'='%04d', '%p', '%04x'\n",
2240                  pid, (int) size, __fd, __message, __flags);
2241       if (size < 0)
2242         {
2243           errno = -size;
2244           return -1;
2245         }
2246       return size;
2247     }
2248   return libc_sendmsg (__fd, __message, __flags);
2249 }
2250
2251 #ifdef __USE_GNU
2252 /*
2253  * Send a VLEN messages as described by VMESSAGES to socket FD.
2254  * Returns the number of datagrams successfully written
2255  * or -1 for errors.
2256  * This function is a cancellation point and therefore not marked
2257  * with __THROW.
2258  * */
2259 int
2260 vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages,
2261                unsigned int __vlen, int __flags)
2262 {
2263   if (vcom_init () != 0)
2264     {
2265       return -1;
2266     }
2267
2268   return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags);
2269 }
2270
2271 int
2272 sendmmsg (int __fd, struct mmsghdr *__vmessages,
2273           unsigned int __vlen, int __flags)
2274 {
2275   ssize_t size;
2276   pid_t pid = getpid ();
2277
2278   if (is_vcom_socket_fd (__fd))
2279     {
2280       size = vcom_sendmmsg (__fd, __message, __vlen, __flags);
2281       if (VCOM_DEBUG > 0)
2282         fprintf (stderr,
2283                  "[%d] sendmmsg: "
2284                  "'%04d'='%04d', '%p', '%04d', '%04x'\n",
2285                  pid, (int) size, __fd, __vmessages, __vlen, __flags);
2286       if (size < 0)
2287         {
2288           errno = -size;
2289           return -1;
2290         }
2291       return size;
2292     }
2293   return libc_sendmmsg (__fd, __message, __vlen, __flags);
2294 }
2295
2296 #endif
2297
2298 /*
2299  * Receive a message as described by MESSAGE from socket FD.
2300  * Returns the number of bytes read or -1 for errors.
2301  * This function is a cancellation point and therefore not marked
2302  * with __THROW.
2303  * */
2304 ssize_t
2305 vcom_recvmsg (int __fd, struct msghdr * __message, int __flags)
2306 {
2307   if (vcom_init () != 0)
2308     {
2309       return -1;
2310     }
2311
2312   return vcom_socket_recvmsg (__fd, __message, __flags);
2313 }
2314
2315 ssize_t
2316 recvmsg (int __fd, struct msghdr * __message, int __flags)
2317 {
2318   ssize_t size;
2319   pid_t pid = getpid ();
2320
2321   if (is_vcom_socket_fd (__fd))
2322     {
2323       size = vcom_recvmsg (__fd, __message, __flags);
2324       if (VCOM_DEBUG > 0)
2325         fprintf (stderr,
2326                  "[%d] recvmsg: "
2327                  "'%04d'='%04d', '%p', '%04x'\n",
2328                  pid, (int) size, __fd, __message, __flags);
2329       if (size < 0)
2330         {
2331           errno = -size;
2332           return -1;
2333         }
2334       return size;
2335     }
2336   return libc_recvmsg (__fd, __message, __flags);
2337 }
2338
2339 #ifdef __USE_GNU
2340 /*
2341  * Receive up to VLEN messages as described by VMESSAGES from socket FD.
2342  * Returns the number of messages received or -1 for errors.
2343  * This function is a cancellation point and therefore not marked
2344  * with __THROW.
2345  * */
2346 int
2347 vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages,
2348                unsigned int __vlen, int __flags, struct timespec *__tmo)
2349 {
2350   if (vcom_init () != 0)
2351     {
2352       return -1;
2353     }
2354
2355   return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2356 }
2357
2358 int
2359 recvmmsg (int __fd, struct mmsghdr *__vmessages,
2360           unsigned int __vlen, int __flags, struct timespec *__tmo)
2361 {
2362   ssize_t size;
2363   pid_t pid = getpid ();
2364
2365   if (is_vcom_socket_fd (__fd))
2366     {
2367       size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2368       if (VCOM_DEBUG > 0)
2369         fprintf (stderr,
2370                  "[%d] recvmmsg: "
2371                  "'%04d'='%04d', '%p', "
2372                  "'%04d', '%04x', '%p'\n",
2373                  pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo);
2374       if (size < 0)
2375         {
2376           errno = -size;
2377           return -1;
2378         }
2379       return size;
2380     }
2381   return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo);
2382 }
2383
2384 #endif
2385
2386 /*
2387  * Put the current value for socket FD's option OPTNAME
2388  * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long),
2389  * and set *OPTLEN to the value's actual length.
2390  * Returns 0 on success, -1 for errors.
2391  * */
2392 int
2393 vcom_getsockopt (int __fd, int __level, int __optname,
2394                  void *__restrict __optval, socklen_t * __restrict __optlen)
2395 {
2396   if (vcom_init () != 0)
2397     {
2398       return -1;
2399     }
2400
2401   return vcom_socket_getsockopt (__fd, __level, __optname,
2402                                  __optval, __optlen);
2403 }
2404
2405 int
2406 getsockopt (int __fd, int __level, int __optname,
2407             void *__restrict __optval, socklen_t * __restrict __optlen)
2408 {
2409   int rv;
2410   pid_t pid = getpid ();
2411
2412   if (is_vcom_socket_fd (__fd))
2413     {
2414       rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen);
2415       if (VCOM_DEBUG > 0)
2416         fprintf (stderr,
2417                  "[%d] getsockopt: "
2418                  "'%04d'='%04d', '%04d', '%04d', "
2419                  "'%p', '%p'\n",
2420                  pid, rv, __fd, __level, __optname, __optval, __optlen);
2421       if (rv != 0)
2422         {
2423           errno = -rv;
2424           return -1;
2425         }
2426       return 0;
2427     }
2428   return libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
2429 }
2430
2431 /*
2432  * Set socket FD's option OPTNAME at protocol level LEVEL
2433  * to *OPTVAL (which is OPTLEN bytes long).
2434  * Returns 0 on success, -1 for errors.
2435  * */
2436 int
2437 vcom_setsockopt (int __fd, int __level, int __optname,
2438                  const void *__optval, socklen_t __optlen)
2439 {
2440   if (vcom_init () != 0)
2441     {
2442       return -1;
2443     }
2444
2445   return vcom_socket_setsockopt (__fd, __level, __optname,
2446                                  __optval, __optlen);
2447 }
2448
2449 int
2450 setsockopt (int __fd, int __level, int __optname,
2451             const void *__optval, socklen_t __optlen)
2452 {
2453   int rv;
2454   pid_t pid = getpid ();
2455
2456   if (is_vcom_socket_fd (__fd))
2457     {
2458       rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen);
2459       if (VCOM_DEBUG > 0)
2460         fprintf (stderr,
2461                  "[%d] setsockopt: "
2462                  "'%04d'='%04d', '%04d', '%04d', "
2463                  "'%p', '%04d'\n",
2464                  pid, rv, __fd, __level, __optname, __optval, __optlen);
2465       if (rv != 0)
2466         {
2467           errno = -rv;
2468           return -1;
2469         }
2470       return 0;
2471     }
2472   return libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2473 }
2474
2475 /*
2476  * Prepare to accept connections on socket FD.
2477  * N connection requests will be queued before further
2478  * requests are refused.
2479  * Returns 0 on success, -1 for errors.
2480  * */
2481 int
2482 vcom_listen (int __fd, int __n)
2483 {
2484   if (vcom_init () != 0)
2485     {
2486       return -1;
2487     }
2488
2489   return vcom_socket_listen (__fd, __n);
2490 }
2491
2492 int
2493 listen (int __fd, int __n)
2494 {
2495   int rv;
2496   pid_t pid = getpid ();
2497
2498   if (is_vcom_socket_fd (__fd))
2499     {
2500       rv = vcom_listen (__fd, __n);
2501       if (VCOM_DEBUG > 0)
2502         fprintf (stderr,
2503                  "[%d] listen: "
2504                  "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n);
2505       if (rv != 0)
2506         {
2507           errno = -rv;
2508           return -1;
2509         }
2510       return 0;
2511     }
2512   return libc_listen (__fd, __n);
2513 }
2514
2515 /*
2516  * Await a connection on socket FD.
2517  * When a connection arrives, open a new socket to communicate
2518  * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address
2519  * of the connecting peer and *ADDR_LEN to the address's actual
2520  * length, and return the new socket's descriptor, or -1 for errors.
2521  * This function is a cancellation point and therefore not marked
2522  * with __THROW.
2523  * */
2524 int
2525 vcom_accept (int __fd, __SOCKADDR_ARG __addr,
2526              socklen_t * __restrict __addr_len)
2527 {
2528
2529   if (vcom_init () != 0)
2530     {
2531       return -1;
2532     }
2533   return vcom_socket_accept (__fd, __addr, __addr_len);
2534 }
2535
2536 int
2537 accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len)
2538 {
2539   int rv = -1;
2540   pid_t pid = getpid ();
2541   pthread_t tid = pthread_self ();
2542
2543   if (is_vcom_socket_fd (__fd))
2544     {
2545       if (VCOM_DEBUG > 0)
2546         vcom_socket_main_show ();
2547       if (VCOM_DEBUG > 0)
2548         fprintf (stderr,
2549                  "[%d][%lu (0x%lx)] accept1: "
2550                  "'%04d'='%04d', '%p', '%p'\n",
2551                  pid, (unsigned long) tid, (unsigned long) tid,
2552                  rv, __fd, __addr, __addr_len);
2553       rv = vcom_accept (__fd, __addr, __addr_len);
2554       if (VCOM_DEBUG > 0)
2555         fprintf (stderr,
2556                  "[%d][%lu (0x%lx)] accept2: "
2557                  "'%04d'='%04d', '%p', '%p'\n",
2558                  pid, (unsigned long) tid, (unsigned long) tid,
2559                  rv, __fd, __addr, __addr_len);
2560       if (VCOM_DEBUG > 0)
2561         vcom_socket_main_show ();
2562       if (rv < 0)
2563         {
2564           errno = -rv;
2565           return -1;
2566         }
2567       return rv;
2568     }
2569   return libc_accept (__fd, __addr, __addr_len);
2570 }
2571
2572 #ifdef __USE_GNU
2573 /*
2574  * Similar to 'accept' but takes an additional parameter to specify
2575  * flags.
2576  * This function is a cancellation point and therefore not marked
2577  * with __THROW.
2578  * */
2579 int
2580 vcom_accept4 (int __fd, __SOCKADDR_ARG __addr,
2581               socklen_t * __restrict __addr_len, int __flags)
2582 {
2583
2584   if (vcom_init () != 0)
2585     {
2586       return -1;
2587     }
2588
2589   return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags);
2590 }
2591
2592 int
2593 accept4 (int __fd, __SOCKADDR_ARG __addr,
2594          socklen_t * __restrict __addr_len, int __flags)
2595 {
2596   int rv;
2597   pid_t pid = getpid ();
2598
2599   if (is_vcom_socket_fd (__fd))
2600     {
2601       if (VCOM_DEBUG > 0)
2602         vcom_socket_main_show ();
2603       rv = vcom_accept4 (__fd, __addr, __addr_len, __flags);
2604       if (VCOM_DEBUG > 0)
2605         fprintf (stderr,
2606                  "[%d] accept4: "
2607                  "'%04d'='%04d', '%p', '%p', '%04x'\n",
2608                  pid, rv, __fd, __addr, __addr_len, __flags);
2609       if (VCOM_DEBUG > 0)
2610         vcom_socket_main_show ();
2611       if (rv < 0)
2612         {
2613           errno = -rv;
2614           return -1;
2615         }
2616       return rv;
2617     }
2618   return libc_accept4 (__fd, __addr, __addr_len, __flags);
2619 }
2620
2621 #endif
2622
2623 /*
2624  * Shut down all or part of the connection open on socket FD.
2625  * HOW determines what to shut down:
2626  *   SHUT_RD   = No more receptions;
2627  *   SHUT_WR   = No more transmissions;
2628  *   SHUT_RDWR = No more receptions or transmissions.
2629  * Returns 0 on success, -1 for errors.
2630  * */
2631 int
2632 vcom_shutdown (int __fd, int __how)
2633 {
2634   if (vcom_init () != 0)
2635     {
2636       return -1;
2637     }
2638   return vcom_socket_shutdown (__fd, __how);
2639 }
2640
2641 int
2642 shutdown (int __fd, int __how)
2643 {
2644   int rv;
2645   pid_t pid = getpid ();
2646
2647   if (is_vcom_socket_fd (__fd))
2648     {
2649       rv = vcom_shutdown (__fd, __how);
2650       if (VCOM_DEBUG > 0)
2651         fprintf (stderr,
2652                  "[%d] shutdown: "
2653                  "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how);
2654       if (rv != 0)
2655         {
2656           errno = -rv;
2657           return -1;
2658         }
2659       return 0;
2660     }
2661   return libc_shutdown (__fd, __how);
2662 }
2663
2664 int
2665 vcom_epoll_create (int __size)
2666 {
2667
2668   if (vcom_init () != 0)
2669     {
2670       return -1;
2671     }
2672
2673   if (__size <= 0)
2674     {
2675       return -EINVAL;
2676     }
2677
2678   /* __size argument is ignored "thereafter" */
2679   return vcom_epoll_create1 (0);
2680 }
2681
2682 /*
2683  * __size argument is ignored, but must be greater than zero
2684  */
2685 int
2686 epoll_create (int __size)
2687 {
2688   int rv = 0;
2689   pid_t pid = getpid ();
2690
2691   rv = vcom_epoll_create (__size);
2692   if (VCOM_DEBUG > 0)
2693     fprintf (stderr,
2694              "[%d] epoll_create: " "'%04d'='%04d'\n", pid, rv, __size);
2695   if (rv < 0)
2696     {
2697       errno = -rv;
2698       return -1;
2699     }
2700   return rv;
2701 }
2702
2703 int
2704 vcom_epoll_create1 (int __flags)
2705 {
2706   if (vcom_init () != 0)
2707     {
2708       return -1;
2709     }
2710
2711   if (__flags < 0)
2712     {
2713       return -EINVAL;
2714     }
2715   if (__flags & ~EPOLL_CLOEXEC)
2716     {
2717       return -EINVAL;
2718     }
2719   /* __flags can be either zero or EPOLL_CLOEXEC */
2720   /* implementation */
2721   return vcom_socket_epoll_create1 (__flags);
2722 }
2723
2724 /*
2725  * __flags can be either zero or EPOLL_CLOEXEC
2726  * */
2727 int
2728 epoll_create1 (int __flags)
2729 {
2730   int rv = 0;
2731   pid_t pid = getpid ();
2732
2733   rv = vcom_epoll_create1 (__flags);
2734   if (VCOM_DEBUG > 0)
2735     fprintf (stderr,
2736              "[%d] epoll_create: " "'%04d'='%08x'\n", pid, rv, __flags);
2737   if (rv < 0)
2738     {
2739       errno = -rv;
2740       return -1;
2741     }
2742   return rv;
2743 }
2744
2745 static inline int
2746 ep_op_has_event (int op)
2747 {
2748   return op != EPOLL_CTL_DEL;
2749 }
2750
2751 int
2752 vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
2753 {
2754   if (vcom_init () != 0)
2755     {
2756       return -1;
2757     }
2758
2759   /*
2760    * the requested operation __op is not supported
2761    * by this interface */
2762   if (!((__op == EPOLL_CTL_ADD) ||
2763         (__op == EPOLL_CTL_MOD) || (__op == EPOLL_CTL_DEL)))
2764     {
2765       return -EINVAL;
2766     }
2767
2768   /* op is ADD or MOD but event parameter is NULL */
2769   if ((ep_op_has_event (__op) && !__event))
2770     {
2771       return -EFAULT;
2772     }
2773
2774   /* fd is same as epfd */
2775   /* do not permit adding an epoll file descriptor inside itself */
2776   if (__epfd == __fd)
2777     {
2778       return -EINVAL;
2779     }
2780
2781   /* implementation */
2782   return vcom_socket_epoll_ctl (__epfd, __op, __fd, __event);
2783 }
2784
2785 /*
2786  * implement the controller interface for epoll
2787  * that enables the insertion/removal/change of
2788  * file descriptors inside the interest set.
2789  */
2790 int
2791 epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
2792 {
2793   int rv;
2794   pid_t pid = getpid ();
2795
2796   if (is_vcom_epfd (__epfd))
2797     {
2798       /* TBD: currently limiting epoll to support only vcom fds */
2799       if (is_vcom_socket_fd (__fd))
2800         {
2801           rv = vcom_epoll_ctl (__epfd, __op, __fd, __event);
2802           if (VCOM_DEBUG > 0)
2803             fprintf (stderr,
2804                      "[%d] epoll_ctl: "
2805                      "'%04d'='%04d', '%04d', '%04d'\n",
2806                      pid, rv, __epfd, __op, __fd);
2807           if (rv != 0)
2808             {
2809               errno = -rv;
2810               return -1;
2811             }
2812           return 0;
2813         }
2814       else
2815         {
2816           /*
2817            * TBD: currently epoll does not support kernel fds
2818            * or epoll fds */
2819           errno = EBADF;
2820           return -1;
2821         }
2822     }
2823   else
2824     {
2825       /* epfd is not an epoll file descriptor */
2826       errno = EINVAL;
2827       return -1;
2828     }
2829   return 0;
2830 }
2831
2832 int
2833 vcom_epoll_wait (int __epfd, struct epoll_event *__events,
2834                  int __maxevents, int __timeout)
2835 {
2836   if (vcom_init () != 0)
2837     {
2838       return -1;
2839     }
2840
2841   return vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, NULL);
2842 }
2843
2844 int
2845 epoll_wait (int __epfd, struct epoll_event *__events,
2846             int __maxevents, int __timeout)
2847 {
2848   int rv;
2849   pid_t pid = getpid ();
2850
2851   if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
2852     {
2853       errno = EINVAL;
2854       return -1;
2855     }
2856
2857   if (is_vcom_epfd (__epfd))
2858     {
2859       rv = vcom_epoll_wait (__epfd, __events, __maxevents, __timeout);
2860       if (VCOM_DEBUG > 0)
2861         fprintf (stderr,
2862                  "[%d] epoll_wait: "
2863                  "'%04d'='%04d', '%p', "
2864                  "'%04d', '%04d'\n",
2865                  pid, rv, __epfd, __events, __maxevents, __timeout);
2866       if (rv < 0)
2867         {
2868           errno = -rv;
2869           return -1;
2870         }
2871       return rv;
2872     }
2873   else
2874     {
2875       errno = EINVAL;
2876       return -1;
2877     }
2878   return 0;
2879 }
2880
2881
2882 int
2883 vcom_epoll_pwait (int __epfd, struct epoll_event *__events,
2884                   int __maxevents, int __timeout, const __sigset_t * __ss)
2885 {
2886   if (vcom_init () != 0)
2887     {
2888       return -1;
2889     }
2890
2891   /* implementation */
2892   return vcom_socket_epoll_pwait (__epfd, __events,
2893                                   __maxevents, __timeout, __ss);
2894 }
2895
2896 int
2897 epoll_pwait (int __epfd, struct epoll_event *__events,
2898              int __maxevents, int __timeout, const __sigset_t * __ss)
2899 {
2900   int rv;
2901   pid_t pid = getpid ();
2902
2903   if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS)
2904     {
2905       errno = EINVAL;
2906       return -1;
2907     }
2908
2909   if (is_vcom_epfd (__epfd))
2910     {
2911       rv = vcom_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss);
2912       if (VCOM_DEBUG > 0)
2913         fprintf (stderr,
2914                  "[%d] epoll_pwait: "
2915                  "'%04d'='%04d', '%p', "
2916                  "'%04d', '%04d', "
2917                  "'%p'\n",
2918                  pid, rv, __epfd, __events, __maxevents, __timeout, __ss);
2919       if (rv < 0)
2920         {
2921           errno = -rv;
2922           return -1;
2923         }
2924       return rv;
2925     }
2926   else
2927     {
2928       errno = EINVAL;
2929       return -1;
2930     }
2931
2932   return 0;
2933 }
2934
2935 /* Poll the file descriptors described by the NFDS structures starting at
2936    FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
2937    an event to occur; if TIMEOUT is -1, block until an event occurs.
2938    Returns the number of file descriptors with events, zero if timed out,
2939    or -1 for errors.
2940
2941    This function is a cancellation point and therefore not marked with
2942    __THROW.  */
2943 int
2944 vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2945 {
2946   if (vcom_init () != 0)
2947     {
2948       return -1;
2949     }
2950
2951   return -EOPNOTSUPP;
2952 }
2953
2954 int
2955 poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
2956 {
2957   int rv = 0;
2958
2959   errno = EOPNOTSUPP;
2960   rv = -1;
2961   return rv;
2962 }
2963
2964 #ifdef __USE_GNU
2965 /* Like poll, but before waiting the threads signal mask is replaced
2966    with that specified in the fourth parameter.  For better usability,
2967    the timeout value is specified using a TIMESPEC object.
2968
2969    This function is a cancellation point and therefore not marked with
2970    __THROW.  */
2971 int
2972 vcom_ppoll (struct pollfd *__fds, nfds_t __nfds,
2973             const struct timespec *__timeout, const __sigset_t * __ss)
2974 {
2975   if (vcom_init () != 0)
2976     {
2977       return -1;
2978     }
2979
2980   return -EOPNOTSUPP;
2981 }
2982
2983 int
2984 ppoll (struct pollfd *__fds, nfds_t __nfds,
2985        const struct timespec *__timeout, const __sigset_t * __ss)
2986 {
2987   int rv = 0;
2988
2989   errno = EOPNOTSUPP;
2990   rv = -1;
2991   return rv;
2992 }
2993 #endif
2994
2995 void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
2996
2997 void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
2998
2999 void
3000 vcom_constructor (void)
3001 {
3002   pid_t pid = getpid ();
3003
3004   swrap_constructor ();
3005   if (vcom_init () != 0)
3006     {
3007       printf ("\n[%d] vcom_constructor...failed!\n", pid);
3008     }
3009   else
3010     {
3011       printf ("\n[%d] vcom_constructor...done!\n", pid);
3012     }
3013 }
3014
3015 /*
3016  * This function is called when the library is unloaded
3017  */
3018 void
3019 vcom_destructor (void)
3020 {
3021   pid_t pid = getpid ();
3022
3023   vcom_destroy ();
3024   swrap_destructor ();
3025   printf ("\n[%d] vcom_destructor...done!\n", pid);
3026 }
3027
3028
3029 /*
3030  * fd.io coding-style-patch-verification: ON
3031  *
3032  * Local Variables:
3033  * eval: (c-set-style "gnu")
3034  * End:
3035  */