]>
Commit | Line | Data |
---|---|---|
5f0e6fc7 RM |
1 | /* Common code for file-based database parsers in nss_files module. |
2 | Copyright (C) 1996 Free Software Foundation, Inc. | |
3 | This file is part of the GNU C Library. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Library General Public License as | |
7 | published by the Free Software Foundation; either version 2 of the | |
8 | License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with the GNU C Library; see the file COPYING.LIB. If | |
17 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, | |
18 | Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include <ctype.h> | |
21 | #include <errno.h> | |
22 | #include <string.h> | |
23 | #include <stdlib.h> | |
24 | ||
adc6ff7f RM |
25 | /* These symbols are defined by the including source file: |
26 | ||
27 | ENTNAME -- database name of the structure and functions (hostent, pwent). | |
28 | STRUCTURE -- struct name, define only if not ENTNAME (passwd, group). | |
29 | DATABASE -- string of the database file's name ("hosts", "passwd"). | |
30 | ||
31 | ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store | |
32 | things pointed to by the resultant `struct STRUCTURE'. | |
33 | ||
34 | NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. | |
35 | ||
36 | Also see files-XXX.c. */ | |
5f0e6fc7 RM |
37 | |
38 | #define CONCAT(a,b) CONCAT1(a,b) | |
39 | #define CONCAT1(a,b) a##b | |
40 | ||
41 | #ifndef STRUCTURE | |
42 | #define STRUCTURE ENTNAME | |
43 | #endif | |
44 | ||
45 | ||
46 | struct parser_data | |
47 | { | |
3776d592 RM |
48 | #ifdef ENTDATA |
49 | struct ENTDATA entdata; | |
ffee1316 | 50 | #define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata; |
3776d592 RM |
51 | #else |
52 | #define ENTDATA_DECL(data) | |
53 | #endif | |
5f0e6fc7 RM |
54 | char linebuffer[0]; |
55 | }; | |
56 | ||
3776d592 RM |
57 | #ifdef ENTDATA |
58 | /* The function can't be exported, because the entdata structure | |
59 | is defined only in files-foo.c. */ | |
60 | #define parser_stclass static inline | |
61 | #else | |
62 | /* Export the line parser function so it can be used in nss_db. */ | |
63 | #define parser_stclass /* Global */ | |
64 | #define parse_line CONCAT(_nss_files_parse_,ENTNAME) | |
65 | #endif | |
66 | ||
96bda0ea RM |
67 | |
68 | #ifdef EXTERN_PARSER | |
69 | ||
70 | /* The parser is defined in a different module. */ | |
71 | extern int parse_line (char *line, struct STRUCTURE *result, | |
72 | struct parser_data *data, int datalen); | |
73 | ||
74 | #define LINE_PARSER(EOLSET, BODY) /* Do nothing */ | |
75 | ||
76 | #else | |
77 | ||
78 | /* Define a line parsing function. */ | |
79 | ||
ffee1316 | 80 | #define LINE_PARSER(EOLSET, BODY) \ |
3776d592 | 81 | parser_stclass int \ |
5f0e6fc7 RM |
82 | parse_line (char *line, struct STRUCTURE *result, \ |
83 | struct parser_data *data, int datalen) \ | |
84 | { \ | |
ffee1316 RM |
85 | ENTDATA_DECL (data) \ |
86 | char *p = strpbrk (line, EOLSET "\n"); \ | |
87 | if (p) \ | |
88 | *p = '\0'; \ | |
5f0e6fc7 RM |
89 | BODY; \ |
90 | TRAILING_LIST_PARSER; \ | |
91 | return 1; \ | |
92 | } | |
93 | ||
94 | ||
5f0e6fc7 RM |
95 | #define STRING_FIELD(variable, terminator_p, swallow) \ |
96 | { \ | |
97 | variable = line; \ | |
adc6ff7f | 98 | while (*line != '\0' && !terminator_p (*line)) \ |
5f0e6fc7 | 99 | ++line; \ |
adc6ff7f RM |
100 | if (*line != '\0') \ |
101 | { \ | |
102 | *line = '\0'; \ | |
103 | do \ | |
104 | ++line; \ | |
105 | while (swallow && terminator_p (*line)); \ | |
106 | } \ | |
5f0e6fc7 RM |
107 | } |
108 | ||
109 | #define INT_FIELD(variable, terminator_p, swallow, base, convert) \ | |
110 | { \ | |
111 | char *endp; \ | |
112 | variable = convert (strtol (line, &endp, base)); \ | |
113 | if (endp == line) \ | |
114 | return 0; \ | |
115 | else if (terminator_p (*endp)) \ | |
116 | do \ | |
117 | ++endp; \ | |
118 | while (swallow && terminator_p (*endp)); \ | |
119 | else if (*endp != '\0') \ | |
120 | return 0; \ | |
121 | line = endp; \ | |
122 | } | |
123 | ||
569c558c UD |
124 | #define INT_FIELD_MAYBE_NULL(variable, terminator_p, swallow, base, convert, default) \ |
125 | { \ | |
126 | char *endp; \ | |
127 | if (*line == '\0') \ | |
128 | /* We expect some more input, so don't allow the string to end here. */ \ | |
129 | return 0; \ | |
130 | variable = convert (strtol (line, &endp, base)); \ | |
131 | if (endp == line) \ | |
132 | variable = default; \ | |
133 | if (terminator_p (*endp)) \ | |
134 | do \ | |
135 | ++endp; \ | |
136 | while (swallow && terminator_p (*endp)); \ | |
137 | else if (*endp != '\0') \ | |
138 | return 0; \ | |
139 | line = endp; \ | |
140 | } | |
141 | ||
5f0e6fc7 RM |
142 | #define ISCOLON(c) ((c) == ':') |
143 | ||
144 | ||
145 | #ifndef TRAILING_LIST_MEMBER | |
146 | #define TRAILING_LIST_PARSER /* Nothing to do. */ | |
147 | #else | |
148 | ||
149 | #define TRAILING_LIST_PARSER \ | |
150 | { \ | |
151 | char **list = parse_list (line, data, datalen); \ | |
152 | if (list) \ | |
153 | result->TRAILING_LIST_MEMBER = list; \ | |
154 | else \ | |
155 | return 0; \ | |
156 | } | |
157 | ||
158 | static inline char ** | |
159 | parse_list (char *line, struct parser_data *data, int datalen) | |
160 | { | |
161 | char *eol, **list, **p; | |
162 | ||
dbe31b9a RM |
163 | if (line >= data->linebuffer && line < (char *) data + datalen) |
164 | /* Find the end of the line buffer, we will use the space in DATA after | |
165 | it for storing the vector of pointers. */ | |
166 | eol = strchr (line, '\0') + 1; | |
167 | else | |
168 | /* LINE does not point within DATA->linebuffer, so that space is | |
169 | not being used for scratch space right now. We can use all of | |
170 | it for the pointer vector storage. */ | |
171 | eol = data->linebuffer; | |
5f0e6fc7 | 172 | /* Adjust the pointer so it is aligned for storing pointers. */ |
3776d592 RM |
173 | eol += __alignof__ (char *) - 1; |
174 | eol -= (eol - (char *) 0) % __alignof__ (char *); | |
5f0e6fc7 RM |
175 | /* We will start the storage here for the vector of pointers. */ |
176 | list = (char **) eol; | |
177 | ||
178 | p = list; | |
179 | while (1) | |
180 | { | |
181 | char *elt; | |
182 | ||
183 | if ((char *) &p[1] - (char *) data > datalen) | |
184 | { | |
185 | /* We cannot fit another pointer in the buffer. */ | |
c4029823 | 186 | __set_errno (ERANGE); |
5f0e6fc7 RM |
187 | return NULL; |
188 | } | |
189 | if (*line == '\0') | |
190 | break; | |
191 | ||
192 | elt = line; | |
193 | while (1) | |
194 | { | |
195 | if (TRAILING_LIST_SEPARATOR_P (*line)) | |
196 | { | |
197 | *p++ = elt; | |
198 | *line = '\0'; | |
199 | do | |
200 | ++line; | |
201 | while (TRAILING_LIST_SEPARATOR_P (*line)); | |
c66273aa | 202 | elt = line; |
5f0e6fc7 RM |
203 | } |
204 | else if (*line == '\0' || *line == '\n') | |
205 | { | |
206 | /* End of the line. */ | |
207 | if (line > elt) | |
208 | /* Last element. */ | |
209 | *p++ = elt; | |
210 | *line = '\0'; | |
211 | break; | |
212 | } | |
213 | else | |
214 | ++line; | |
215 | } | |
216 | } | |
217 | *p = NULL; | |
218 | ||
219 | return list; | |
220 | } | |
221 | ||
11336c16 | 222 | #endif /* TRAILING_LIST_MEMBER */ |
96bda0ea RM |
223 | #endif /* EXTERN_PARSER */ |
224 | ||
225 | ||
5f0e6fc7 RM |
226 | #define LOOKUP_NAME(nameelt, aliaselt) \ |
227 | { \ | |
228 | char **ap; \ | |
229 | if (! strcmp (name, result->nameelt)) \ | |
230 | break; \ | |
231 | for (ap = result->aliaselt; *ap; ++ap) \ | |
232 | if (! strcmp (name, *ap)) \ | |
233 | break; \ | |
234 | if (*ap) \ | |
235 | break; \ | |
236 | } | |
237 | ||
96bda0ea RM |
238 | |
239 | /* This is defined by db-*.c to include "../nss_db/db-XXX.c" instead. */ | |
240 | #ifndef GENERIC | |
241 | #define GENERIC "files-XXX.c" | |
242 | #endif |