]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - misc.c
first pass
[PuTTY.git] / misc.c
diff --git a/misc.c b/misc.c
index b1bfb36176fab38832a9244e03e8422620bc8cbf..9aff234b9fdde6c04527c2b79db32ef02e1122e4 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -394,25 +394,23 @@ int toint(unsigned u)
  *    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;
+    int len, size, newsize;
+
+    assert(*oldsize >= oldlen);
+    size = *oldsize - oldlen;
+    if (size == 0) {
+        size = 512;
+        newsize = oldlen + size;
+        buf = sresize(buf, newsize, char);
+    } else {
+        newsize = *oldsize;
+    }
 
     while (1) {
-#ifdef _WINDOWS
+#if defined _WINDOWS && !defined __WINE__ && _MSC_VER < 1900 /* 1900 == VS2015 has real snprintf */
 #define vsnprintf _vsnprintf
 #endif
 #ifdef va_copy
@@ -420,7 +418,7 @@ char *dupvprintf(const char *fmt, va_list ap)
         * 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.
@@ -431,11 +429,12 @@ char *dupvprintf(const char *fmt, va_list ap)
         * (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
             * been completely successful. */
+            *oldsize = newsize;
            return buf;
        } else if (len > 0) {
            /* This is the C99 error condition: the returned length is
@@ -446,10 +445,67 @@ char *dupvprintf(const char *fmt, va_list ap)
             * buffer wasn't big enough, so we enlarge it a bit and hope. */
            size += 512;
        }
-       buf = sresize(buf, size, char);
+        newsize = oldlen + size;
+        buf = sresize(buf, newsize, char);
     }
 }
 
+char *dupvprintf(const char *fmt, va_list ap)
+{
+    int size = 0;
+    return dupvprintf_inner(NULL, 0, &size, 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).
@@ -460,7 +516,7 @@ char *fgetline(FILE *fp)
     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);
@@ -1064,12 +1120,12 @@ int match_ssh_id(int stringlen, const void *string, const char *id)
 void *get_ssh_string(int *datalen, const void **data, int *stringlen)
 {
     void *ret;
-    int len;
+    unsigned int len;
 
     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;
@@ -1087,3 +1143,90 @@ int get_ssh_uint32(int *datalen, const void **data, unsigned *ret)
     *data = (const char *)*data + 4;
     return TRUE;
 }
+
+int strstartswith(const char *s, const char *t)
+{
+    return !memcmp(s, t, strlen(t));
+}
+
+int strendswith(const char *s, const char *t)
+{
+    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 BUILDINFO_GTK
+    {
+        char *gtk_buildinfo = buildinfo_gtk_version();
+        if (gtk_buildinfo) {
+            strbuf_catf(buf, "%sCompiled against GTK version %s",
+                        newline, gtk_buildinfo);
+            sfree(gtk_buildinfo);
+        }
+    }
+#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);
+}