9 /* #include <readlline.h>
11 /* VSTRING *readlline(buf, fp, lineno)
16 /* readlline() reads one logical line from the named stream.
17 /* .IP "blank lines and comments"
18 /* Empty lines and whitespace-only lines are ignored, as
19 /* are lines whose first non-whitespace character is a `#'.
20 /* .IP "multi-line text"
21 /* A logical line starts with non-whitespace text. A line that
22 /* starts with whitespace continues a logical line.
24 /* The result value is the input buffer argument or a null pointer
25 /* when no input is found.
29 /* A variable-length buffer for input. The result is null terminated.
31 /* Handle to an open stream.
33 /* A null pointer, or a pointer to an integer that is incremented
34 /* after reading a newline character.
37 /* Warning: a continuation line that does not continue preceding text.
38 /* The invalid input is ignored, to avoid complicating caller code.
42 /* readlline() imposes no logical line length limit therefore it
43 /* should be used for reading trusted information only.
47 /* The Secure Mailer license must be distributed with this software.
50 /* IBM T.J. Watson Research
52 /* Yorktown Heights, NY 10598, USA
60 /* Utility library. */
65 #include "readlline.h"
67 #define STR(x) vstring_str(x)
68 #define LEN(x) VSTRING_LEN(x)
69 #define END(x) vstring_end(x)
71 /* readlline - read one logical line */
73 VSTRING
*readlline(VSTRING
*buf
, VSTREAM
*fp
, int *lineno
)
83 * Ignore comment lines, all whitespace lines, and empty lines. Terminate
84 * at EOF or at the beginning of the next logical line.
87 /* Read one line, possibly not newline terminated. */
89 while ((ch
= VSTREAM_GETC(fp
)) != VSTREAM_EOF
&& ch
!= '\n')
90 VSTRING_ADDCH(buf
, ch
);
91 if (ch
== '\n' && lineno
!= 0)
93 /* Ignore comment line, all whitespace line, or empty line. */
94 for (cp
= STR(buf
) + start
; cp
< END(buf
) && ISSPACE(*cp
); cp
++)
96 if (cp
== END(buf
) || *cp
== '#')
97 vstring_truncate(buf
, start
);
98 /* Terminate at EOF or at the beginning of the next logical line. */
99 if (ch
== VSTREAM_EOF
)
102 if ((next
= VSTREAM_GETC(fp
)) != VSTREAM_EOF
)
103 vstream_ungetc(fp
, next
);
104 if (next
!= '#' && !ISSPACE(next
))
108 VSTRING_TERMINATE(buf
);
111 * Invalid input: continuing text without preceding text. Allowing this
112 * would complicate "postconf -e", which implements its own multi-line
113 * parsing routine. Do not abort, just warn, so that critical programs
114 * like postmap do not leave behind a truncated table.
116 if (LEN(buf
) > 0 && ISSPACE(*STR(buf
))) {
117 msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"",
118 VSTREAM_PATH(fp
), STR(buf
),
119 LEN(buf
) > 30 ? "..." : "");
120 return (readlline(buf
, fp
, lineno
));
126 return (LEN(buf
) > 0 ? buf
: 0);