From: Todd C. Miller <Todd.Miller@courtesan.com>
Date: Thu, 18 Mar 2010 10:42:17 +0000 (-0400)
Subject: Pass in output function to lbuf_init() instead of writing to stdout.
X-Git-Tag: SUDO_1_8_0~795
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b4f4afdf6931732227370e2827ca68bd3a4a4cd3;p=sudo

Pass in output function to lbuf_init() instead of writing to stdout.
A side effect is that the usage info can now go to stderr as it should.
---

diff --git a/include/lbuf.h b/include/lbuf.h
index 302918aad..1a8e6dfda 100644
--- a/include/lbuf.h
+++ b/include/lbuf.h
@@ -23,18 +23,19 @@
  * Line buffer struct.
  */
 struct lbuf {
+    int (*output)(const char *);
     char *buf;
-    int continuation;
+    const char *continuation;
     int indent;
     int len;
     int size;
     int cols;
 };
 
-void lbuf_init		(struct lbuf *, char *, int, int, int);
-void lbuf_destroy	(struct lbuf *);
-void lbuf_append	(struct lbuf *, ...);
-void lbuf_append_quoted	(struct lbuf *, const char *, ...);
-void lbuf_print		(struct lbuf *);
+void lbuf_init(struct lbuf *, int (*)(const char *), int, const char *, int);
+void lbuf_destroy(struct lbuf *);
+void lbuf_append(struct lbuf *, ...);
+void lbuf_append_quoted(struct lbuf *, const char *, ...);
+void lbuf_print(struct lbuf *);
 
 #endif /* _SUDO_LBUF_H */
diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c
index 707c5cc87..94ca3bb35 100644
--- a/plugins/sudoers/auth/sudo_auth.c
+++ b/plugins/sudoers/auth/sudo_auth.c
@@ -52,8 +52,6 @@
 #include "sudo_auth.h"
 #include "insults.h"
 
-sudo_conv_t sudo_conv;
-
 sudo_auth auth_switch[] = {
 #ifdef AUTH_STANDALONE
     AUTH_STANDALONE
diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c
index f913ff667..161d86e5d 100644
--- a/plugins/sudoers/check.c
+++ b/plugins/sudoers/check.c
@@ -75,8 +75,6 @@ static char *expand_prompt(char *, char *, char *);
 static void  lecture(int);
 static void  update_timestamp(char *, char *);
 
-extern sudo_conv_t sudo_conv;
-
 /*
  * This function only returns if the user can successfully
  * verify who he/she is.
diff --git a/plugins/sudoers/sudo_nss.c b/plugins/sudoers/sudo_nss.c
index c6e905a4e..df8509c1a 100644
--- a/plugins/sudoers/sudo_nss.c
+++ b/plugins/sudoers/sudo_nss.c
@@ -224,10 +224,27 @@ reset_groups(pw)
 #endif
 }
 
+static int
+output(const char *buf)
+{
+    struct sudo_conv_message msg;
+    struct sudo_conv_reply repl;
+
+    /* Call conversation function */
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_type = SUDO_CONV_INFO_MSG;
+    msg.msg = buf;
+    memset(&repl, 0, sizeof(repl));
+    if (sudo_conv(1, &msg, &repl) == -1)
+	return 0;
+    return (int)strlen(buf);
+}
+
 /*
  * Print out privileges for the specified user.
  * We only get here if the user is allowed to run something on this host.
  */
+/* XXX - conversation function or newlines in lbuf */
 void
 display_privs(snl, pw)
     struct sudo_nss_list *snl;
@@ -240,7 +257,7 @@ display_privs(snl, pw)
     /* Reset group vector so group matching works correctly. */
     reset_groups(pw);
 
-    lbuf_init(&lbuf, NULL, 4, 0, sudo_user.cols);
+    lbuf_init(&lbuf, output, 4, NULL, sudo_user.cols);
 
     /* Display defaults from all sources. */
     count = 0;
diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c
index 7820135a2..986cef6cd 100644
--- a/plugins/sudoers/sudoers.c
+++ b/plugins/sudoers/sudoers.c
@@ -152,6 +152,8 @@ login_cap_t *lc;
 char *login_style;
 #endif /* HAVE_BSD_AUTH_H */
 sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp;
+sudo_conv_t sudo_conv;
+
 static char *runas_user;
 static char *runas_group;
 static struct sudo_nss_list *snl;
diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h
index 46a3c7847..19ac90131 100644
--- a/plugins/sudoers/sudoers.h
+++ b/plugins/sudoers/sudoers.h
@@ -307,6 +307,7 @@ extern struct passwd *auth_pw, *list_pw;
 extern int tgetpass_flags; /* XXX */
 extern int long_list;
 extern uid_t timestamp_uid;
+extern sudo_conv_t sudo_conv;
 #endif
 #ifndef errno
 extern int errno;
diff --git a/src/lbuf.c b/src/lbuf.c
index 148278ded..4a7437ebe 100644
--- a/src/lbuf.c
+++ b/src/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
@@ -58,8 +58,10 @@
  */
 
 void
-lbuf_init(struct lbuf *lbuf, char *buf, int indent, int continuation, int cols)
+lbuf_init(struct lbuf *lbuf, int (*output)(const char *),
+    int indent, const char *continuation, int cols)
 {
+    lbuf->output = output;
     lbuf->continuation = continuation;
     lbuf->indent = indent;
     lbuf->cols = cols;
@@ -163,10 +165,10 @@ lbuf_append(struct lbuf *lbuf, ...)
 void
 lbuf_print(struct lbuf *lbuf)
 {
-    char *cp;
+    char *cp, save;
     int i, have, contlen;
 
-    contlen = lbuf->continuation ? 2 : 0;
+    contlen = lbuf->continuation ? strlen(lbuf->continuation) : 0;
 
     /* For very small widths just give up... */
     if (lbuf->cols <= lbuf->indent + contlen + 20) {
@@ -198,9 +200,13 @@ lbuf_print(struct lbuf *lbuf)
 	if (cp != lbuf->buf) {
 	    /* indent continued lines */
 	    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;
 
 	/*
@@ -212,12 +218,10 @@ lbuf_print(struct lbuf *lbuf)
 	    do {
 		cp++;
 	    } while (isspace((unsigned char)*cp));
-	    if (lbuf->continuation) {
-		putchar(' ');
-		putchar(lbuf->continuation);
-	    }
+	    if (contlen)
+		lbuf->output(lbuf->continuation);
 	}
-	putchar('\n');
+	lbuf->output("\n");
     }
 
 done:
diff --git a/src/parse_args.c b/src/parse_args.c
index 41d0ed5cd..e970a9f04 100644
--- a/src/parse_args.c
+++ b/src/parse_args.c
@@ -373,6 +373,12 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
     return(mode | flags);
 }
 
+static int
+usage_out(const char *buf)
+{
+    return fputs(buf, stderr);
+}
+
 /*
  * Give usage message and exit.
  * The actual usage strings are in sudo_usage.h for configure substitution.
@@ -404,7 +410,7 @@ usage(int exit_val)
      * tty width.
      */
     ulen = (int)strlen(getprogname()) + 8;
-    lbuf_init(&lbuf, NULL, ulen, 0, user_details.ts_cols);
+    lbuf_init(&lbuf, usage_out, ulen, NULL, user_details.ts_cols);
     for (i = 0; uvec[i] != NULL; i++) {
 	lbuf_append(&lbuf, "usage: ", getprogname(), uvec[i], NULL);
 	lbuf_print(&lbuf);