OSSP CVS Repository

ossp - Difference in ossp-pkg/sa/sa.c versions 1.26 and 1.27
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/sa/sa.c 1.26 -> 1.27

--- sa.c 2001/10/10 07:42:26     1.26
+++ sa.c 2001/10/10 09:05:18     1.27
@@ -248,62 +248,117 @@
 #endif
 }
 
-/* minimal vsnprintf(3) variant which supports %{c,s,d} only */
-static int sa_mvsnprintf(char *buffer, size_t bufsize, const char *format, va_list ap)
+/* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */
+static int sa_mvxprintf(int (*output)(void *ctx, const char *buffer, size_t bufsize), void *ctx, const char *format, va_list ap)
 {
-    char *bufptr;
-    char *bufend;
     /* sufficient integer buffer: <available-bits> x log_10(2) + safety */
     char ibuf[((sizeof(int)*8)/3)+10]; 
     char *cp;
     char c;
     int d;
     int n;
+    int bytes;
 
-    bufptr = buffer;
-    bufend = buffer + bufsize - 1;
-    while ((c = *format++) != '\0' && bufptr < bufend) {
-        if (c == '%') {
-            c = *format++;
-            if (c == '%')
-                /* implement "%%" */
-                *bufptr++ = c;
-            else if (c == 'c')
-                /* implement "%c" */
-                *bufptr++ = (char)va_arg(ap, int);
+    if (format == NULL || ap == NULL)
+        return -1;
+    bytes = 0;
+    while (*format != '\0') {
+        if (*format == '%') {
+            c = *(format+1);
+            if (c == '%') {
+                /* expand "%%" */
+                cp = &c;
+                n = sizeof(char);
+            }
+            else if (c == 'c') {
+                /* expand "%c" */
+                c = (char)va_arg(ap, int);
+                cp = &c;
+                n = sizeof(char);
+            }
             else if (c == 's') {
-                /* implement "%s" */
+                /* expand "%s" */
                 if ((cp = (char *)va_arg(ap, char *)) == NULL)
                     cp = "(null)";
                 n = strlen(cp);
-                if ((bufptr + n) > bufend)
-                    n = bufend - bufptr;
-                memcpy(bufptr, cp, n);
-                bufptr += n;
             }
             else if (c == 'd') {
-                /* implement "%d" */
+                /* expand "%d" */
                 d = (int)va_arg(ap, int);
 #ifdef HAVE_SNPRINTF
                 snprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */
 #else
                 sprintf(ibuf, "%d", d);                /* implicitly secure */
 #endif
-                n = strlen(ibuf);
-                memcpy(bufptr, ibuf, n);
-                bufptr += n;
+                cp = ibuf;
+                n = strlen(cp);
             }
             else {
-                *bufptr++ = '%';
-                if (bufptr < bufend)
-                    *bufptr++ = c;
+                /* any other "%X" */
+                cp = (char *)format;
+                n  = 2;
             }
+            format += 2;
         }
-        else
-            *bufptr++ = c;
+        else {
+            /* plain text */
+            cp = (char *)format;
+            if ((format = strchr(cp, '%')) == NULL)
+                format = strchr(cp, '\0');
+            n = format - cp;
+        }
+        /* perform output operation */
+        if (output != NULL)
+            if ((n = output(ctx, cp, n)) == -1)
+                break;
+        bytes += n;
     }
-    *bufptr = '\0';
-    return (bufptr - buffer);
+    return bytes;
+}
+
+/* output callback function context for sa_mvsnprintf() */
+typedef struct {
+    char *bufptr;
+    size_t buflen;
+} sa_mvsnprintf_cb_t;
+
+/* output callback function for sa_mvsnprintf() */
+static int sa_mvsnprintf_cb(void *_ctx, const char *buffer, size_t bufsize)
+{
+    sa_mvsnprintf_cb_t *ctx = (sa_mvsnprintf_cb_t *)_ctx;
+
+    if (bufsize > ctx->buflen)
+        return -1;
+    memcpy(ctx->bufptr, buffer, bufsize);
+    ctx->bufptr += bufsize;
+    ctx->buflen -= bufsize;
+    return bufsize;
+}
+
+/* minimal vsnprintf(3) variant which supports %{c,s,d} only */
+static int sa_mvsnprintf(char *buffer, size_t bufsize, const char *format, va_list ap)
+{
+    int n;
+    sa_mvsnprintf_cb_t ctx;
+
+    if (format == NULL || ap == NULL)
+        return -1;
+    if (buffer != NULL && bufsize == 0)
+        return -1;
+    if (buffer == NULL) 
+        /* just determine output length */
+        n = sa_mvxprintf(NULL, NULL, format, ap);
+    else {
+        /* perform real output */
+        ctx.bufptr = buffer;
+        ctx.buflen = bufsize - 1;
+        n = sa_mvxprintf(sa_mvsnprintf_cb, &ctx, format, ap);
+    }
+    if (n != -1 && ctx.buflen == 0)
+        n = -1;
+    if (n != -1)
+        *(ctx.bufptr) = '\0';
+    return n;
 }
 
 /* minimal snprintf(3) variant which supports %{c,s,d} only */
@@ -312,10 +367,6 @@
     int chars;
     va_list ap;
 
-    /* argument sanity check(s) */
-    if (buffer == NULL || bufsize == 0 || format == NULL)
-        return 0;
-
     /* pass through to va_list based variant */
     va_start(ap, format);
     chars = sa_mvsnprintf(buffer, bufsize, format, ap);
@@ -1675,13 +1726,29 @@
     return rv;
 }
 
+/* output callback function context for sa_writef() */
+typedef struct {
+    sa_t *sa;
+    sa_rc_t rv;
+} sa_writef_cb_t;
+
+/* output callback function for sa_writef() */
+static int sa_writef_cb(void *_ctx, const char *buffer, size_t bufsize)
+{
+    size_t n;
+    sa_writef_cb_t *ctx = (sa_writef_cb_t *)_ctx;
+
+    if ((ctx->rv = sa_write(ctx->sa, buffer, bufsize, &n)) != SA_OK)
+        n = -1;
+    return n;
+}
+
 /* write formatted string to socket (convinience function) */
 sa_rc_t sa_writef(sa_t *sa, const char *cpFmt, ...)
 {
     va_list ap;
     size_t n;
-    char caBuf[1024];
-    sa_rc_t rv;
+    sa_writef_cb_t ctx;
 
     /* argument sanity check(s) */
     if (sa == NULL || cpFmt == NULL)
@@ -1697,13 +1764,12 @@
 
     /* format string into temporary buffer */
     va_start(ap, cpFmt);
-    n = sa_mvsnprintf(caBuf, sizeof(caBuf), cpFmt, ap);
+    ctx.sa = sa;
+    ctx.rv = SA_OK;
+    n = sa_mvxprintf(sa_writef_cb, &ctx, cpFmt, ap);
     va_end(ap);
 
-    /* write result buffer to socket */
-    rv = sa_write(sa, caBuf, n, &n);
-
-    return rv;
+    return ctx.rv;
 }
 
 /* flush write/outgoing I/O buffer */

CVSTrac 2.0.1