1/*	$NetBSD$	*/
2
3/*++
4/* NAME
5/*	postconf_print 3
6/* SUMMARY
7/*	basic line printing support
8/* SYNOPSIS
9/*	#include <postconf.h>
10/*
11/*	void	pcf_print_line(fp, mode, const char *fmt, ...)
12/*	VSTREAM	*fp;
13/*	int	mode;
14/*	const char *fmt;
15/* DESCRIPTION
16/*	pcf_print_line() formats text, normalized whitespace, and
17/*	optionally folds long lines.
18/*
19/*	Arguments:
20/* .IP fp
21/*	Output stream.
22/* .IP mode
23/*	Bit-wise OR of zero or more of the following (other flags
24/*	are ignored):
25/* .RS
26/* .IP PCF_FOLD_LINE
27/*	Fold long lines.
28/* .RE
29/* .IP fmt
30/*	Format string.
31/* DIAGNOSTICS
32/*	Problems are reported to the standard error stream.
33/* LICENSE
34/* .ad
35/* .fi
36/*	The Secure Mailer license must be distributed with this software.
37/* AUTHOR(S)
38/*	Wietse Venema
39/*	IBM T.J. Watson Research
40/*	P.O. Box 704
41/*	Yorktown Heights, NY 10598, USA
42/*--*/
43
44/* System library. */
45
46#include <sys_defs.h>
47#include <string.h>
48#include <stdarg.h>
49
50/* Utility library. */
51
52#include <msg.h>
53#include <vstream.h>
54#include <vstring.h>
55
56/* Application-specific. */
57
58#include <postconf.h>
59
60/* SLMs. */
61
62#define STR(x)	vstring_str(x)
63
64/* pcf_print_line - show line possibly folded, and with normalized whitespace */
65
66void    pcf_print_line(VSTREAM *fp, int mode, const char *fmt,...)
67{
68    va_list ap;
69    static VSTRING *buf = 0;
70    char   *start;
71    char   *next;
72    int     line_len = 0;
73    int     word_len;
74
75    /*
76     * One-off initialization.
77     */
78    if (buf == 0)
79	buf = vstring_alloc(100);
80
81    /*
82     * Format the text.
83     */
84    va_start(ap, fmt);
85    vstring_vsprintf(buf, fmt, ap);
86    va_end(ap);
87
88    /*
89     * Normalize the whitespace. We don't use the line_wrap() routine because
90     * 1) that function does not normalize whitespace between words and 2) we
91     * want to normalize whitespace even when not wrapping lines.
92     *
93     * XXX Some parameters preserve whitespace: for example, smtpd_banner and
94     * smtpd_reject_footer. If we have to preserve whitespace between words,
95     * then perhaps readlline() can be changed to canonicalize whitespace
96     * that follows a newline.
97     */
98    for (start = STR(buf); *(start += strspn(start, PCF_SEPARATORS)) != 0; start = next) {
99	word_len = strcspn(start, PCF_SEPARATORS);
100	if (*(next = start + word_len) != 0)
101	    *next++ = 0;
102	if (word_len > 0 && line_len > 0) {
103	    if ((mode & PCF_FOLD_LINE) == 0
104		|| line_len + word_len < PCF_LINE_LIMIT) {
105		vstream_fputs(" ", fp);
106		line_len += 1;
107	    } else {
108		vstream_fputs("\n" PCF_INDENT_TEXT, fp);
109		line_len = PCF_INDENT_LEN;
110	    }
111	}
112	vstream_fputs(start, fp);
113	line_len += word_len;
114    }
115    vstream_fputs("\n", fp);
116}
117