OSDN Git Service

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