asprintf.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:3k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: asprintf.c,v $
  4.  * PRODUCTION Revision 1000.0  2003/10/29 20:34:23  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [ORIGINAL] Dev-tree R1.3
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*
  10.  * vasprintf(3), asprintf(3)
  11.  * 20020809 entropy@tappedin.com
  12.  * public domain.  no warranty.  use at your own risk.  have a nice day.
  13.  *
  14.  * Assumes that mprotect(2) granularity is one page.  May need adjustment
  15.  * on systems with unusual protection semantics.
  16.  */
  17. #include <tds_config.h>
  18. #if !HAVE_VASPRINTF
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <stdarg.h>
  22. #include <unistd.h>
  23. #include <string.h>
  24. #ifndef _REENTRANT
  25. #include <sys/mman.h>
  26. #include <setjmp.h>
  27. #include <signal.h>
  28. #include <assert.h>
  29. #endif
  30. static char  software_version[]   = "$Id: asprintf.c,v 1000.0 2003/10/29 20:34:23 gouriano Exp $";
  31. static void *no_unused_var_warn[] = {software_version,
  32.                                      no_unused_var_warn};
  33. #ifndef _REENTRANT
  34. static jmp_buf env;
  35. static void
  36. sigsegv(int sig)
  37. {
  38.   longjmp(env, 1);
  39. }
  40. #endif
  41. int
  42. vasprintf(char **ret, const char *fmt, va_list ap)
  43. {
  44. #ifdef _REENTRANT
  45.   FILE *fp;
  46.   int len;
  47.   char *buf;
  48.   *ret = NULL;
  49.   if ((fp = fopen("/dev/null", "w")) == NULL)
  50.     return -1;
  51.   len = vfprintf(fp, fmt, ap);
  52.   if (fclose(fp) != 0)
  53.     return -1;
  54.   if (len < 0)
  55.     return len;
  56.   if ((buf = malloc(len + 1)) == NULL)
  57.     return -1;
  58.   vsprintf(buf, fmt, ap);
  59.   *ret = buf;
  60.   return len;
  61. #else
  62. # ifndef _SC_PAGE_SIZE
  63. #  define _SC_PAGE_SIZE _SC_PAGESIZE
  64. # endif
  65.   volatile char *buf = NULL;
  66.   volatile unsigned int pgs;
  67.   struct sigaction sa, osa;
  68.   int len;
  69. #ifdef HAVE_GETPAGESIZE
  70.   long pgsize = getpagesize();
  71. #else
  72.   long pgsize = sysconf(_SC_PAGE_SIZE);
  73. #endif
  74.   pgs = ((strlen(fmt) + 1) / pgsize) + 1;
  75.   if (sigaction(SIGSEGV, NULL, &osa)) {
  76.     *ret = NULL;
  77.     return -1;
  78.   }
  79.   sa.sa_handler = sigsegv;
  80.   sigemptyset(&sa.sa_mask);
  81.   sa.sa_flags = 0;
  82.   if (setjmp(env) != 0) {
  83.     mprotect((void *) (buf + pgs * pgsize), pgsize, PROT_READ|PROT_WRITE);
  84.     free((void *) buf);
  85.     pgs++;
  86.   }
  87.   if ((buf = valloc((pgs + 1) * pgsize)) == NULL) {
  88.     *ret = NULL;
  89.     return -1;
  90.   }
  91.   assert(((unsigned long) buf % pgsize) == 0);
  92.   if (sigaction(SIGSEGV, &sa, NULL)) {
  93.     free((void *) buf);
  94.     *ret = NULL;
  95.     return -1;
  96.   }
  97.   mprotect((void *) (buf + pgs * pgsize), pgsize, PROT_NONE);
  98.   len = vsprintf((void *) buf, fmt, ap);
  99.   mprotect((void *) (buf + pgs * pgsize), pgsize, PROT_READ|PROT_WRITE);
  100.   if (sigaction(SIGSEGV, &osa, NULL)) {
  101.     free((void *) buf);
  102.     *ret = NULL;
  103.     return -1;
  104.   }
  105.   if (len < 0) {
  106.     free((void *) buf);
  107.     *ret = NULL;
  108.     return len;
  109.   }
  110.   if ((buf = realloc((void *) buf, len + 1)) == NULL) {
  111.     *ret = NULL;
  112.     return -1;
  113.   }
  114.   *ret = (char *) buf;
  115.   return len;
  116. #endif
  117. }
  118. int
  119. asprintf(char **ret, const char *fmt, ...)
  120. {
  121.   int len;
  122.   va_list ap;
  123.   va_start(ap, fmt);
  124.   len = vasprintf(ret, fmt, ap);
  125.   va_end(ap);
  126.   return len;
  127. }
  128. #endif /* HAVE_VASPRINTF */