OSDN Git Service

Use temporary variables for calls with multiple results.
[pf3gnuchains/gcc-fork.git] / libmudflap / mf-hooks2.c
1 /* Mudflap: narrow-pointer bounds-checking by tree rewriting.
2    Copyright (C) 2002, 2003, 2004, 2009, 2011 Free Software Foundation, Inc.
3    Contributed by Frank Ch. Eigler <fche@redhat.com>
4    and Graydon Hoare <graydon@redhat.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 <http://www.gnu.org/licenses/>.  */
26
27 #include "config.h"
28
29 #ifndef HAVE_SOCKLEN_T
30 #define socklen_t int
31 #endif
32
33 /* These attempt to coax various unix flavours to declare all our
34    needed tidbits in the system headers.  */
35 #if !defined(__FreeBSD__) && !defined(__APPLE__)
36 #define _POSIX_SOURCE
37 #endif /* Some BSDs break <sys/socket.h> if this is defined. */
38 #define _GNU_SOURCE
39 #define _XOPEN_SOURCE
40 #define _BSD_TYPES
41 #define __EXTENSIONS__
42 #define _ALL_SOURCE
43 #define _LARGE_FILE_API
44 #define _LARGEFILE64_SOURCE
45 #define _XOPEN_SOURCE_EXTENDED 1
46
47 #include <string.h>
48 #include <stdarg.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <sys/stat.h>
52 #include <sys/time.h>
53 #include <sys/types.h>
54 #include <unistd.h>
55 #include <assert.h>
56 #include <errno.h>
57 #include <limits.h>
58 #include <time.h>
59 #include <ctype.h>
60 #ifdef HAVE_DLFCN_H
61 #include <dlfcn.h>
62 #endif
63 #ifdef HAVE_DIRENT_H
64 #include <dirent.h>
65 #endif
66 #ifdef HAVE_SYS_SOCKET_H
67 #include <sys/socket.h>
68 #endif
69 #ifdef HAVE_NETDB_H
70 #include <netdb.h>
71 #endif
72 #ifdef HAVE_SYS_WAIT_H
73 #include <sys/wait.h>
74 #endif
75 #ifdef HAVE_SYS_IPC_H
76 #include <sys/ipc.h>
77 #endif
78 #ifdef HAVE_SYS_SEM_H
79 #include <sys/sem.h>
80 #endif
81 #ifdef HAVE_SYS_SHM_H
82 #include <sys/shm.h>
83 #endif
84 #ifdef HAVE_PWD_H
85 #include <pwd.h>
86 #endif
87 #ifdef HAVE_GRP_H
88 #include <grp.h>
89 #endif
90 #ifdef HAVE_MNTENT_H
91 #include <mntent.h>
92 #endif
93 #ifdef HAVE_SYS_MNTTAB_H
94 #include <sys/mnttab.h>
95 #endif
96 #ifdef HAVE_SYS_SOCKET_H
97 #include <sys/socket.h>
98 #endif
99 #ifdef HAVE_NETINET_IN_H
100 #include <netinet/in.h>
101 #endif
102 #ifdef HAVE_ARPA_INET_H
103 #include <arpa/inet.h>
104 #endif
105
106 #include "mf-runtime.h"
107 #include "mf-impl.h"
108
109 #ifdef _MUDFLAP
110 #error "Do not compile this file with -fmudflap!"
111 #endif
112
113
114 /* A bunch of independent stdlib/unistd hook functions, all
115    intercepted by mf-runtime.h macros.  */
116
117 #ifndef HAVE_STRNLEN
118 static inline size_t (strnlen) (const char* str, size_t n)
119 {
120   const char *s;
121
122   for (s = str; n && *s; ++s, --n)
123     ;
124   return (s - str);
125 }
126 #endif
127
128
129 /* str*,mem*,b* */
130
131 WRAPPER2(void *, memcpy, void *dest, const void *src, size_t n)
132 {
133   TRACE ("%s\n", __PRETTY_FUNCTION__);
134   MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "memcpy source");
135   MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "memcpy dest");
136   return memcpy (dest, src, n);
137 }
138
139
140 WRAPPER2(void *, memmove, void *dest, const void *src, size_t n)
141 {
142   TRACE ("%s\n", __PRETTY_FUNCTION__);
143   MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "memmove src");
144   MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "memmove dest");
145   return memmove (dest, src, n);
146 }
147
148
149 WRAPPER2(void *, memset, void *s, int c, size_t n)
150 {
151   TRACE ("%s\n", __PRETTY_FUNCTION__);
152   MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "memset dest");
153   return memset (s, c, n);
154 }
155
156
157 WRAPPER2(int, memcmp, const void *s1, const void *s2, size_t n)
158 {
159   TRACE ("%s\n", __PRETTY_FUNCTION__);
160   MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "memcmp 1st arg");
161   MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "memcmp 2nd arg");
162   return memcmp (s1, s2, n);
163 }
164
165
166 WRAPPER2(void *, memchr, const void *s, int c, size_t n)
167 {
168   TRACE ("%s\n", __PRETTY_FUNCTION__);
169   MF_VALIDATE_EXTENT(s, n, __MF_CHECK_READ, "memchr region");
170   return memchr (s, c, n);
171 }
172
173
174 #ifdef HAVE_MEMRCHR
175 WRAPPER2(void *, memrchr, const void *s, int c, size_t n)
176 {
177   TRACE ("%s\n", __PRETTY_FUNCTION__);
178   MF_VALIDATE_EXTENT(s, n, __MF_CHECK_READ, "memrchr region");
179   return memrchr (s, c, n);
180 }
181 #endif
182
183
184 WRAPPER2(char *, strcpy, char *dest, const char *src)
185 {
186   /* nb: just because strlen(src) == n doesn't mean (src + n) or (src + n +
187      1) are valid pointers. the allocated object might have size < n.
188      check anyways. */
189
190   size_t n = strlen (src);
191   TRACE ("%s\n", __PRETTY_FUNCTION__);
192   MF_VALIDATE_EXTENT(src, CLAMPADD(n, 1), __MF_CHECK_READ, "strcpy src");
193   MF_VALIDATE_EXTENT(dest, CLAMPADD(n, 1), __MF_CHECK_WRITE, "strcpy dest");
194   return strcpy (dest, src);
195 }
196
197
198 #ifdef HAVE_STRNCPY
199 WRAPPER2(char *, strncpy, char *dest, const char *src, size_t n)
200 {
201   size_t len = strnlen (src, n);
202   TRACE ("%s\n", __PRETTY_FUNCTION__);
203   MF_VALIDATE_EXTENT(src, len, __MF_CHECK_READ, "strncpy src");
204   MF_VALIDATE_EXTENT(dest, len, __MF_CHECK_WRITE, "strncpy dest"); /* nb: strNcpy */
205   return strncpy (dest, src, n);
206 }
207 #endif
208
209
210 WRAPPER2(char *, strcat, char *dest, const char *src)
211 {
212   size_t dest_sz;
213   size_t src_sz;
214   TRACE ("%s\n", __PRETTY_FUNCTION__);
215   dest_sz = strlen (dest);
216   src_sz = strlen (src);
217   MF_VALIDATE_EXTENT(src, CLAMPADD(src_sz, 1), __MF_CHECK_READ, "strcat src");
218   MF_VALIDATE_EXTENT(dest, CLAMPADD(dest_sz, CLAMPADD(src_sz, 1)),
219                      __MF_CHECK_WRITE, "strcat dest");
220   return strcat (dest, src);
221 }
222
223
224 WRAPPER2(char *, strncat, char *dest, const char *src, size_t n)
225 {
226
227   /* nb: validating the extents (s,n) might be a mistake for two reasons.
228
229   (1) the string s might be shorter than n chars, and n is just a
230   poor choice by the programmer. this is not a "true" error in the
231   sense that the call to strncat would still be ok.
232
233   (2) we could try to compensate for case (1) by calling strlen(s) and
234   using that as a bound for the extent to verify, but strlen might fall off
235   the end of a non-terminated string, leading to a false positive.
236
237   so we will call strnlen(s,n) and use that as a bound.
238
239   if strnlen returns a length beyond the end of the registered extent
240   associated with s, there is an error: the programmer's estimate for n is
241   too large _AND_ the string s is unterminated, in which case they'd be
242   about to touch memory they don't own while calling strncat.
243
244   this same logic applies to further uses of strnlen later down in this
245   file. */
246
247   size_t src_sz;
248   size_t dest_sz;
249   TRACE ("%s\n", __PRETTY_FUNCTION__);
250   src_sz = strnlen (src, n);
251   dest_sz = strnlen (dest, n);
252   MF_VALIDATE_EXTENT(src, src_sz, __MF_CHECK_READ, "strncat src");
253   MF_VALIDATE_EXTENT(dest, (CLAMPADD(dest_sz, CLAMPADD(src_sz, 1))),
254                      __MF_CHECK_WRITE, "strncat dest");
255   return strncat (dest, src, n);
256 }
257
258
259 WRAPPER2(int, strcmp, const char *s1, const char *s2)
260 {
261   size_t s1_sz;
262   size_t s2_sz;
263   TRACE ("%s\n", __PRETTY_FUNCTION__);
264   s1_sz = strlen (s1);
265   s2_sz = strlen (s2);
266   MF_VALIDATE_EXTENT(s1, CLAMPADD(s1_sz, 1), __MF_CHECK_READ, "strcmp 1st arg");
267   MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), __MF_CHECK_WRITE, "strcmp 2nd arg");
268   return strcmp (s1, s2);
269 }
270
271
272 WRAPPER2(int, strcasecmp, const char *s1, const char *s2)
273 {
274   size_t s1_sz;
275   size_t s2_sz;
276   TRACE ("%s\n", __PRETTY_FUNCTION__);
277   s1_sz = strlen (s1);
278   s2_sz = strlen (s2);
279   MF_VALIDATE_EXTENT(s1, CLAMPADD(s1_sz, 1), __MF_CHECK_READ, "strcasecmp 1st arg");
280   MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), __MF_CHECK_READ, "strcasecmp 2nd arg");
281   return strcasecmp (s1, s2);
282 }
283
284
285 WRAPPER2(int, strncmp, const char *s1, const char *s2, size_t n)
286 {
287   size_t s1_sz;
288   size_t s2_sz;
289   TRACE ("%s\n", __PRETTY_FUNCTION__);
290   s1_sz = strnlen (s1, n);
291   s2_sz = strnlen (s2, n);
292   MF_VALIDATE_EXTENT(s1, s1_sz, __MF_CHECK_READ, "strncmp 1st arg");
293   MF_VALIDATE_EXTENT(s2, s2_sz, __MF_CHECK_READ, "strncmp 2nd arg");
294   return strncmp (s1, s2, n);
295 }
296
297
298 WRAPPER2(int, strncasecmp, const char *s1, const char *s2, size_t n)
299 {
300   size_t s1_sz;
301   size_t s2_sz;
302   TRACE ("%s\n", __PRETTY_FUNCTION__);
303   s1_sz = strnlen (s1, n);
304   s2_sz = strnlen (s2, n);
305   MF_VALIDATE_EXTENT(s1, s1_sz, __MF_CHECK_READ, "strncasecmp 1st arg");
306   MF_VALIDATE_EXTENT(s2, s2_sz, __MF_CHECK_READ, "strncasecmp 2nd arg");
307   return strncasecmp (s1, s2, n);
308 }
309
310
311 WRAPPER2(char *, strdup, const char *s)
312 {
313   DECLARE(void *, malloc, size_t sz);
314   char *result;
315   size_t n = strlen (s);
316   TRACE ("%s\n", __PRETTY_FUNCTION__);
317   MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strdup region");
318   result = (char *)CALL_REAL(malloc,
319                              CLAMPADD(CLAMPADD(n,1),
320                                       CLAMPADD(__mf_opts.crumple_zone,
321                                                __mf_opts.crumple_zone)));
322
323   if (UNLIKELY(! result)) return result;
324
325   result += __mf_opts.crumple_zone;
326   memcpy (result, s, n);
327   result[n] = '\0';
328
329   __mf_register (result, CLAMPADD(n,1), __MF_TYPE_HEAP_I, "strdup region");
330   return result;
331 }
332
333
334 WRAPPER2(char *, strndup, const char *s, size_t n)
335 {
336   DECLARE(void *, malloc, size_t sz);
337   char *result;
338   size_t sz = strnlen (s, n);
339   TRACE ("%s\n", __PRETTY_FUNCTION__);
340   MF_VALIDATE_EXTENT(s, sz, __MF_CHECK_READ, "strndup region"); /* nb: strNdup */
341
342   /* note: strndup still adds a \0, even with the N limit! */
343   result = (char *)CALL_REAL(malloc,
344                              CLAMPADD(CLAMPADD(n,1),
345                                       CLAMPADD(__mf_opts.crumple_zone,
346                                                __mf_opts.crumple_zone)));
347
348   if (UNLIKELY(! result)) return result;
349
350   result += __mf_opts.crumple_zone;
351   memcpy (result, s, n);
352   result[n] = '\0';
353
354   __mf_register (result, CLAMPADD(n,1), __MF_TYPE_HEAP_I, "strndup region");
355   return result;
356 }
357
358
359 WRAPPER2(char *, strchr, const char *s, int c)
360 {
361   size_t n;
362   TRACE ("%s\n", __PRETTY_FUNCTION__);
363   n = strlen (s);
364   MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strchr region");
365   return strchr (s, c);
366 }
367
368
369 WRAPPER2(char *, strrchr, const char *s, int c)
370 {
371   size_t n;
372   TRACE ("%s\n", __PRETTY_FUNCTION__);
373   n = strlen (s);
374   MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strrchr region");
375   return strrchr (s, c);
376 }
377
378
379 WRAPPER2(char *, strstr, const char *haystack, const char *needle)
380 {
381   size_t haystack_sz;
382   size_t needle_sz;
383   TRACE ("%s\n", __PRETTY_FUNCTION__);
384   haystack_sz = strlen (haystack);
385   needle_sz = strlen (needle);
386   MF_VALIDATE_EXTENT(haystack, CLAMPADD(haystack_sz, 1), __MF_CHECK_READ, "strstr haystack");
387   MF_VALIDATE_EXTENT(needle, CLAMPADD(needle_sz, 1), __MF_CHECK_READ, "strstr needle");
388   return strstr (haystack, needle);
389 }
390
391
392 #ifdef HAVE_MEMMEM
393 WRAPPER2(void *, memmem,
394         const void *haystack, size_t haystacklen,
395         const void *needle, size_t needlelen)
396 {
397   TRACE ("%s\n", __PRETTY_FUNCTION__);
398   MF_VALIDATE_EXTENT(haystack, haystacklen, __MF_CHECK_READ, "memmem haystack");
399   MF_VALIDATE_EXTENT(needle, needlelen, __MF_CHECK_READ, "memmem needle");
400   return memmem (haystack, haystacklen, needle, needlelen);
401 }
402 #endif
403
404
405 WRAPPER2(size_t, strlen, const char *s)
406 {
407   size_t result = strlen (s);
408   TRACE ("%s\n", __PRETTY_FUNCTION__);
409   MF_VALIDATE_EXTENT(s, CLAMPADD(result, 1), __MF_CHECK_READ, "strlen region");
410   return result;
411 }
412
413
414 WRAPPER2(size_t, strnlen, const char *s, size_t n)
415 {
416   size_t result = strnlen (s, n);
417   TRACE ("%s\n", __PRETTY_FUNCTION__);
418   MF_VALIDATE_EXTENT(s, result, __MF_CHECK_READ, "strnlen region");
419   return result;
420 }
421
422
423 WRAPPER2(void, bzero, void *s, size_t n)
424 {
425   TRACE ("%s\n", __PRETTY_FUNCTION__);
426   MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region");
427   bzero (s, n);
428 }
429
430
431 #undef bcopy
432 WRAPPER2(void, bcopy, const void *src, void *dest, size_t n)
433 {
434   TRACE ("%s\n", __PRETTY_FUNCTION__);
435   MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src");
436   MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest");
437   bcopy (src, dest, n);
438 }
439
440
441 #undef bcmp
442 WRAPPER2(int, bcmp, const void *s1, const void *s2, size_t n)
443 {
444   TRACE ("%s\n", __PRETTY_FUNCTION__);
445   MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg");
446   MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg");
447   return bcmp (s1, s2, n);
448 }
449
450
451 WRAPPER2(char *, index, const char *s, int c)
452 {
453   size_t n = strlen (s);
454   TRACE ("%s\n", __PRETTY_FUNCTION__);
455   MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region");
456   return index (s, c);
457 }
458
459
460 WRAPPER2(char *, rindex, const char *s, int c)
461 {
462   size_t n = strlen (s);
463   TRACE ("%s\n", __PRETTY_FUNCTION__);
464   MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region");
465   return rindex (s, c);
466 }
467
468 /* XXX:  stpcpy, memccpy */
469
470 /* XXX: *printf,*scanf */
471
472 /* XXX: setjmp, longjmp */
473
474 WRAPPER2(char *, asctime, struct tm *tm)
475 {
476   static char *reg_result = NULL;
477   char *result;
478   TRACE ("%s\n", __PRETTY_FUNCTION__);
479   MF_VALIDATE_EXTENT(tm, sizeof (struct tm), __MF_CHECK_READ, "asctime tm");
480   result = asctime (tm);
481   if (reg_result == NULL)
482     {
483       __mf_register (result, strlen (result)+1, __MF_TYPE_STATIC, "asctime string");
484       reg_result = result;
485     }
486   return result;
487 }
488
489
490 WRAPPER2(char *, ctime, const time_t *timep)
491 {
492   static char *reg_result = NULL;
493   char *result;
494   TRACE ("%s\n", __PRETTY_FUNCTION__);
495   MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "ctime time");
496   result = ctime (timep);
497   if (reg_result == NULL)
498     {
499       /* XXX: what if asctime and ctime return the same static ptr? */
500       __mf_register (result, strlen (result)+1, __MF_TYPE_STATIC, "ctime string");
501       reg_result = result;
502     }
503   return result;
504 }
505
506
507 WRAPPER2(struct tm*, localtime, const time_t *timep)
508 {
509   static struct tm *reg_result = NULL;
510   struct tm *result;
511   TRACE ("%s\n", __PRETTY_FUNCTION__);
512   MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "localtime time");
513   result = localtime (timep);
514   if (reg_result == NULL)
515     {
516       __mf_register (result, sizeof (struct tm), __MF_TYPE_STATIC, "localtime tm");
517       reg_result = result;
518     }
519   return result;
520 }
521
522
523 WRAPPER2(struct tm*, gmtime, const time_t *timep)
524 {
525   static struct tm *reg_result = NULL;
526   struct tm *result;
527   TRACE ("%s\n", __PRETTY_FUNCTION__);
528   MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "gmtime time");
529   result = gmtime (timep);
530   if (reg_result == NULL)
531     {
532       __mf_register (result, sizeof (struct tm), __MF_TYPE_STATIC, "gmtime tm");
533       reg_result = result;
534     }
535   return result;
536 }
537
538
539 /* EL start */
540
541 /* The following indicate if the result of the corresponding function
542  * should be explicitly un/registered by the wrapper
543 */
544
545 #ifdef __FreeBSD__
546 #define MF_REGISTER_fopen               __MF_TYPE_STATIC
547 #else
548 #undef  MF_REGISTER_fopen
549 #endif
550 #define MF_RESULT_SIZE_fopen            (sizeof (FILE))
551
552 #undef  MF_REGISTER_opendir
553 #define MF_RESULT_SIZE_opendir          0       /* (sizeof (DIR)) */
554 #undef  MF_REGISTER_readdir
555 #define MF_REGISTER_gethostbyname       __MF_TYPE_STATIC
556 #undef  MF_REGISTER_gethostbyname_items
557 #undef  MF_REGISTER_dlopen
558 #undef  MF_REGISTER_dlerror
559 #undef  MF_REGISTER_dlsym
560 #define MF_REGISTER_shmat               __MF_TYPE_GUESS
561
562
563 #include <time.h>
564 WRAPPER2(time_t, time, time_t *timep)
565 {
566   TRACE ("%s\n", __PRETTY_FUNCTION__);
567   if (NULL != timep)
568     MF_VALIDATE_EXTENT (timep, sizeof (*timep), __MF_CHECK_WRITE,
569       "time timep");
570   return time (timep);
571 }
572
573
574 WRAPPER2(char *, strerror, int errnum)
575 {
576   char *p;
577   static char * last_strerror = NULL;
578
579   TRACE ("%s\n", __PRETTY_FUNCTION__);
580   p = strerror (errnum);
581   if (last_strerror != NULL)
582     __mf_unregister (last_strerror, 0, __MF_TYPE_STATIC);
583   if (NULL != p)
584     __mf_register (p, strlen (p) + 1, __MF_TYPE_STATIC, "strerror result");
585   last_strerror = p;
586   return p;
587 }
588
589
590
591 /* An auxiliary data structure for tracking the hand-made stdio
592    buffers we generate during the fopen/fopen64 hooks.  In a civilized
593    language, this would be a simple dynamically sized FILE*->char*
594    lookup table, but this is C and we get to do it by hand.  */
595 struct mf_filebuffer
596 {
597   FILE *file;
598   char *buffer;
599   struct mf_filebuffer *next;
600 };
601 static struct mf_filebuffer *mf_filebuffers = NULL;
602
603 static void
604 mkbuffer (FILE *f)
605 {
606   /* Reset any buffer automatically provided by libc, since this may
607      have been done via mechanisms that libmudflap couldn't
608      intercept.  */
609   int rc;
610   size_t bufsize = BUFSIZ;
611   int bufmode;
612   char *buffer = malloc (bufsize);
613   struct mf_filebuffer *b = malloc (sizeof (struct mf_filebuffer));
614   assert ((buffer != NULL) && (b != NULL));
615
616   /* Link it into list.  */
617   b->file = f;
618   b->buffer = buffer;
619   b->next = mf_filebuffers;
620   mf_filebuffers = b;
621
622   /* Determine how the file is supposed to be buffered at the moment.  */
623   bufmode = fileno (f) == 2 ? _IONBF : (isatty (fileno (f)) ? _IOLBF : _IOFBF);
624
625   rc = setvbuf (f, buffer, bufmode, bufsize);
626   assert (rc == 0);
627 }
628
629 static void
630 unmkbuffer (FILE *f)
631 {
632   struct mf_filebuffer *b = mf_filebuffers;
633   struct mf_filebuffer **pb = & mf_filebuffers;
634   while (b != NULL)
635     {
636       if (b->file == f)
637         {
638           *pb = b->next;
639           free (b->buffer);
640           free (b);
641           return;
642         }
643       pb = & b->next;
644       b = b->next;
645     }
646 }
647
648
649
650 WRAPPER2(FILE *, fopen, const char *path, const char *mode)
651 {
652   size_t n;
653   FILE *p;
654   TRACE ("%s\n", __PRETTY_FUNCTION__);
655
656   n = strlen (path);
657   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen path");
658
659   n = strlen (mode);
660   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen mode");
661
662   p = fopen (path, mode);
663   if (NULL != p) {
664 #ifdef MF_REGISTER_fopen
665     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen result");
666 #endif
667     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen result");
668
669     mkbuffer (p);
670   }
671
672   return p;
673 }
674
675
676 WRAPPER2(int, setvbuf, FILE *stream, char *buf, int mode, size_t size)
677 {
678   int rc = 0;
679   TRACE ("%s\n", __PRETTY_FUNCTION__);
680
681   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE, "setvbuf stream");
682
683   unmkbuffer (stream);
684
685   if (buf != NULL)
686     MF_VALIDATE_EXTENT (buf, size, __MF_CHECK_WRITE, "setvbuf buffer");
687
688   /* Override the user only if it's an auto-allocated buffer request.  Otherwise
689      assume that the supplied buffer is already known to libmudflap.  */
690   if ((buf == NULL) && ((mode == _IOFBF) || (mode == _IOLBF)))
691     mkbuffer (stream);
692   else
693     rc = setvbuf (stream, buf, mode, size);
694
695   return rc;
696 }
697
698
699 #ifdef HAVE_SETBUF
700 WRAPPER2(int, setbuf, FILE* stream, char *buf)
701 {
702   return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
703 }
704 #endif
705
706 #ifdef HAVE_SETBUFFER
707 WRAPPER2(int, setbuffer, FILE* stream, char *buf, size_t sz)
708 {
709   return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, sz);
710 }
711 #endif
712
713 #ifdef HAVE_SETLINEBUF
714 WRAPPER2(int, setlinebuf, FILE* stream)
715 {
716   return __mfwrap_setvbuf(stream, NULL, _IOLBF, 0);
717 }
718 #endif
719
720
721
722 WRAPPER2(FILE *, fdopen, int fd, const char *mode)
723 {
724   size_t n;
725   FILE *p;
726   TRACE ("%s\n", __PRETTY_FUNCTION__);
727
728   n = strlen (mode);
729   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fdopen mode");
730
731   p = fdopen (fd, mode);
732   if (NULL != p) {
733 #ifdef MF_REGISTER_fopen
734     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fdopen result");
735 #endif
736     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fdopen result");
737
738     mkbuffer (p);
739   }
740
741   return p;
742 }
743
744
745 WRAPPER2(FILE *, freopen, const char *path, const char *mode, FILE *s)
746 {
747   size_t n;
748   FILE *p;
749   TRACE ("%s\n", __PRETTY_FUNCTION__);
750
751   n = strlen (path);
752   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen path");
753
754   MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen stream");
755   unmkbuffer (s);
756
757   n = strlen (mode);
758   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen mode");
759
760   p = freopen (path, mode, s);
761   if (NULL != p) {
762 #ifdef MF_REGISTER_fopen
763     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen result");
764 #endif
765     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen result");
766
767     mkbuffer (p);
768   }
769
770   return p;
771 }
772
773
774 #ifdef HAVE_FOPEN64
775 WRAPPER2(FILE *, fopen64, const char *path, const char *mode)
776 {
777   size_t n;
778   FILE *p;
779   TRACE ("%s\n", __PRETTY_FUNCTION__);
780
781   n = strlen (path);
782   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 path");
783
784   n = strlen (mode);
785   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 mode");
786
787   p = fopen64 (path, mode);
788   if (NULL != p) {
789 #ifdef MF_REGISTER_fopen
790     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen64 result");
791 #endif
792     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen64 result");
793
794     mkbuffer (p);
795   }
796
797   return p;
798 }
799 #endif
800
801
802 #ifdef HAVE_FREOPEN64
803 WRAPPER2(FILE *, freopen64, const char *path, const char *mode, FILE *s)
804 {
805   size_t n;
806   FILE *p;
807   TRACE ("%s\n", __PRETTY_FUNCTION__);
808
809   n = strlen (path);
810   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 path");
811
812   MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen64 stream");
813   unmkbuffer (s);
814
815   n = strlen (mode);
816   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 mode");
817
818   p = freopen (path, mode, s);
819   if (NULL != p) {
820 #ifdef MF_REGISTER_fopen
821     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen64 result");
822 #endif
823     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen64 result");
824
825     mkbuffer (p);
826   }
827
828   return p;
829 }
830 #endif
831
832
833 WRAPPER2(int, fclose, FILE *stream)
834 {
835   int resp;
836   TRACE ("%s\n", __PRETTY_FUNCTION__);
837   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
838     "fclose stream");
839   resp = fclose (stream);
840 #ifdef MF_REGISTER_fopen
841   __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
842 #endif
843   unmkbuffer (stream);
844
845   return resp;
846 }
847
848
849 WRAPPER2(size_t, fread, void *ptr, size_t size, size_t nmemb, FILE *stream)
850 {
851   TRACE ("%s\n", __PRETTY_FUNCTION__);
852   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
853     "fread stream");
854   MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_WRITE, "fread buffer");
855   return fread (ptr, size, nmemb, stream);
856 }
857
858
859 WRAPPER2(size_t, fwrite, const void *ptr, size_t size, size_t nmemb,
860         FILE *stream)
861 {
862   TRACE ("%s\n", __PRETTY_FUNCTION__);
863   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
864     "fwrite stream");
865   MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_READ, "fwrite buffer");
866   return fwrite (ptr, size, nmemb, stream);
867 }
868
869
870 WRAPPER2(int, fgetc, FILE *stream)
871 {
872   TRACE ("%s\n", __PRETTY_FUNCTION__);
873   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
874     "fgetc stream");
875   return fgetc (stream);
876 }
877
878
879 WRAPPER2(char *, fgets, char *s, int size, FILE *stream)
880 {
881   TRACE ("%s\n", __PRETTY_FUNCTION__);
882   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
883     "fgets stream");
884   MF_VALIDATE_EXTENT (s, size, __MF_CHECK_WRITE, "fgets buffer");
885   return fgets (s, size, stream);
886 }
887
888
889 WRAPPER2(int, getc, FILE *stream)
890 {
891   TRACE ("%s\n", __PRETTY_FUNCTION__);
892   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
893     "getc stream");
894   return getc (stream);
895 }
896
897
898 WRAPPER2(char *, gets, char *s)
899 {
900   TRACE ("%s\n", __PRETTY_FUNCTION__);
901   MF_VALIDATE_EXTENT (s, 1, __MF_CHECK_WRITE, "gets buffer");
902   /* Avoid link-time warning... */
903   s = fgets (s, INT_MAX, stdin);
904   if (NULL != s) {      /* better late than never */
905     size_t n = strlen (s);
906     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_WRITE, "gets buffer");
907   }
908   return s;
909 }
910
911
912 WRAPPER2(int, ungetc, int c, FILE *stream)
913 {
914   TRACE ("%s\n", __PRETTY_FUNCTION__);
915   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
916      "ungetc stream");
917   return ungetc (c, stream);
918 }
919
920
921 WRAPPER2(int, fputc, int c, FILE *stream)
922 {
923   TRACE ("%s\n", __PRETTY_FUNCTION__);
924   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
925     "fputc stream");
926   return fputc (c, stream);
927 }
928
929
930 WRAPPER2(int, fputs, const char *s, FILE *stream)
931 {
932   size_t n;
933   TRACE ("%s\n", __PRETTY_FUNCTION__);
934   n = strlen (s);
935   MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "fputs buffer");
936   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
937     "fputs stream");
938   return fputs (s, stream);
939 }
940
941
942 WRAPPER2(int, putc, int c, FILE *stream)
943 {
944   TRACE ("%s\n", __PRETTY_FUNCTION__);
945   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
946     "putc stream");
947   return putc (c, stream);
948 }
949
950
951 WRAPPER2(int, puts, const char *s)
952 {
953   size_t n;
954   TRACE ("%s\n", __PRETTY_FUNCTION__);
955   n = strlen (s);
956   MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "puts buffer");
957   return puts (s);
958 }
959
960
961 WRAPPER2(void, clearerr, FILE *stream)
962 {
963   TRACE ("%s\n", __PRETTY_FUNCTION__);
964   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
965     "clearerr stream");
966   clearerr (stream);
967 }
968
969
970 WRAPPER2(int, feof, FILE *stream)
971 {
972   TRACE ("%s\n", __PRETTY_FUNCTION__);
973   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
974     "feof stream");
975   return feof (stream);
976 }
977
978
979 WRAPPER2(int, ferror, FILE *stream)
980 {
981   TRACE ("%s\n", __PRETTY_FUNCTION__);
982   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
983     "ferror stream");
984   return ferror (stream);
985 }
986
987
988 WRAPPER2(int, fileno, FILE *stream)
989 {
990   TRACE ("%s\n", __PRETTY_FUNCTION__);
991   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
992     "fileno stream");
993   return fileno (stream);
994 }
995
996
997 WRAPPER2(int, printf, const char *format, ...)
998 {
999   size_t n;
1000   va_list ap;
1001   int result;
1002   TRACE ("%s\n", __PRETTY_FUNCTION__);
1003   n = strlen (format);
1004   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1005     "printf format");
1006   va_start (ap, format);
1007   result = vprintf (format, ap);
1008   va_end (ap);
1009   return result;
1010 }
1011
1012
1013 WRAPPER2(int, fprintf, FILE *stream, const char *format, ...)
1014 {
1015   size_t n;
1016   va_list ap;
1017   int result;
1018   TRACE ("%s\n", __PRETTY_FUNCTION__);
1019   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1020     "fprintf stream");
1021   n = strlen (format);
1022   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1023     "fprintf format");
1024   va_start (ap, format);
1025   result = vfprintf (stream, format, ap);
1026   va_end (ap);
1027   return result;
1028 }
1029
1030
1031 WRAPPER2(int, sprintf, char *str, const char *format, ...)
1032 {
1033   size_t n;
1034   va_list ap;
1035   int result;
1036   TRACE ("%s\n", __PRETTY_FUNCTION__);
1037   MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "sprintf str");
1038   n = strlen (format);
1039   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1040     "sprintf format");
1041   va_start (ap, format);
1042   result = vsprintf (str, format, ap);
1043   va_end (ap);
1044   n = strlen (str);
1045   MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "sprintf str");
1046   return result;
1047 }
1048
1049
1050 WRAPPER2(int, snprintf, char *str, size_t size, const char *format, ...)
1051 {
1052   size_t n;
1053   va_list ap;
1054   int result;
1055   TRACE ("%s\n", __PRETTY_FUNCTION__);
1056   MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "snprintf str");
1057   n = strlen (format);
1058   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1059     "snprintf format");
1060   va_start (ap, format);
1061   result = vsnprintf (str, size, format, ap);
1062   va_end (ap);
1063   return result;
1064 }
1065
1066
1067 WRAPPER2(int, vprintf,  const char *format, va_list ap)
1068 {
1069   size_t n;
1070   TRACE ("%s\n", __PRETTY_FUNCTION__);
1071   n = strlen (format);
1072   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1073     "vprintf format");
1074   return vprintf (format, ap);
1075 }
1076
1077
1078 WRAPPER2(int, vfprintf, FILE *stream, const char *format, va_list ap)
1079 {
1080   size_t n;
1081   TRACE ("%s\n", __PRETTY_FUNCTION__);
1082   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1083     "vfprintf stream");
1084   n = strlen (format);
1085   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1086     "vfprintf format");
1087   return vfprintf (stream, format, ap);
1088 }
1089
1090
1091 WRAPPER2(int, vsprintf, char *str, const char *format, va_list ap)
1092 {
1093   size_t n;
1094   int result;
1095   TRACE ("%s\n", __PRETTY_FUNCTION__);
1096   MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "vsprintf str");
1097   n = strlen (format);
1098   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1099     "vsprintf format");
1100   result = vsprintf (str, format, ap);
1101   n = strlen (str);
1102   MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "vsprintf str");
1103   return result;
1104 }
1105
1106
1107 WRAPPER2(int, vsnprintf, char *str, size_t size, const char *format,
1108         va_list ap)
1109 {
1110   size_t n;
1111   TRACE ("%s\n", __PRETTY_FUNCTION__);
1112   MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "vsnprintf str");
1113   n = strlen (format);
1114   MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
1115     "vsnprintf format");
1116   return vsnprintf (str, size, format, ap);
1117 }
1118
1119
1120 WRAPPER2(int , access, const char *path, int mode)
1121 {
1122   size_t n;
1123   TRACE ("%s\n", __PRETTY_FUNCTION__);
1124   n = strlen (path);
1125   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "access path");
1126   return access (path, mode);
1127 }
1128
1129
1130 WRAPPER2(int , remove, const char *path)
1131 {
1132   size_t n;
1133   TRACE ("%s\n", __PRETTY_FUNCTION__);
1134   n = strlen (path);
1135   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "remove path");
1136   return remove (path);
1137 }
1138
1139
1140 WRAPPER2(int, fflush, FILE *stream)
1141 {
1142   TRACE ("%s\n", __PRETTY_FUNCTION__);
1143   if (stream != NULL)
1144     MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1145                         "fflush stream");
1146   return fflush (stream);
1147 }
1148
1149
1150 WRAPPER2(int, fseek, FILE *stream, long offset, int whence)
1151 {
1152   TRACE ("%s\n", __PRETTY_FUNCTION__);
1153   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1154     "fseek stream");
1155   return fseek (stream, offset, whence);
1156 }
1157
1158
1159 #ifdef HAVE_FSEEKO64
1160 WRAPPER2(int, fseeko64, FILE *stream, off64_t offset, int whence)
1161 {
1162   TRACE ("%s\n", __PRETTY_FUNCTION__);
1163   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1164     "fseeko64 stream");
1165   return fseeko64 (stream, offset, whence);
1166 }
1167 #endif
1168
1169
1170 WRAPPER2(long, ftell, FILE *stream)
1171 {
1172   TRACE ("%s\n", __PRETTY_FUNCTION__);
1173   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1174     "ftell stream");
1175   return ftell (stream);
1176 }
1177
1178
1179 #ifdef HAVE_FTELLO64
1180 WRAPPER2(off64_t, ftello64, FILE *stream)
1181 {
1182   TRACE ("%s\n", __PRETTY_FUNCTION__);
1183   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1184     "ftello64 stream");
1185   return ftello64 (stream);
1186 }
1187 #endif
1188
1189
1190 WRAPPER2(void, rewind, FILE *stream)
1191 {
1192   TRACE ("%s\n", __PRETTY_FUNCTION__);
1193   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1194     "rewind stream");
1195   rewind (stream);
1196 }
1197
1198
1199 WRAPPER2(int, fgetpos, FILE *stream, fpos_t *pos)
1200 {
1201   TRACE ("%s\n", __PRETTY_FUNCTION__);
1202   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1203     "fgetpos stream");
1204   MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_WRITE, "fgetpos pos");
1205   return fgetpos (stream, pos);
1206 }
1207
1208
1209 WRAPPER2(int, fsetpos, FILE *stream, fpos_t *pos)
1210 {
1211   TRACE ("%s\n", __PRETTY_FUNCTION__);
1212   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1213     "fsetpos stream");
1214   MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_READ, "fsetpos pos");
1215   return fsetpos (stream, pos);
1216 }
1217
1218
1219 WRAPPER2(int , stat, const char *path, struct stat *buf)
1220 {
1221   size_t n;
1222   TRACE ("%s\n", __PRETTY_FUNCTION__);
1223   n = strlen (path);
1224   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat path");
1225   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat buf");
1226   return stat (path, buf);
1227 }
1228
1229
1230 #ifdef HAVE_STAT64
1231 WRAPPER2(int , stat64, const char *path, struct stat64 *buf)
1232 {
1233   size_t n;
1234   TRACE ("%s\n", __PRETTY_FUNCTION__);
1235   n = strlen (path);
1236   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat64 path");
1237   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat64 buf");
1238   return stat64 (path, buf);
1239 }
1240 #endif
1241
1242
1243 WRAPPER2(int , fstat, int filedes, struct stat *buf)
1244 {
1245   TRACE ("%s\n", __PRETTY_FUNCTION__);
1246   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "fstat buf");
1247   return fstat (filedes, buf);
1248 }
1249
1250
1251 WRAPPER2(int , lstat, const char *path, struct stat *buf)
1252 {
1253   size_t n;
1254   TRACE ("%s\n", __PRETTY_FUNCTION__);
1255   n = strlen (path);
1256   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "lstat path");
1257   MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "lstat buf");
1258   return lstat (path, buf);
1259 }
1260
1261
1262 WRAPPER2(int , mkfifo, const char *path, mode_t mode)
1263 {
1264   size_t n;
1265   TRACE ("%s\n", __PRETTY_FUNCTION__);
1266   n = strlen (path);
1267   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "mkfifo path");
1268   return mkfifo (path, mode);
1269 }
1270
1271
1272 #ifdef HAVE_DIRENT_H
1273 WRAPPER2(DIR *, opendir, const char *path)
1274 {
1275   DIR *p;
1276   size_t n;
1277   TRACE ("%s\n", __PRETTY_FUNCTION__);
1278   n = strlen (path);
1279   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "opendir path");
1280
1281   p = opendir (path);
1282   if (NULL != p) {
1283 #ifdef MF_REGISTER_opendir
1284     __mf_register (p, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir,
1285       "opendir result");
1286 #endif
1287     MF_VALIDATE_EXTENT (p, MF_RESULT_SIZE_opendir, __MF_CHECK_WRITE,
1288       "opendir result");
1289   }
1290   return p;
1291 }
1292
1293
1294 WRAPPER2(int, closedir, DIR *dir)
1295 {
1296   TRACE ("%s\n", __PRETTY_FUNCTION__);
1297   MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_WRITE, "closedir dir");
1298 #ifdef MF_REGISTER_opendir
1299   __mf_unregister (dir, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir);
1300 #endif
1301   return closedir (dir);
1302 }
1303
1304
1305 WRAPPER2(struct dirent *, readdir, DIR *dir)
1306 {
1307   struct dirent *p;
1308   TRACE ("%s\n", __PRETTY_FUNCTION__);
1309   MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_READ, "readdir dir");
1310   p = readdir (dir);
1311   if (NULL != p) {
1312 #ifdef MF_REGISTER_readdir
1313     __mf_register (p, sizeof (*p), MF_REGISTER_readdir, "readdir result");
1314 #endif
1315     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "readdir result");
1316   }
1317   return p;
1318 }
1319 #endif
1320
1321
1322 #ifdef HAVE_SYS_SOCKET_H
1323
1324 WRAPPER2(int, recv, int s, void *buf, size_t len, int flags)
1325 {
1326   TRACE ("%s\n", __PRETTY_FUNCTION__);
1327   MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recv buf");
1328   return recv (s, buf, len, flags);
1329 }
1330
1331
1332 WRAPPER2(int, recvfrom, int s, void *buf, size_t len, int flags,
1333                 struct sockaddr *from, socklen_t *fromlen)
1334 {
1335   TRACE ("%s\n", __PRETTY_FUNCTION__);
1336   MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recvfrom buf");
1337   MF_VALIDATE_EXTENT (from, (size_t)*fromlen, __MF_CHECK_WRITE,
1338     "recvfrom from");
1339   return recvfrom (s, buf, len, flags, from, fromlen);
1340 }
1341
1342
1343 WRAPPER2(int, recvmsg, int s, struct msghdr *msg, int flags)
1344 {
1345   TRACE ("%s\n", __PRETTY_FUNCTION__);
1346   MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_WRITE, "recvmsg msg");
1347   return recvmsg (s, msg, flags);
1348 }
1349
1350
1351 WRAPPER2(int, send, int s, const void *msg, size_t len, int flags)
1352 {
1353   TRACE ("%s\n", __PRETTY_FUNCTION__);
1354   MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "send msg");
1355   return send (s, msg, len, flags);
1356 }
1357
1358
1359 WRAPPER2(int, sendto, int s, const void *msg, size_t len, int flags,
1360                 const struct sockaddr *to, socklen_t tolen)
1361 {
1362   TRACE ("%s\n", __PRETTY_FUNCTION__);
1363   MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "sendto msg");
1364   MF_VALIDATE_EXTENT (to, (size_t)tolen, __MF_CHECK_WRITE, "sendto to");
1365   return sendto (s, msg, len, flags, to, tolen);
1366 }
1367
1368
1369 WRAPPER2(int, sendmsg, int s, const void *msg, int flags)
1370 {
1371   TRACE ("%s\n", __PRETTY_FUNCTION__);
1372   MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_READ, "sendmsg msg");
1373   return sendmsg (s, msg, flags);
1374 }
1375
1376
1377 WRAPPER2(int, setsockopt, int s, int level, int optname, const void *optval,
1378         socklen_t optlen)
1379 {
1380   TRACE ("%s\n", __PRETTY_FUNCTION__);
1381   MF_VALIDATE_EXTENT (optval, (size_t)optlen, __MF_CHECK_READ,
1382     "setsockopt optval");
1383   return setsockopt (s, level, optname, optval, optlen);
1384 }
1385
1386
1387 WRAPPER2(int, getsockopt, int s, int level, int optname, void *optval,
1388                 socklen_t *optlen)
1389 {
1390   TRACE ("%s\n", __PRETTY_FUNCTION__);
1391   MF_VALIDATE_EXTENT (optval, (size_t)*optlen, __MF_CHECK_WRITE,
1392     "getsockopt optval");
1393   return getsockopt (s, level, optname, optval, optlen);
1394 }
1395
1396
1397 WRAPPER2(int, accept, int s, struct  sockaddr *addr, socklen_t *addrlen)
1398 {
1399   TRACE ("%s\n", __PRETTY_FUNCTION__);
1400   if (addr != NULL)
1401     MF_VALIDATE_EXTENT (addr, (size_t)*addrlen, __MF_CHECK_WRITE, "accept addr");
1402   return accept (s, addr, addrlen);
1403 }
1404
1405
1406 WRAPPER2(int, bind, int sockfd, struct  sockaddr *addr, socklen_t addrlen)
1407 {
1408   TRACE ("%s\n", __PRETTY_FUNCTION__);
1409   MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_WRITE, "bind addr");
1410   return bind (sockfd, addr, addrlen);
1411 }
1412
1413
1414 WRAPPER2(int, connect, int sockfd, const struct sockaddr  *addr,
1415         socklen_t addrlen)
1416 {
1417   TRACE ("%s\n", __PRETTY_FUNCTION__);
1418   MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_READ,
1419     "connect addr");
1420   return connect (sockfd, addr, addrlen);
1421 }
1422
1423 #endif /* HAVE_SYS_SOCKET_H */
1424
1425
1426 WRAPPER2(int, gethostname, char *name, size_t len)
1427 {
1428   TRACE ("%s\n", __PRETTY_FUNCTION__);
1429   MF_VALIDATE_EXTENT (name, len, __MF_CHECK_WRITE, "gethostname name");
1430   return gethostname (name, len);
1431 }
1432
1433
1434 #ifdef HAVE_SETHOSTNAME
1435 WRAPPER2(int, sethostname, const char *name, size_t len)
1436 {
1437   TRACE ("%s\n", __PRETTY_FUNCTION__);
1438   MF_VALIDATE_EXTENT (name, len, __MF_CHECK_READ, "sethostname name");
1439   return sethostname (name, len);
1440 }
1441 #endif
1442
1443
1444 #ifdef HAVE_NETDB_H
1445
1446 WRAPPER2(struct hostent *, gethostbyname, const char *name)
1447 {
1448   struct hostent *p;
1449   char **ss;
1450   char *s;
1451   size_t n;
1452   int nreg;
1453   TRACE ("%s\n", __PRETTY_FUNCTION__);
1454   n = strlen (name);
1455   MF_VALIDATE_EXTENT (name, CLAMPADD(n, 1), __MF_CHECK_READ,
1456     "gethostbyname name");
1457   p = gethostbyname (name);
1458   if (NULL != p) {
1459 #ifdef MF_REGISTER_gethostbyname
1460     __mf_register (p, sizeof (*p), MF_REGISTER_gethostbyname,
1461       "gethostbyname result");
1462 #endif
1463     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE,
1464       "gethostbyname result");
1465     if (NULL != (s = p->h_name)) {
1466       n = strlen (s);
1467       n = CLAMPADD(n, 1);
1468 #ifdef MF_REGISTER_gethostbyname_items
1469       __mf_register (s, n, MF_REGISTER_gethostbyname_items,
1470         "gethostbyname result->h_name");
1471 #endif
1472       MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
1473         "gethostbyname result->h_name");
1474     }
1475
1476     if (NULL != (ss = p->h_aliases)) {
1477       for (nreg = 1;; ++nreg) {
1478         s = *ss++;
1479         if (NULL == s)
1480           break;
1481         n = strlen (s);
1482         n = CLAMPADD(n, 1);
1483 #ifdef MF_REGISTER_gethostbyname_items
1484         __mf_register (s, n, MF_REGISTER_gethostbyname_items,
1485           "gethostbyname result->h_aliases[]");
1486 #endif
1487         MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
1488           "gethostbyname result->h_aliases[]");
1489       }
1490       nreg *= sizeof (*p->h_aliases);
1491 #ifdef MF_REGISTER_gethostbyname_items
1492       __mf_register (p->h_aliases, nreg, MF_REGISTER_gethostbyname_items,
1493         "gethostbyname result->h_aliases");
1494 #endif
1495       MF_VALIDATE_EXTENT (p->h_aliases, nreg, __MF_CHECK_WRITE,
1496         "gethostbyname result->h_aliases");
1497     }
1498
1499     if (NULL != (ss = p->h_addr_list)) {
1500       for (nreg = 1;; ++nreg) {
1501         s = *ss++;
1502         if (NULL == s)
1503           break;
1504 #ifdef MF_REGISTER_gethostbyname_items
1505         __mf_register (s, p->h_length, MF_REGISTER_gethostbyname_items,
1506           "gethostbyname result->h_addr_list[]");
1507 #endif
1508         MF_VALIDATE_EXTENT (s, p->h_length, __MF_CHECK_WRITE,
1509           "gethostbyname result->h_addr_list[]");
1510       }
1511       nreg *= sizeof (*p->h_addr_list);
1512 #ifdef MF_REGISTER_gethostbyname_items
1513       __mf_register (p->h_addr_list, nreg, MF_REGISTER_gethostbyname_items,
1514         "gethostbyname result->h_addr_list");
1515 #endif
1516       MF_VALIDATE_EXTENT (p->h_addr_list, nreg, __MF_CHECK_WRITE,
1517         "gethostbyname result->h_addr_list");
1518     }
1519   }
1520   return p;
1521 }
1522
1523 #endif /* HAVE_NETDB_H */
1524
1525
1526 #ifdef HAVE_SYS_WAIT_H
1527
1528 WRAPPER2(pid_t, wait, int *status)
1529 {
1530   TRACE ("%s\n", __PRETTY_FUNCTION__);
1531   if (NULL != status)
1532     MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
1533       "wait status");
1534   return wait (status);
1535 }
1536
1537
1538 WRAPPER2(pid_t, waitpid, pid_t pid, int *status, int options)
1539 {
1540   TRACE ("%s\n", __PRETTY_FUNCTION__);
1541   if (NULL != status)
1542     MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
1543       "waitpid status");
1544   return waitpid (pid, status, options);
1545 }
1546
1547 #endif /* HAVE_SYS_WAIT_H */
1548
1549
1550 WRAPPER2(FILE *, popen, const char *command, const char *mode)
1551 {
1552   size_t n;
1553   FILE *p;
1554   TRACE ("%s\n", __PRETTY_FUNCTION__);
1555
1556   n = strlen (command);
1557   MF_VALIDATE_EXTENT (command, CLAMPADD(n, 1), __MF_CHECK_READ, "popen path");
1558
1559   n = strlen (mode);
1560   MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "popen mode");
1561
1562   p = popen (command, mode);
1563   if (NULL != p) {
1564 #ifdef MF_REGISTER_fopen
1565     __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "popen result");
1566 #endif
1567     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "popen result");
1568   }
1569   return p;
1570 }
1571
1572
1573 WRAPPER2(int, pclose, FILE *stream)
1574 {
1575   int resp;
1576   TRACE ("%s\n", __PRETTY_FUNCTION__);
1577   MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
1578     "pclose stream");
1579   resp = pclose (stream);
1580 #ifdef MF_REGISTER_fopen
1581   __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
1582 #endif
1583   return resp;
1584 }
1585
1586
1587 WRAPPER2(int, execve, const char *path, char *const argv [],
1588         char *const envp[])
1589 {
1590   size_t n;
1591   char *const *p;
1592   const char *s;
1593   TRACE ("%s\n", __PRETTY_FUNCTION__);
1594
1595   n = strlen (path);
1596   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execve path");
1597
1598   for (p = argv;;) {
1599     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *argv");
1600     s = *p++;
1601     if (NULL == s)
1602       break;
1603     n = strlen (s);
1604     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **argv");
1605   }
1606
1607   for (p = envp;;) {
1608     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *envp");
1609     s = *p++;
1610     if (NULL == s)
1611       break;
1612     n = strlen (s);
1613     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **envp");
1614   }
1615   return execve (path, argv, envp);
1616 }
1617
1618
1619 WRAPPER2(int, execv, const char *path, char *const argv [])
1620 {
1621   size_t n;
1622   char *const *p;
1623   const char *s;
1624   TRACE ("%s\n", __PRETTY_FUNCTION__);
1625
1626   n = strlen (path);
1627   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execv path");
1628
1629   for (p = argv;;) {
1630     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execv *argv");
1631     s = *p++;
1632     if (NULL == s)
1633       break;
1634     n = strlen (s);
1635     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execv **argv");
1636   }
1637   return execv (path, argv);
1638 }
1639
1640
1641 WRAPPER2(int, execvp, const char *path, char *const argv [])
1642 {
1643   size_t n;
1644   char *const *p;
1645   const char *s;
1646   TRACE ("%s\n", __PRETTY_FUNCTION__);
1647
1648   n = strlen (path);
1649   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp path");
1650
1651   for (p = argv;;) {
1652     MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execvp *argv");
1653     s = *p++;
1654     if (NULL == s)
1655       break;
1656     n = strlen (s);
1657     MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp **argv");
1658   }
1659   return execvp (path, argv);
1660 }
1661
1662
1663 WRAPPER2(int, system, const char *string)
1664 {
1665   size_t n;
1666   TRACE ("%s\n", __PRETTY_FUNCTION__);
1667   n = strlen (string);
1668   MF_VALIDATE_EXTENT (string, CLAMPADD(n, 1), __MF_CHECK_READ,
1669     "system string");
1670   return system (string);
1671 }
1672
1673
1674 WRAPPER2(void *, dlopen, const char *path, int flags)
1675 {
1676   void *p;
1677   size_t n;
1678   TRACE ("%s\n", __PRETTY_FUNCTION__);
1679   n = strlen (path);
1680   MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "dlopen path");
1681   p = dlopen (path, flags);
1682   if (NULL != p) {
1683 #ifdef MF_REGISTER_dlopen
1684     __mf_register (p, 0, MF_REGISTER_dlopen, "dlopen result");
1685 #endif
1686     MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlopen result");
1687   }
1688   return p;
1689 }
1690
1691
1692 WRAPPER2(int, dlclose, void *handle)
1693 {
1694   int resp;
1695   TRACE ("%s\n", __PRETTY_FUNCTION__);
1696   MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlclose handle");
1697   resp = dlclose (handle);
1698 #ifdef MF_REGISTER_dlopen
1699   __mf_unregister (handle, 0, MF_REGISTER_dlopen);
1700 #endif
1701   return resp;
1702 }
1703
1704
1705 WRAPPER2(char *, dlerror)
1706 {
1707   char *p;
1708   TRACE ("%s\n", __PRETTY_FUNCTION__);
1709   p = dlerror ();
1710   if (NULL != p) {
1711     size_t n;
1712     n = strlen (p);
1713     n = CLAMPADD(n, 1);
1714 #ifdef MF_REGISTER_dlerror
1715     __mf_register (p, n, MF_REGISTER_dlerror, "dlerror result");
1716 #endif
1717     MF_VALIDATE_EXTENT (p, n, __MF_CHECK_WRITE, "dlerror result");
1718   }
1719   return p;
1720 }
1721
1722
1723 WRAPPER2(void *, dlsym, void *handle, char *symbol)
1724 {
1725   size_t n;
1726   void *p;
1727   TRACE ("%s\n", __PRETTY_FUNCTION__);
1728   MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlsym handle");
1729   n = strlen (symbol);
1730   MF_VALIDATE_EXTENT (symbol, CLAMPADD(n, 1), __MF_CHECK_READ, "dlsym symbol");
1731   p = dlsym (handle, symbol);
1732   if (NULL != p) {
1733 #ifdef MF_REGISTER_dlsym
1734     __mf_register (p, 0, MF_REGISTER_dlsym, "dlsym result");
1735 #endif
1736     MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlsym result");
1737   }
1738   return p;
1739 }
1740
1741
1742 #if defined (HAVE_SYS_IPC_H) && defined (HAVE_SYS_SEM_H) && defined (HAVE_SYS_SHM_H)
1743
1744 WRAPPER2(int, semop, int semid, struct sembuf *sops, unsigned nsops)
1745 {
1746   TRACE ("%s\n", __PRETTY_FUNCTION__);
1747   MF_VALIDATE_EXTENT (sops, sizeof (*sops) * nsops, __MF_CHECK_READ,
1748     "semop sops");
1749   return semop (semid, sops, nsops);
1750 }
1751
1752
1753 #ifndef HAVE_UNION_SEMUN
1754 union semun {
1755         int val;                        /* value for SETVAL */
1756         struct semid_ds *buf;           /* buffer for IPC_STAT, IPC_SET */
1757         unsigned short int *array;      /* array for GETALL, SETALL */
1758         struct seminfo *__buf;          /* buffer for IPC_INFO */
1759 };
1760 #endif
1761 WRAPPER2(int, semctl, int semid, int semnum, int cmd, union semun arg)
1762 {
1763   TRACE ("%s\n", __PRETTY_FUNCTION__);
1764   switch (cmd) {
1765   case IPC_STAT:
1766     MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_WRITE,
1767       "semctl buf");
1768     break;
1769   case IPC_SET:
1770     MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_READ,
1771       "semctl buf");
1772     break;
1773   case GETALL:
1774     MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_WRITE,
1775       "semctl array");
1776   case SETALL:
1777     MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_READ,
1778       "semctl array");
1779     break;
1780 #ifdef IPC_INFO
1781   /* FreeBSD 5.1 And Cygwin headers include IPC_INFO but not the __buf field.  */
1782 #if !defined(__FreeBSD__) && !defined(__CYGWIN__)
1783   case IPC_INFO:
1784     MF_VALIDATE_EXTENT (arg.__buf, sizeof (*arg.__buf), __MF_CHECK_WRITE,
1785       "semctl __buf");
1786     break;
1787 #endif
1788 #endif
1789   default:
1790     break;
1791   }
1792   return semctl (semid, semnum, cmd, arg);
1793 }
1794
1795
1796 WRAPPER2(int, shmctl, int shmid, int cmd, struct shmid_ds *buf)
1797 {
1798   TRACE ("%s\n", __PRETTY_FUNCTION__);
1799   switch (cmd) {
1800   case IPC_STAT:
1801     MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_WRITE,
1802       "shmctl buf");
1803     break;
1804   case IPC_SET:
1805     MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ,
1806       "shmctl buf");
1807     break;
1808   default:
1809     break;
1810   }
1811   return shmctl (shmid, cmd, buf);
1812 }
1813
1814
1815 WRAPPER2(void *, shmat, int shmid, const void *shmaddr, int shmflg)
1816 {
1817   void *p;
1818   TRACE ("%s\n", __PRETTY_FUNCTION__);
1819   p = shmat (shmid, shmaddr, shmflg);
1820 #ifdef MF_REGISTER_shmat
1821   if (NULL != p) {
1822     struct shmid_ds buf;
1823     __mf_register (p, shmctl (shmid, IPC_STAT, &buf) ? 0 : buf.shm_segsz,
1824       MF_REGISTER_shmat, "shmat result");
1825   }
1826 #endif
1827   return p;
1828 }
1829
1830
1831 WRAPPER2(int, shmdt, const void *shmaddr)
1832 {
1833   int resp;
1834   TRACE ("%s\n", __PRETTY_FUNCTION__);
1835   resp = shmdt (shmaddr);
1836 #ifdef MF_REGISTER_shmat
1837   __mf_unregister ((void *)shmaddr, 0, MF_REGISTER_shmat);
1838 #endif
1839   return resp;
1840 }
1841
1842
1843 #endif /* HAVE_SYS_IPC/SEM/SHM_H */
1844
1845
1846
1847 /* ctype stuff.  This is host-specific by necessity, as the arrays
1848    that is used by most is*()/to*() macros are implementation-defined.  */
1849
1850 /* GLIBC 2.3 */
1851 #ifdef HAVE___CTYPE_B_LOC
1852 WRAPPER2(unsigned short **, __ctype_b_loc, void)
1853 {
1854   static unsigned short * last_buf = (void *) 0;
1855   static unsigned short ** last_ptr = (void *) 0;
1856   unsigned short ** ptr = (unsigned short **) __ctype_b_loc ();
1857   unsigned short * buf = * ptr;
1858   if (ptr != last_ptr)
1859     {
1860       /* XXX: unregister last_ptr? */
1861       last_ptr = ptr;
1862       __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_b_loc **");
1863     }
1864   if (buf != last_buf)
1865     {
1866       last_buf = buf;
1867       __mf_register ((void *) (last_buf - 128), 384 * sizeof(unsigned short), __MF_TYPE_STATIC,
1868                      "ctype_b_loc []");
1869     }
1870   return ptr;
1871 }
1872 #endif
1873
1874 #ifdef HAVE___CTYPE_TOUPPER_LOC
1875 WRAPPER2(int **, __ctype_toupper_loc, void)
1876 {
1877   static int * last_buf = (void *) 0;
1878   static int ** last_ptr = (void *) 0;
1879   int ** ptr = (int **) __ctype_toupper_loc ();
1880   int * buf = * ptr;
1881   if (ptr != last_ptr)
1882     {
1883       /* XXX: unregister last_ptr? */
1884       last_ptr = ptr;
1885       __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_toupper_loc **");
1886     }
1887   if (buf != last_buf)
1888     {
1889       last_buf = buf;
1890       __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
1891                      "ctype_toupper_loc []");
1892     }
1893   return ptr;
1894 }
1895 #endif
1896
1897 #ifdef HAVE___CTYPE_TOLOWER_LOC
1898 WRAPPER2(int **, __ctype_tolower_loc, void)
1899 {
1900   static int * last_buf = (void *) 0;
1901   static int ** last_ptr = (void *) 0;
1902   int ** ptr = (int **) __ctype_tolower_loc ();
1903   int * buf = * ptr;
1904   if (ptr != last_ptr)
1905     {
1906       /* XXX: unregister last_ptr? */
1907       last_ptr = ptr;
1908       __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_tolower_loc **");
1909     }
1910   if (buf != last_buf)
1911     {
1912       last_buf = buf;
1913       __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
1914                      "ctype_tolower_loc []");
1915     }
1916   return ptr;
1917 }
1918 #endif
1919
1920
1921 /* passwd/group related functions.  These register every (static) pointer value returned,
1922    and rely on libmudflap's quiet toleration of duplicate static registrations.  */
1923
1924 #ifdef HAVE_GETLOGIN
1925 WRAPPER2(char *, getlogin, void)
1926 {
1927   char *buf = getlogin ();
1928   if (buf != NULL)
1929     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1930                    "getlogin() return");
1931   return buf;
1932 }
1933 #endif
1934
1935
1936 #ifdef HAVE_CUSERID
1937 WRAPPER2(char *, cuserid, char * buf)
1938 {
1939   if (buf != NULL)
1940     {
1941       MF_VALIDATE_EXTENT(buf, L_cuserid, __MF_CHECK_WRITE,
1942                          "cuserid destination");
1943       return cuserid (buf);
1944     }
1945   buf = cuserid (NULL);
1946   if (buf != NULL)
1947     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1948                    "getcuserid() return");
1949   return buf;
1950 }
1951 #endif
1952
1953
1954 #ifdef HAVE_GETPWNAM
1955 WRAPPER2(struct passwd *, getpwnam, const char *name)
1956 {
1957   struct passwd *buf;
1958   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
1959                      "getpwnam name");
1960   buf = getpwnam (name);
1961   if (buf != NULL)
1962     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1963                    "getpw*() return");
1964   return buf;
1965 }
1966 #endif
1967
1968
1969 #ifdef HAVE_GETPWUID
1970 WRAPPER2(struct passwd *, getpwuid, uid_t uid)
1971 {
1972   struct passwd *buf;
1973   buf = getpwuid (uid);
1974   if (buf != NULL)
1975     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1976                    "getpw*() return");
1977   return buf;
1978 }
1979 #endif
1980
1981
1982 #ifdef HAVE_GETGRNAM
1983 WRAPPER2(struct group *, getgrnam, const char *name)
1984 {
1985   struct group *buf;
1986   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
1987                      "getgrnam name");
1988   buf = getgrnam (name);
1989   if (buf != NULL)
1990     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
1991                    "getgr*() return");
1992   return buf;
1993 }
1994 #endif
1995
1996
1997 #ifdef HAVE_GETGRGID
1998 WRAPPER2(struct group *, getgrgid, uid_t uid)
1999 {
2000   struct group *buf;
2001   buf = getgrgid (uid);
2002   if (buf != NULL)
2003     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2004                    "getgr*() return");
2005   return buf;
2006 }
2007 #endif
2008
2009
2010 #ifdef HAVE_GETSERVENT
2011 WRAPPER2(struct servent *, getservent, void)
2012 {
2013   struct servent *buf;
2014   buf = getservent ();
2015   if (buf != NULL)
2016     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2017                    "getserv*() return");
2018   return buf;
2019 }
2020 #endif
2021
2022
2023 #ifdef HAVE_GETSERVBYNAME
2024 WRAPPER2(struct servent *, getservbyname, const char *name, const char *proto)
2025 {
2026   struct servent *buf;
2027   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
2028                      "getservbyname name");
2029   MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
2030                      "getservbyname proto");
2031   buf = getservbyname (name, proto);
2032   if (buf != NULL)
2033     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2034                    "getserv*() return");
2035   return buf;
2036 }
2037 #endif
2038
2039
2040 #ifdef HAVE_GETSERVBYPORT
2041 WRAPPER2(struct servent *, getservbyport, int port, const char *proto)
2042 {
2043   struct servent *buf;
2044   MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
2045                      "getservbyport proto");
2046   buf = getservbyport (port, proto);
2047   if (buf != NULL)
2048     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2049                    "getserv*() return");
2050   return buf;
2051 }
2052 #endif
2053
2054
2055 #ifdef HAVE_GAI_STRERROR
2056 WRAPPER2(const char *, gai_strerror, int errcode)
2057 {
2058   const char *buf;
2059   buf = gai_strerror (errcode);
2060   if (buf != NULL)
2061     __mf_register ((void *) buf, strlen(buf)+1, __MF_TYPE_STATIC,
2062                    "gai_strerror() return");
2063   return buf;
2064 }
2065 #endif
2066
2067
2068 #ifdef HAVE_GETMNTENT
2069 #ifdef HAVE_MNTENT_H
2070 WRAPPER2(struct mntent *, getmntent, FILE *filep)
2071 {
2072   struct mntent *m;
2073   static struct mntent *last = NULL;
2074
2075   MF_VALIDATE_EXTENT (filep, sizeof (*filep), __MF_CHECK_WRITE,
2076     "getmntent stream");
2077 #define UR(field) __mf_unregister(last->field, strlen (last->field)+1, __MF_TYPE_STATIC)
2078   if (last)
2079     {
2080       UR (mnt_fsname);
2081       UR (mnt_dir);
2082       UR (mnt_type);
2083       UR (mnt_opts);
2084       __mf_unregister (last, sizeof (*last), __MF_TYPE_STATIC);
2085     }
2086 #undef UR
2087
2088   m = getmntent (filep);
2089   last = m;
2090
2091 #define R(field) __mf_register(last->field, strlen (last->field)+1, __MF_TYPE_STATIC, "mntent " #field)
2092   if (m)
2093     {
2094       R (mnt_fsname);
2095       R (mnt_dir);
2096       R (mnt_type);
2097       R (mnt_opts);
2098       __mf_register (last, sizeof (*last), __MF_TYPE_STATIC, "getmntent result");
2099     }
2100 #undef R
2101
2102   return m;
2103 }
2104 #elif defined HAVE_SYS_MNTTAB_H
2105 WRAPPER2(int, getmntent, FILE *filep, struct mnttab *mp)
2106 {
2107   static struct mnttab *last = NULL;
2108   int res;
2109
2110   MF_VALIDATE_EXTENT (filep, sizeof (*filep), __MF_CHECK_WRITE,
2111     "getmntent stream");
2112 #define UR(field) __mf_unregister(last->field, strlen (last->field)+1, __MF_TYPE_STATIC)
2113   if (last)
2114     {
2115       UR (mnt_special);
2116       UR (mnt_mountp);
2117       UR (mnt_fstype);
2118       UR (mnt_mntopts);
2119       UR (mnt_time);
2120       __mf_unregister (last, sizeof (*last), __MF_TYPE_STATIC);
2121     }
2122 #undef UR
2123
2124   res = getmntent (filep, mp);
2125   last = mp;
2126
2127 #define R(field) __mf_register(last->field, strlen (last->field)+1, __MF_TYPE_STATIC, "mntent " #field)
2128   if (mp)
2129     {
2130       R (mnt_special);
2131       R (mnt_mountp);
2132       R (mnt_fstype);
2133       R (mnt_mntopts);
2134       R (mnt_time);
2135       __mf_register (last, sizeof (*last), __MF_TYPE_STATIC, "getmntent result");
2136     }
2137 #undef R
2138
2139   return res;
2140 }
2141 #endif
2142 #endif
2143
2144
2145 #ifdef HAVE_INET_NTOA
2146 WRAPPER2(char *, inet_ntoa, struct in_addr in)
2147 {
2148   static char *last_buf = NULL;
2149   char *buf;
2150   if (last_buf)
2151     __mf_unregister (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC);
2152   buf = inet_ntoa (in);
2153   last_buf = buf;
2154   if (buf)
2155     __mf_register (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC, "inet_ntoa result");
2156   return buf;
2157 }
2158 #endif
2159
2160
2161 #ifdef HAVE_GETPROTOENT
2162 WRAPPER2(struct protoent *, getprotoent, void)
2163 {
2164   struct protoent *buf;
2165   buf = getprotoent ();
2166   if (buf != NULL)
2167     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC, "getproto*() return");
2168   return buf;
2169 }
2170 #endif
2171
2172
2173 #ifdef HAVE_GETPROTOBYNAME
2174 WRAPPER2(struct protoent *, getprotobyname, const char *name)
2175 {
2176   struct protoent *buf;
2177   MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
2178                      "getprotobyname name");
2179   buf = getprotobyname (name);
2180   if (buf != NULL)
2181     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2182                    "getproto*() return");
2183   return buf;
2184 }
2185 #endif
2186
2187
2188 #ifdef HAVE_GETPROTOBYNUMBER
2189 WRAPPER2(struct protoent *, getprotobynumber, int port)
2190 {
2191   struct protoent *buf;
2192   buf = getprotobynumber (port);
2193   if (buf != NULL)
2194     __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
2195                    "getproto*() return");
2196   return buf;
2197 }
2198 #endif