Postfix3.3.1
readlline.c
[詳解]
1 /*++
2 /* NAME
3 /* readlline 3
4 /* SUMMARY
5 /* read logical line
6 /* SYNOPSIS
7 /* #include <readlline.h>
8 /*
9 /* VSTRING *readllines(buf, fp, lineno, first_line)
10 /* VSTRING *buf;
11 /* VSTREAM *fp;
12 /* int *lineno;
13 /* int *first_line;
14 /*
15 /* VSTRING *readlline(buf, fp, lineno)
16 /* VSTRING *buf;
17 /* VSTREAM *fp;
18 /* int *lineno;
19 /* DESCRIPTION
20 /* readllines() reads one logical line from the named stream.
21 /* .IP "blank lines and comments"
22 /* Empty lines and whitespace-only lines are ignored, as
23 /* are lines whose first non-whitespace character is a `#'.
24 /* .IP "multi-line text"
25 /* A logical line starts with non-whitespace text. A line that
26 /* starts with whitespace continues a logical line.
27 /* .PP
28 /* The result value is the input buffer argument or a null pointer
29 /* when no input is found.
30 /*
31 /* readlline() is a backwards-compatibility wrapper.
32 /*
33 /* Arguments:
34 /* .IP buf
35 /* A variable-length buffer for input. The result is null terminated.
36 /* .IP fp
37 /* Handle to an open stream.
38 /* .IP lineno
39 /* A null pointer, or a pointer to an integer that is incremented
40 /* after reading a physical line.
41 /* .IP first_line
42 /* A null pointer, or a pointer to an integer that will contain
43 /* the line number of the first non-blank, non-comment line
44 /* in the result logical line.
45 /* DIAGNOSTICS
46 /* Warning: a continuation line that does not continue preceding text.
47 /* The invalid input is ignored, to avoid complicating caller code.
48 /* SECURITY
49 /* .ad
50 /* .fi
51 /* readlline() imposes no logical line length limit therefore it
52 /* should be used for reading trusted information only.
53 /* LICENSE
54 /* .ad
55 /* .fi
56 /* The Secure Mailer license must be distributed with this software.
57 /* AUTHOR(S)
58 /* Wietse Venema
59 /* IBM T.J. Watson Research
60 /* P.O. Box 704
61 /* Yorktown Heights, NY 10598, USA
62 /*--*/
63 
64 /* System library. */
65 
66 #include <sys_defs.h>
67 #include <ctype.h>
68 
69 /* Utility library. */
70 
71 #include "msg.h"
72 #include "vstream.h"
73 #include "vstring.h"
74 #include "readlline.h"
75 
76 #define STR(x) vstring_str(x)
77 #define LEN(x) VSTRING_LEN(x)
78 #define END(x) vstring_end(x)
79 
80 /* readllines - read one logical line */
81 
82 VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
83 {
84  int ch;
85  int next;
86  ssize_t start;
87  char *cp;
88 
89  VSTRING_RESET(buf);
90 
91  /*
92  * Ignore comment lines, all whitespace lines, and empty lines. Terminate
93  * at EOF or at the beginning of the next logical line.
94  */
95  for (;;) {
96  /* Read one line, possibly not newline terminated. */
97  start = LEN(buf);
98  while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
99  VSTRING_ADDCH(buf, ch);
100  if (lineno != 0 && (ch == '\n' || LEN(buf) > start))
101  *lineno += 1;
102  /* Ignore comment line, all whitespace line, or empty line. */
103  for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++)
104  /* void */ ;
105  if (cp == END(buf) || *cp == '#')
106  vstring_truncate(buf, start);
107  else if (start == 0 && lineno != 0 && first_line != 0)
108  *first_line = *lineno;
109  /* Terminate at EOF or at the beginning of the next logical line. */
110  if (ch == VSTREAM_EOF)
111  break;
112  if (LEN(buf) > 0) {
113  if ((next = VSTREAM_GETC(fp)) != VSTREAM_EOF)
114  vstream_ungetc(fp, next);
115  if (next != '#' && !ISSPACE(next))
116  break;
117  }
118  }
119  VSTRING_TERMINATE(buf);
120 
121  /*
122  * Invalid input: continuing text without preceding text. Allowing this
123  * would complicate "postconf -e", which implements its own multi-line
124  * parsing routine. Do not abort, just warn, so that critical programs
125  * like postmap do not leave behind a truncated table.
126  */
127  if (LEN(buf) > 0 && ISSPACE(*STR(buf))) {
128  msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"",
129  VSTREAM_PATH(fp), STR(buf),
130  LEN(buf) > 30 ? "..." : "");
131  return (readllines(buf, fp, lineno, first_line));
132  }
133 
134  /*
135  * Done.
136  */
137  return (LEN(buf) > 0 ? buf : 0);
138 }
#define VSTREAM_EOF
Definition: vstream.h:110
#define STR(x)
Definition: readlline.c:76
#define LEN(x)
Definition: readlline.c:77
#define VSTREAM_GETC(vp)
Definition: vstream.h:108
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
Definition: vstring.c:415
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define vstream_ungetc(vp, ch)
Definition: vstream.h:109
#define VSTRING_RESET(vp)
Definition: vstring.h:77
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
Definition: readlline.c:82
#define ISSPACE(c)
Definition: sys_defs.h:1753
#define END(x)
Definition: readlline.c:78