/*
- * Copyright (c) 2007-2008 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 <ctype.h>
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#else
+# ifdef HAVE_TERMIO_H
+# include <termio.h>
+# endif
+#endif
#include "sudo.h"
#include "lbuf.h"
-#ifndef lint
-__unused static const char rcsid[] = "$Sudo: lbuf.c,v 1.7 2008/12/09 20:55:49 millert Exp $";
-#endif /* lint */
-
#if !defined(TIOCGSIZE) && defined(TIOCGWINSZ)
# define TIOCGSIZE TIOCGWINSZ
# define ttysize winsize
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;
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 */
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;
/*
* 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: