* directive we don't know about, we should panic and die rather
* than run any risk.
*/
-char *dupprintf(const char *fmt, ...)
-{
- char *ret;
- va_list ap;
- va_start(ap, fmt);
- ret = dupvprintf(fmt, ap);
- va_end(ap);
- return ret;
-}
-char *dupvprintf(const char *fmt, va_list ap)
+static char *dupvprintf_inner(char *buf, int oldlen, int oldsize,
+ const char *fmt, va_list ap)
{
- char *buf;
int len, size;
- buf = snewn(512, char);
- size = 512;
+ size = oldsize - oldlen;
+ if (size == 0) {
+ size = 512;
+ buf = sresize(buf, oldlen + size, char);
+ }
while (1) {
-#ifdef _WINDOWS
+#if defined _WINDOWS && !defined __WINE__ && _MSC_VER < 1900 /* 1900 == VS2015 has real snprintf */
#define vsnprintf _vsnprintf
#endif
#ifdef va_copy
* XXX some environments may have this as __va_copy() */
va_list aq;
va_copy(aq, ap);
- len = vsnprintf(buf, size, fmt, aq);
+ len = vsnprintf(buf + oldlen, size, fmt, aq);
va_end(aq);
#else
/* Ugh. No va_copy macro, so do something nasty.
* (indeed, it has been observed to).
* XXX the autoconf manual suggests that using memcpy() will give
* "maximum portability". */
- len = vsnprintf(buf, size, fmt, ap);
+ len = vsnprintf(buf + oldlen, size, fmt, ap);
#endif
if (len >= 0 && len < size) {
/* This is the C99-specified criterion for snprintf to have
* buffer wasn't big enough, so we enlarge it a bit and hope. */
size += 512;
}
- buf = sresize(buf, size, char);
+ buf = sresize(buf, oldlen + size, char);
}
}
+char *dupvprintf(const char *fmt, va_list ap)
+{
+ return dupvprintf_inner(NULL, 0, 0, fmt, ap);
+}
+char *dupprintf(const char *fmt, ...)
+{
+ char *ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = dupvprintf(fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+struct strbuf {
+ char *s;
+ int len, size;
+};
+strbuf *strbuf_new(void)
+{
+ strbuf *buf = snew(strbuf);
+ buf->len = 0;
+ buf->size = 512;
+ buf->s = snewn(buf->size, char);
+ *buf->s = '\0';
+ return buf;
+}
+void strbuf_free(strbuf *buf)
+{
+ sfree(buf->s);
+ sfree(buf);
+}
+char *strbuf_str(strbuf *buf)
+{
+ return buf->s;
+}
+char *strbuf_to_str(strbuf *buf)
+{
+ char *ret = buf->s;
+ sfree(buf);
+ return ret;
+}
+void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap)
+{
+ buf->s = dupvprintf_inner(buf->s, buf->len, buf->size, fmt, ap);
+ buf->len += strlen(buf->s + buf->len);
+}
+void strbuf_catf(strbuf *buf, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ strbuf_catfv(buf, fmt, ap);
+ va_end(ap);
+}
+
/*
* Read an entire line of text from a file. Return a buffer
* malloced to be as big as necessary (caller must free).
int size = 512, len = 0;
while (fgets(ret + len, size - len, fp)) {
len += strlen(ret + len);
- if (ret[len-1] == '\n')
+ if (len > 0 && ret[len-1] == '\n')
break; /* got a newline, we're done */
size = len + 512;
ret = sresize(ret, size, char);
if (*datalen < 4)
return NULL;
len = GET_32BIT_MSB_FIRST((const unsigned char *)*data);
- if (*datalen < len+4)
+ if (*datalen - 4 < len)
return NULL;
ret = (void *)((const char *)*data + 4);
*datalen -= len + 4;
size_t slen = strlen(s), tlen = strlen(t);
return slen >= tlen && !strcmp(s + (slen - tlen), t);
}
+
+char *buildinfo(const char *newline)
+{
+ strbuf *buf = strbuf_new();
+ extern const char commitid[]; /* in commitid.c */
+
+ strbuf_catf(buf, "Build platform: %d-bit %s",
+ (int)(CHAR_BIT * sizeof(void *)),
+ BUILDINFO_PLATFORM);
+
+#ifdef __clang_version__
+ strbuf_catf(buf, "%sCompiler: clang %s", newline, __clang_version__);
+#elif defined __GNUC__ && defined __VERSION__
+ strbuf_catf(buf, "%sCompiler: gcc %s", newline, __VERSION__);
+#elif defined _MSC_VER
+ strbuf_catf(buf, "%sCompiler: Visual Studio", newline);
+#if _MSC_VER == 1900
+ strbuf_catf(buf, " 2015 / MSVC++ 14.0");
+#elif _MSC_VER == 1800
+ strbuf_catf(buf, " 2013 / MSVC++ 12.0");
+#elif _MSC_VER == 1700
+ strbuf_catf(buf, " 2012 / MSVC++ 11.0");
+#elif _MSC_VER == 1600
+ strbuf_catf(buf, " 2010 / MSVC++ 10.0");
+#elif _MSC_VER == 1500
+ strbuf_catf(buf, " 2008 / MSVC++ 9.0");
+#elif _MSC_VER == 1400
+ strbuf_catf(buf, " 2005 / MSVC++ 8.0");
+#elif _MSC_VER == 1310
+ strbuf_catf(buf, " 2003 / MSVC++ 7.1");
+#else
+ strbuf_catf(buf, ", unrecognised version");
+#endif
+ strbuf_catf(buf, " (_MSC_VER=%d)", (int)_MSC_VER);
+#endif
+
+#ifdef NO_SECURITY
+ strbuf_catf(buf, "%sBuild option: NO_SECURITY", newline);
+#endif
+#ifdef NO_SECUREZEROMEMORY
+ strbuf_catf(buf, "%sBuild option: NO_SECUREZEROMEMORY", newline);
+#endif
+#ifdef NO_IPV6
+ strbuf_catf(buf, "%sBuild option: NO_IPV6", newline);
+#endif
+#ifdef NO_GSSAPI
+ strbuf_catf(buf, "%sBuild option: NO_GSSAPI", newline);
+#endif
+#ifdef STATIC_GSSAPI
+ strbuf_catf(buf, "%sBuild option: STATIC_GSSAPI", newline);
+#endif
+#ifdef UNPROTECT
+ strbuf_catf(buf, "%sBuild option: UNPROTECT", newline);
+#endif
+#ifdef FUZZING
+ strbuf_catf(buf, "%sBuild option: FUZZING", newline);
+#endif
+#ifdef DEBUG
+ strbuf_catf(buf, "%sBuild option: DEBUG", newline);
+#endif
+
+ strbuf_catf(buf, "%sSource commit: %s", newline, commitid);
+
+ return strbuf_to_str(buf);
+}