clean up changelog and tag confusion in my checked out tree
[debian/sudo] / lbuf.c
diff --git a/lbuf.c b/lbuf.c
index 9e6bf0d10b000058d4500526c71e2be194a00761..bd218da873b32cc7ef68cce0245cf230659cff14 100644 (file)
--- a/lbuf.c
+++ b/lbuf.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2009 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2007-2010 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #endif /* STDC_HEADERS */
 #ifdef HAVE_STRING_H
 # include <string.h>
-#else
-# ifdef HAVE_STRINGS_H
-#  include <strings.h>
-# endif
 #endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif /* HAVE_UNISTD_H */
 #include "sudo.h"
 #include "lbuf.h"
 
-#ifndef lint
-__unused static const char rcsid[] = "$Sudo: lbuf.c,v 1.9 2009/05/25 12:02:41 millert Exp $";
-#endif /* lint */
-
 #if !defined(TIOCGSIZE) && defined(TIOCGWINSZ)
 # define TIOCGSIZE     TIOCGWINSZ
 # define ttysize       winsize
@@ -80,19 +75,17 @@ get_ttycols()
     return(cols);
 }
 
-/*
- * TODO: add support for embedded newlines in lbufs
- */
-
 void
-lbuf_init(lbuf, buf, indent, continuation)
+lbuf_init(lbuf, output, indent, continuation)
     struct lbuf *lbuf;
-    char *buf;
+    int (*output)__P((const char *));
     int indent;
-    int continuation;
+    const char *continuation;
 {
+    lbuf->output = output;
     lbuf->continuation = continuation;
     lbuf->indent = indent;
+    lbuf->cols = get_ttycols();
     lbuf->len = 0;
     lbuf->size = 0;
     lbuf->buf = NULL;
@@ -216,37 +209,26 @@ lbuf_append(lbuf, va_alist)
     va_end(ap);
 }
 
-/*
- * Print the buffer with word wrap based on the tty width.
- * The lbuf is reset on return.
- */
-void
-lbuf_print(lbuf)
+static void
+lbuf_println(lbuf, line, len)
     struct lbuf *lbuf;
+    char *line;
+    int len;
 {
-    char *cp;
+    char *cp, save;
     int i, have, contlen;
-    static int cols = -1;
-
-    if (cols == -1)
-       cols = get_ttycols();
-    contlen = lbuf->continuation ? 2 : 0;
 
-    /* For very small widths just give up... */
-    if (cols <= lbuf->indent + contlen + 20) {
-       puts(lbuf->buf);
-       goto done;
-    }
+    contlen = lbuf->continuation ? strlen(lbuf->continuation) : 0;
 
     /*
      * Print the buffer, splitting the line as needed on a word
      * boundary.
      */
-    cp = lbuf->buf;
-    have = cols;
+    cp = line;
+    have = lbuf->cols;
     while (cp != NULL && *cp != '\0') {
        char *ep = NULL;
-       int need = lbuf->len - (int)(cp - lbuf->buf);
+       int need = len - (int)(cp - line);
 
        if (need > have) {
            have -= contlen;            /* subtract for continuation char */
@@ -255,12 +237,17 @@ lbuf_print(lbuf)
            if (ep != NULL)
                need = (int)(ep - cp);
        }
-       if (cp != lbuf->buf) {
+       if (cp != line) {
            /* indent continued lines */
+           /* XXX - build up string instead? */
            for (i = 0; i < lbuf->indent; i++)
-               putchar(' ');
+               lbuf->output(" ");
        }
-       fwrite(cp, need, 1, stdout);
+       /* NUL-terminate cp for the output function and restore afterwards */
+       save = cp[need];
+       cp[need] = '\0';
+       lbuf->output(cp);
+       cp[need] = save;
        cp = ep;
 
        /*
@@ -268,16 +255,49 @@ lbuf_print(lbuf)
         * the whitespace, and print a line continuaton char if needed.
         */
        if (cp != NULL) {
-           have = cols - lbuf->indent;
-           do {
+           have = lbuf->cols - lbuf->indent;
+           ep = line + len;
+           while (cp < ep && isblank((unsigned char)*cp)) {
                cp++;
-           } while (isspace((unsigned char)*cp));
-           if (lbuf->continuation) {
-               putchar(' ');
-               putchar(lbuf->continuation);
            }
+           if (contlen)
+               lbuf->output(lbuf->continuation);
+       }
+       lbuf->output("\n");
+    }
+}
+
+/*
+ * Print the buffer with word wrap based on the tty width.
+ * The lbuf is reset on return.
+ */
+void
+lbuf_print(lbuf)
+    struct lbuf *lbuf;
+{
+    char *cp, *ep;
+    int len, contlen;
+
+    contlen = lbuf->continuation ? strlen(lbuf->continuation) : 0;
+
+    /* For very small widths just give up... */
+    if (lbuf->cols <= lbuf->indent + contlen + 20) {
+       lbuf->output(lbuf->buf);
+       lbuf->output("\n");
+       goto done;
+    }
+
+    /* Print each line in the buffer */
+    for (cp = lbuf->buf; cp != NULL && *cp != '\0'; ) {
+       if (*cp == '\n') {
+           lbuf->output("\n");
+           cp++;
+       } else {
+           ep = memchr(cp, '\n', lbuf->len - (cp - lbuf->buf));
+           len = ep ? (int)(ep - cp) : lbuf->len;
+           lbuf_println(lbuf, cp, len);
+           cp = ep ? ep + 1 : NULL;
        }
-       putchar('\n');
     }
 
 done: