3
* cfgfile.c - configuration and job file parsing
5
* Copyright © 2006 Canonical Ltd.
6
* Author: Scott James Remnant <scott@ubuntu.com>.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
#endif /* HAVE_CONFIG_H */
30
#include <nih/macros.h>
31
#include <nih/alloc.h>
32
#include <nih/logging.h>
33
#include <nih/error.h>
41
* Definition of what characters we consider whitespace.
46
/* Prototypes for static functions */
47
static char * cfg_read_script (void *parent, const char *file,
48
ssize_t len, ssize_t *pos)
49
static ssize_t cfg_script_end (const char *file, ssize_t len, ssize_t *pos);
54
* @parent: parent of returned string,
55
* @file: memory mapped copy of file, or string buffer,
56
* @len: length of @file,
57
* @pos: position to read from.
59
* @pos should point to the start of the entire script fragment, including
62
* @pos is updated to point to the next line in the configuration or will be
63
* past the end of the file.
65
* Returns: the script contained in the fragment or %NULL if the end could
66
* not be found before the end of file.
69
cfg_read_script (void *parent,
75
ssize_t sh_start, sh_end, sh_len, ws, p;
78
nih_assert (file != NULL);
80
nih_assert (pos != NULL);
82
/* Find the start of the script proper */
83
while ((*pos < len) && (file[*pos] != '\n'))
86
/* Step over the newline */
93
/* Ok, we found the start of the script. We now need to find the end
94
* of the script which is a line that looks like:
96
* WS end WS script (WS COMMENT?)?
98
* Just to make things more difficult for ourselves, we work out the
99
* common whitespace on the start of the script lines and remember
100
* not to copy those out later
107
while ((sh_end = cfg_script_end (file, len, pos)) < 0) {
113
/* Count initial whitespace */
114
while ((*pos < len) && strchr (WS, file[*pos]))
117
ws = *pos - line_start;
119
/* Compare how much whitespace matches the
120
* first line; and decrease the count if it's
123
while ((*pos < len) && (*pos - line_start < ws)
124
&& (file[sh_start + *pos - line_start]
128
if (*pos - line_start < ws)
129
ws = *pos - line_start;
132
/* Find the end of the line */
133
while ((*pos < len) && (file[*pos] != '\n'))
136
/* Step over the newline */
146
* Copy the fragment into a string, removing common whitespace from
147
* the start. We can be less strict here because we already know
151
sh_len = sh_end - sh_start - (ws * lines);
152
NIH_MUST (script = nih_alloc (parent, sh_len + 1));
162
while (file[p++] != '\n')
165
strncat (script, file + line_start, p - line_start);
173
* @file: memory mapped copy of file, or string buffer,
174
* @len: length of @file,
175
* @pos: position to read from.
177
* Determines whether the current line is an end-of-script marker.
179
* @pos is updated to point to the next line in configuration or past the
182
* Returns: index of script end (always the value of @pos at the time this
183
* function was called) or -1 if it is not on this line.
186
cfg_script_end (const char *file,
192
nih_assert (file != NULL);
193
nih_assert (len > 0);
194
nih_assert (pos != NULL);
198
/* Skip initial whitespace */
199
while ((p < len) && strchr (WS, file[p]))
202
/* Check the first word (check we have at least 4 chars because of
203
* the need for whitespace immediately after)
205
if ((len - p < 4) || strncmp (file + p, "end", 3))
208
/* Must be whitespace after */
209
if (! strchr (WS, file[p + 3]))
212
/* Find the second word */
214
while ((p < len) && strchr (WS, file[p]))
217
/* Check the second word */
218
if ((len - p < 6) || strncmp (file + p, "script", 6))
221
/* May be followed by whitespace */
223
while ((p < len) && strchr (WS, file[p]))
226
/* May be a comment, in which case eat up to the
229
if ((p < len) && (file[p] == '#')) {
230
while ((p < len) && (file[p] != '\n'))
234
/* Should be end of string, or a newline */
235
if ((p < len) && (file[p] != '\n'))
238
/* Point past the new line */
242
/* Return the beginning of the line (which is the end of the script)
243
* but update pos to point past this line.