Portable build framework for OpenNTPD
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.3 KiB

  1. /*
  2. * Copyright (c) 2004 Darren Tucker.
  3. *
  4. * Based originally on asprintf.c from OpenBSD:
  5. * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
  6. *
  7. * Permission to use, copy, modify, and distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #ifndef HAVE_ASPRINTF
  20. #include <errno.h>
  21. #include <limits.h> /* for INT_MAX */
  22. #include <stdarg.h>
  23. #include <stdio.h> /* for vsnprintf */
  24. #include <stdlib.h>
  25. #ifndef VA_COPY
  26. # ifdef HAVE_VA_COPY
  27. # define VA_COPY(dest, src) va_copy(dest, src)
  28. # else
  29. # ifdef HAVE___VA_COPY
  30. # define VA_COPY(dest, src) __va_copy(dest, src)
  31. # else
  32. # define VA_COPY(dest, src) (dest) = (src)
  33. # endif
  34. # endif
  35. #endif
  36. #define INIT_SZ 128
  37. int
  38. vasprintf(char **str, const char *fmt, va_list ap)
  39. {
  40. int ret;
  41. va_list ap2;
  42. char *string, *newstr;
  43. size_t len;
  44. if ((string = malloc(INIT_SZ)) == NULL)
  45. goto fail;
  46. VA_COPY(ap2, ap);
  47. ret = vsnprintf(string, INIT_SZ, fmt, ap2);
  48. va_end(ap2);
  49. if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
  50. *str = string;
  51. } else if (ret == INT_MAX || ret < 0) { /* Bad length */
  52. free(string);
  53. goto fail;
  54. } else { /* bigger than initial, realloc allowing for nul */
  55. len = (size_t)ret + 1;
  56. if ((newstr = realloc(string, len)) == NULL) {
  57. free(string);
  58. goto fail;
  59. }
  60. VA_COPY(ap2, ap);
  61. ret = vsnprintf(newstr, len, fmt, ap2);
  62. va_end(ap2);
  63. if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */
  64. free(newstr);
  65. goto fail;
  66. }
  67. *str = newstr;
  68. }
  69. return (ret);
  70. fail:
  71. *str = NULL;
  72. errno = ENOMEM;
  73. return (-1);
  74. }
  75. int asprintf(char **str, const char *fmt, ...)
  76. {
  77. va_list ap;
  78. int ret;
  79. *str = NULL;
  80. va_start(ap, fmt);
  81. ret = vasprintf(str, fmt, ap);
  82. va_end(ap);
  83. return ret;
  84. }
  85. #endif