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